【折腾心得】OpenWrt + PassWall + 双 AdGuardHome DNS 分流去广告配置记录

这篇是一次 OpenWrt DNS 折腾记录,场景比较具体:京东云雅典娜 AX6600 上跑 OpenWrt,用 PassWall 保留国内外分流,再接两套 AdGuardHome 分别处理国内和国外 DNS。

本文记录本次在京东云雅典娜 AX6600 OpenWrt 路由器上,配置 PassWall 配合双 AdGuardHome 实现国内外 DNS 分流去广告的完整过程、正确配置、踩坑原因和相关知识点。

1. 目标

本次目标是:

  • 在 OpenWrt 中接入 AdGuardHome 做 DNS 广告过滤。
  • 保留 PassWall 现有国内外分流能力。
  • 使用两个 AdGuardHome 分别处理国内和国外 DNS 分支:
    • 本地 OpenWrt 服务版 AdGuardHome:处理国内域名广告过滤。
    • Docker 版 AdGuardHome:处理国外域名广告过滤。
  • 避免 DNS 环路、端口冲突、防火墙转发问题。
  • 形成一套以后重装软路由可复用的配置流程。

最终目标链路:

客户端
  -> 路由器 10.0.0.1:53
  -> PassWall DNS 重定向
  -> PassWall dnsmasq:11400
  -> chinadns-ng
      ├─ 国内域名 -> 本地 AGH:127.0.0.1:5333 -> 国内 DNS
      └─ 国外域名 -> Docker AGH:127.0.0.1:5336 -> tls://1.1.1.1:853

2. 当前环境关键点

设备和系统:

设备:JDCloud RE-CS-02 / 京东云雅典娜 AX6600
系统:Kwrt 25.12-SNAPSHOT
内核:6.12.62
LAN 地址:10.0.0.1/24
上游网络:海南大学校园网 WiFi

原始 DNS 相关服务:

主 dnsmasq:10.0.0.1:53
PassWall dnsmasq:11400
chinadns-ng:15355 / 15353,具体端口由 PassWall 模式生成
本地 AdGuardHome:127.0.0.1:5333
Docker AdGuardHome:127.0.0.1:5336

Docker 数据目录:

Docker Root Dir:/opt/docker
国外 AGH 数据目录:/opt/agh-foreign

3. 正确配置流程

3.1 配置本地 AdGuardHome 处理国内分支

本地 AGH 是 OpenWrt 服务,不是 Docker 容器。

关键配置:

WebUI:10.0.0.1:3000
DNS:127.0.0.1:5333
重定向:无

本地 AGH 上游建议:

210.37.40.4
210.37.40.5
119.29.29.29
223.5.5.5

不要在国内 AGH 中混入国外 DoH 或国外公共 DNS,例如:

https://dns10.quad9.net/dns-query
https://dns.google/dns-query
1.1.1.1
8.8.8.8

原因:

本地 AGH 负责国内分支,应优先稳定、低延迟、直连。
国外 DNS 或 DoH 容易导致超时、污染或路径变复杂。

PassWall 中设置:

DNS 分流:ChinaDNS-NG
直连 DNS:127.0.0.1:5333
直连 DNS 请求协议:通过 TCP 请求 DNS
远程 DNS:先保持 1.1.1.1,等 Docker AGH 稳定后再改
DNS 重定向:开启

国内链路:

国内域名
  -> chinadns-ng
  -> 本地 AGH:5333
  -> 国内 DNS
  -> 返回国内 IP

3.2 部署 Docker 版 AdGuardHome 处理国外分支

创建目录:

mkdir -p /opt/agh-foreign/work /opt/agh-foreign/conf

推荐容器启动命令:

docker run -d \
  --name adguardhome \
  -v /opt/agh-foreign/work:/opt/adguardhome/work \
  -v /opt/agh-foreign/conf:/opt/adguardhome/conf \
  -p 3001:3000 \
  -p 5336:5336/tcp \
  -p 5336:5336/udp \
  --restart always \
  adguard/adguardhome

初始化页面填写:

网页管理界面:
监听接口:所有接口
端口:3000

DNS 服务器:
监听接口:所有接口
端口:5336

这个配置的对应关系:

宿主机 3001 -> 容器 3000
宿主机 5336/tcp -> 容器 5336/tcp
宿主机 5336/udp -> 容器 5336/udp

访问 Docker AGH:

http://10.0.0.1:3001

3.3 配置 Docker AGH 上游 DNS

国外 AGH 上游建议使用 DoT,避免 DNS 53 端口环路:

tls://1.1.1.1
tls://1.0.0.1

Bootstrap DNS 可以填:

210.37.40.4 //这是海南大学DHCP服务器下放的DNS服务器解析地址
210.37.40.5 //这是海南大学DHCP服务器下放的DNS服务器解析地址

Fallback DNS 留空。

不要混用这些上游:

1.1.1.1
8.8.8.8
tcp://1.1.1.1
tcp://8.8.8.8
https://cloudflare-dns.com/dns-query
https://dns.google/dns-query

