AdguardHome 和 Clash 透明代理配合使用

2 mins to read

image-20210417112325830

配置

我的方案如上图是 Adguard 作为 Clash 的上游 DNS。然后将路由的 DHCP 配置的 DNS 服务器改为 Clash 的 DNS 地址即可。

首先启动 Adguard:

docker run -d \
--name adguard \
--restart unless-stopped \
--log-opt max-size=1m \
-v /root/adguard/work:/opt/adguardhome/work \
-v /root/adguard/conf:/opt/adguardhome/conf \
-p 5656:53/tcp \
-p 5656:53/udp \
-p 3000:3000 \
-p 3001:80 \
adguard/adguardhome

然后 Clash 配置入口 DNS 为 5353 端口,然后设置 nameserver 上游 DNS 为 Adguard 地址。

dns:
  enable: true
  listen: "0.0.0.0:5353"
  ipv6: false
  nameserver:
    - "127.0.0.1:5656"

然后使用 iptables 将 53 端口流量转发到实际的 5353 端口:

iptables -t nat -I PREROUTING -p udp --dport 53 -j REDIRECT --to 5353

部分发行版 53 端口可能已被 systemd-resolved 占用,先改掉:

vi /etc/systemd/resolved.conf

DNSStubListener=no  #取消注释,把yes改为no

问题

但是发现 Clash 的 DNS 查询全部超时失败了,直接使用 AdguardHome 的 DNS 查询也超时。排查日志发现:

  1. Clash 代理流量需要连接代理服务器,我的代理服务器配置的是域名,然后 DNS 查询这个代理服务器的域名失败了
  2. AdguardHome 连接 DOT/DOH DNS 查询时连接失败

想了很久没有想出原因,后来尝试进入 AdguardHome 容器使用 nc 连接 IP 调试:

nc 1.2.3.4 80

# 然后在 clash 日志则出现连接日志
time="2020-11-01T05:59:39Z" level=info msg="[TCP] 172.17.0.3:38804 --> 1.2.3.4 match GeoIP(CN) using Domestic[DIRECT]"

由于我这台旁路由配置了透明代理(详细见Docker Clash 和 透明代理),使用iptables 规则接管了全部网络流量,导致 AdguardHome 容器也走了代理流量,但 Clash 代理服务器的域名解析又依赖 AdguardHome DNS才能初始化代理。解决方案是:

iptables -t nat -I PREROUTING -p udp --dport 53 -d 192.168.0.0/16 ! -i docker0 -j REDIRECT --to 5353 # 只有局域网流量以及非 docker0 网卡的流量才重定向 53 端口

# 流量转发排除 docker0 网卡,即旁路由的所有 docker 容器都不再经过 clash
iptables -t nat -A PREROUTING -p tcp ! -i docker0 -j CLASH
iptables -t mangle -A PREROUTING -p udp ! -i docker0 -j CLASH
iptables -t nat -I CLASH -i docker0 -j RETURN
iptables -t mangle -I CLASH -i docker0 -j RETURN

使用效果

当然只用 Clash 也可以做到去污染、去广告等效果,但配置比 Adguard 麻烦且应用配置需重启服务。以下是 Adguard 使用效果。

image-20210417110255625