原因:

  • 裸 IP 默认走普通 DNS 53,被 PassWall DNS 重定向抓回。
  • tcp://1.1.1.1 仍然是 53 端口,触发环路。
  • 域名 DoH 需要先解析 DoH 服务器域名,链路更复杂。
  • tls://1.1.1.1 走 853 端口,不会被 PassWall 的 DNS 重定向规则抓回 11400。

3.4 添加 LAN 到 Docker 的防火墙转发

电脑从 LAN 访问 Docker 容器映射端口时(你看ADH的配置页需要访问docker内部的ADH),NAT 会把目标改为 Docker 网桥地址,例如:

10.0.0.1:3001 -> 172.17.0.2:3000

这时包需要从:

br-lan -> docker0

OpenWrt 默认只有:

lan -> wan
docker -> wan

缺少:

lan -> docker

所以需要添加规则。

修改前备份:

cp -a /etc/config/firewall /etc/config/firewall.bak.$(date +%Y%m%d%H%M%S)

添加规则:

uci -q delete firewall.lan_to_docker
uci set firewall.lan_to_docker='forwarding'
uci set firewall.lan_to_docker.src='lan'
uci set firewall.lan_to_docker.dest='docker'
uci commit firewall
/etc/init.d/firewall reload

验证:

uci show firewall.lan_to_docker
nft list chain inet fw4 forward_lan

预期看到:

firewall.lan_to_docker=forwarding
firewall.lan_to_docker.src='lan'
firewall.lan_to_docker.dest='docker'

以及:

jump accept_to_docker comment "!fw4: Accept lan to docker forwarding"

3.5 最后接入 PassWall 远程 DNS

确认 Docker AGH 单独稳定:

nslookup youtube.com 127.0.0.1:5336
nslookup google.com 127.0.0.1:5336
docker logs adguardhome --tail 50

确认无大量 timeout 后,再进入 PassWall:

PassWall -> 基本设置 -> DNS

设置:

DNS 分流:ChinaDNS-NG
直连 DNS:127.0.0.1:5333
直连 DNS 请求协议:通过 TCP 请求 DNS

远程 DNS:127.0.0.1:5336
过滤模式:通过 TCP 请求 DNS

默认 DNS:远程 DNS
DNS 重定向:开启

最终国外链路:

国外域名
  -> PassWall dnsmasq:11400
  -> chinadns-ng
  -> Docker AGH:127.0.0.1:5336
  -> tls://1.1.1.1:853
  -> 返回国外 IP
  -> PassWall 按规则代理连接

4. 本次踩坑和原因

4.1 误以为 Docker 映射 3001:3000 一定长期有效

AGH 初始化时 WebUI 默认监听 3000,但初始化页面可以把正式 Web 端口改成 80

如果 Docker 映射是:

3001 -> 3000

但初始化后 AGH 改成监听容器内 80,外部访问 3001 就会失效。

解决:

  • 如果 Docker 映射 3001:3000,初始化页面 Web 端口就必须填 3000
  • 如果初始化页面 Web 端口填 80,Docker 映射就必须是 3001:80

4.2 只映射 TCP,没有映射 UDP

错误示例:

-p 5336:5336

这通常只映射 TCP。

DNS 需要同时支持 UDP 和 TCP:

-p 5336:5336/tcp
-p 5336:5336/udp

4.3 LAN 访问 Docker 映射端口失败

现象:

路由器本机 curl http://10.0.0.1:3001 成功
电脑访问 http://10.0.0.1:3001 显示拒绝连接或超时

原因:

路由器本机访问走 INPUT/本机路径。
电脑访问会被 Docker DNAT 到 172.17.0.2,需要 br-lan -> docker0 转发。
OpenWrt fw4 里缺少 lan -> docker forwarding。

解决:

uci set firewall.lan_to_docker='forwarding'
uci set firewall.lan_to_docker.src='lan'
uci set firewall.lan_to_docker.dest='docker'
uci commit firewall
/etc/init.d/firewall reload

4.4 Docker AGH 上游使用 1.1.1.1:53 造成 DNS 环路

错误链路:

PassWall 远程 DNS
  -> Docker AGH:5336
  -> 1.1.1.1:53
  -> 被 PassWall DNS 重定向抓回 11400
  -> chinadns-ng
  -> PassWall 远程 DNS
  -> Docker AGH:5336
  -> 无限循环

原因:

PassWall 的 DNS 重定向规则会抓:

udp dport 53 -> redirect to :11400
tcp dport 53 -> redirect to :11400

所以 Docker AGH 再去访问 1.1.1.1:53 时,会被重新拉回 PassWall DNS 入口,形成环路。

解决:

Docker AGH 上游改为 tls://1.1.1.1

即走 DNS-over-TLS 的 853 端口。

4.5 DoH 域名上游不稳定

曾尝试:

https://cloudflare-dns.com/dns-query
https://dns.google/dns-query

日志出现:

failed to init http client: timeout exceeded
Client.Timeout exceeded while awaiting headers

原因:

  • DoH 域名上游需要先解析 cloudflare-dns.comdns.google
  • 解析上游域名又依赖 Bootstrap DNS。
  • 在校园网 + PassWall + Docker bridge 环境下,链路复杂且容易超时。

解决:

优先使用 IP 形式的 DoT:tls://1.1.1.1

4.6 Bootstrap DNS 不等于普通查询上游

Bootstrap DNS 的作用:

当上游是域名时,用来解析这个上游服务器的 IP。

例如:

https://dns.google/dns-query

AGH 需要先知道 dns.google 的 IP,这时才用 Bootstrap DNS。

如果上游是:

tls://1.1.1.1

则不需要解析上游服务器域名,Bootstrap 基本不参与普通网站解析。

5. 值得记录的知识点

5.1 上游 DNS 是相对概念

上游 DNS 指的是:

当前 DNS 程序自己答不出来时,把请求转发给谁。

例如:

客户端的上游 DNS = 路由器 10.0.0.1
PassWall dnsmasq 的上游 = chinadns-ng
chinadns-ng 的国内上游 = 本地 AGH
chinadns-ng 的国外上游 = Docker AGH
Docker AGH 的上游 = tls://1.1.1.1

5.2 0.0.0.0 的含义

0.0.0.0 表示监听所有接口。

在容器内部:

0.0.0.0:3000

表示容器内所有网卡都监听 3000。

外部是否能访问,由 Docker 端口映射和 OpenWrt 防火墙决定。

5.3 tls://1.1.1.1 的含义

tls:// 表示 DNS-over-TLS,简称 DoT。

tls://1.1.1.1

等价于:

用 TLS 加密连接 1.1.1.1:853,并在加密连接里进行 DNS 查询。

它的特点:

  • 不走 53 端口。
  • DNS 查询内容加密。
  • 校园网仍然能看到你连接了 1.1.1.1:853
  • 校园网看不到具体查询了 youtube.com 还是 google.com

5.4 DNS 加密不等于完全隐身

使用 DoT 后,校园网仍然可以看到:

你的路由器连接了 1.1.1.1:853(但是passwall应该代理了连接,走的是加密)
连接时间
流量大小

校园网看不到:

具体 DNS 查询内容
DNS 返回记录

5.5 双 AGH 的意义

单 AGH:

先过滤,再交给 PassWall 分流

双 AGH:

PassWall 先分流
国内域名 -> 国内 AGH
国外域名 -> 国外 AGH

双 AGH 的价值:

  • 国内外规则分开。
  • 国内外上游 DNS 分开。
  • 日志更容易区分。
  • 国内 DNS 不走国外,国外 DNS 不走国内。

代价:

  • 链路复杂。
  • 更容易产生环路。
  • Docker、fw4、PassWall DNS 重定向都要配合正确。

6. 推荐最终配置摘要

本地 AGH:

WebUI:10.0.0.1:3000
DNS:127.0.0.1:5333
上游:210.37.40.4 / 210.37.40.5 / 119.29.29.29 / 223.5.5.5
重定向:无

Docker AGH:

WebUI:10.0.0.1:3001
DNS:127.0.0.1:5336
上游:tls://1.1.1.1 / tls://1.0.0.1
Bootstrap:210.37.40.4 / 210.37.40.5

Docker run:

docker run -d \
  --name adguardhome \
  -v /opt/agh-foreign/work:/opt/adguardhome/work \
  -v /opt/agh-foreign/conf:/opt/adguardhome/conf \
  -p 3001:3000 \
  -p 5336:5336/tcp \
  -p 5336:5336/udp \
  --restart always \
  adguard/adguardhome

PassWall:

DNS 分流:ChinaDNS-NG
直连 DNS:127.0.0.1:5333
直连 DNS 请求协议:通过 TCP 请求 DNS
远程 DNS:127.0.0.1:5336
过滤模式:通过 TCP 请求 DNS
默认 DNS:远程 DNS
DNS 重定向:开启

防火墙:

lan -> docker forwarding 必须存在

验证命令:

nslookup baidu.com 127.0.0.1:5333
nslookup youtube.com 127.0.0.1:5336
nslookup youtube.com 127.0.0.1:11400
nft list chain inet fw4 forward_lan
docker logs adguardhome --tail 50

7. 故障排查速查

电脑打不开 Docker AGH WebUI:

检查 docker ps 端口映射
检查是否缺 lan -> docker forwarding
检查初始化后 Web 端口是否和 Docker 映射一致

国外网站打不开:

先把 PassWall 远程 DNS 改回 1.1.1.1 恢复通信
单独测试 nslookup youtube.com 127.0.0.1:5336
查看 docker logs adguardhome 是否有 timeout
确认 Docker AGH 上游不要走 53

AGH 日志出现 UDP timeout:

说明上游用了裸 IP 普通 DNS,例如 1.1.1.1
改为 tls://1.1.1.1

AGH 日志出现 failed to init http client:

说明 DoH HTTP 客户端初始化超时
优先避免域名 DoH,上游改为 IP DoT

防火墙 reload 出现 PassWall include 警告:

不一定表示 lan_to_docker 失败
用 nft list chain inet fw4 forward_lan 验证最终规则
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