基于 OpenWrt、AdGuard Home 与 Tailscale 构建全网去广告方案:架构设计与避坑指南
Table of Contents
- 背景:之前的两次尝试
- 这次方案的目标
- 1. 角色定义与流量拓扑
- 设备清单与角色分配
- 场景流量分析
- 2. 实施阶段一:局域网 DNS 接管 (OpenWrt)
- 步骤 1:迁移 dnsmasq 并部署 AGH
- 步骤 2:配置 DHCP 下发 DNS (关键)
- 3. 实施阶段二:全网覆盖 (Tailscale)
- 步骤 1:配置 Global Nameservers
- 步骤 2:配置高性能出口 (Windows)
- 4. 验证与回滚 (Disaster Recovery)
- 验证步骤
- 紧急回滚与救砖
- 5. 常见问题排查 (Troubleshooting)
- 1. local_ptr_upstreams 导致的解析死循环
- 2. Windows Exit Node 导致的“客户端归一化”
- 3. Android “私人 DNS” 导致的泄漏
- 总结
这篇文章记录的是一次家庭网络架构的重构实践,也是我在 AdGuard Home 去广告这条路上的第三次迭代。
目标非常明确:利用家庭局域网中部署的 AdGuard Home,实现对所有设备(包括家中的 PC/IoT 设备,以及漫游在外的 MacBook、手机)的统一广告拦截和隐私保护。同时,通过合理的“控制与数据分离”,解决老旧路由器的性能瓶颈,确保在启用加密隧道(Tailscale)时,依然保持千兆级的网络体验。
背景:之前的两次尝试
在之前的文章中,我尝试过两种方案:
-
旁路由 + 手动DNS方案(详见这篇文章)
- 在 OpenWrt 旁路由上运行 AdGuard Home
- 每个设备需要手动设置 DNS 指向旁路由
- 局限性:只能在局域网内生效,出门在外无法享受去广告
-
路由器全包方案的尝试与放弃(详见这篇文章)
- 尝试在路由器上同时运行 AdGuard Home + IPv6 relay
- 问题:路由器内存和存储空间吃紧,配置复杂度高
- 结果:最终退回到简单方案
这次方案的目标
经过前两次的踩坑,我意识到:
- 需求 1:全网覆盖——无论在家里还是外面,所有设备都能享受去广告
- 需求 2:自动化配置——不想在每个设备上手动设置 DNS
于是,这次方案的核心思路变成了:职责分离。
- OpenWrt 路由器:负责”控制”(DNS 过滤、DHCP)
- 高性能 Windows PC:负责”数据”(流量转发、加密解密)
- Tailscale:负责”连接”(组网、全球访问)
这种架构的好处是:既能发挥老旧硬件的剩余价值,又能保证千兆级的网络体验。
1. 角色定义与流量拓扑
在开始配置之前,必须厘清网络中各设备的“角色”以及数据流向。这是避免配置混乱的关键。
设备清单与角色分配
| 设备名称 | 硬件/环境 | 角色 | 职责 |
|---|---|---|---|
| AE86Wrt | OpenWrt 路由器 (512MB RAM) | 控制核心 (DNS & DHCP) | 1. 运行 AdGuard Home (AGH) 进行 DNS 过滤。 2. 运行 Tailscale (非 Exit Node) 作为内网入口。 3. 负责 DHCP 地址分配。 |
| ThinkBook | Windows PC (i7 CPU) | 数据核心 (Exit Node) | 1. 运行 Tailscale Exit Node。 2. 利用高性能 CPU 处理繁重的流量加密/解密转发。 3. 7x24小时在线(设置不睡眠)。 |
| MacBook/Phone | macOS / Android | 客户端 | 无论在内网还是外网,均通过 Tailscale 接入网络,享受去广告服务。 |
场景流量分析
这是最容易产生误解的部分:不同的连接模式下,DNS 和业务流量走的路径是完全不同的。
场景 A:局域网内设备 (LAN Clients)
- IP 获取:通过路由器 DHCP 获取内网 IP (
192.168.2.x)。 - DNS 流量:DHCP 下发 DNS 指向路由器 IP -> AdGuard Home -> 上游 DoH。
- 业务流量:直接通过路由器网关访问互联网(不经过 Tailscale)。
场景 B:远程设备 - 仅组网 (No Exit Node)
- 连接方式:Tailscale 在线,未开启 Exit Node。
- DNS 流量:Tailscale 拦截 DNS 请求 -> 隧道 -> 路由器 AdGuard Home。
- 业务流量:直接走设备当前的物理网络(如 4G/咖啡厅 Wi-Fi)访问互联网。
- 适用场景:仅需要去广告,或访问家庭内网 NAS 文件。
场景 C:远程设备 - 全流量代理 (With Exit Node)
- 连接方式:Tailscale 在线,Exit Node 选择 “ThinkBook”。
- DNS 流量:Tailscale 拦截 DNS 请求 -> 隧道 -> 路由器 AdGuard Home。
- 业务流量:隧道 -> ThinkBook (Windows) -> 解密转发 -> 互联网。
- 适用场景:需要家庭公网 IP 访问受限资源,或公共 Wi-Fi 环境下保护隐私。
2. 实施阶段一:局域网 DNS 接管 (OpenWrt)
首先确保局域网内的设备能用上 AdGuard Home。OpenWrt 默认使用 dnsmasq 监听 53 端口,我们需要进行端口置换。
步骤 1:迁移 dnsmasq 并部署 AGH
保留 dnsmasq 负责 DHCP,但将其 DNS 监听端口移走:
# 1. 修改 dnsmasq 监听端口为 5300
uci set dhcp.@dnsmasq[0].port='5300'
uci commit dhcp
/etc/init.d/dnsmasq restart
# 2. 部署 AdGuard Home
# 在 AdGuard Home 初始化向导中,将管理端口设为 3000,DNS 监听端口设为 53。
步骤 2:配置 DHCP 下发 DNS (关键)
仅仅修改监听端口是不够的,局域网客户端默认会把网关 (192.168.2.1) 当作 DNS。为了更稳健,我们通过 DHCP Option 6 明确告知客户端使用 AGH 的地址(通常就是路由器 LAN IP)。
在 OpenWrt 界面:网络 -> 接口 -> LAN -> DHCP 服务器 -> 高级设置 -> DHCP 选项。输入:
6,192.168.2.1
注:6 代表 DNS 服务器选项。这确保了设备连上 Wi-Fi 后,DNS 依然指向运行 AGH 的路由器。
3. 实施阶段二:全网覆盖 (Tailscale)
这一步将局域网的 DNS 能力扩展到全世界。
步骤 1:配置 Global Nameservers
登录 Tailscale Admin Console,进入 DNS 页面:
Global Nameservers: 添加路由器的 Tailscale IP(例如 100.100.1.4)。
Override local DNS: 必须开启。
原理:这会强制远程设备的 OS 忽略当前的本地 DNS(如 4G 网络的 DNS),强行将解析请求送入 Tailscale 隧道,发往家里的 100.100.1.4。
步骤 2:配置高性能出口 (Windows)
为了避免路由器因处理加密流量而 OOM (内存溢出),我们将“脏活累活”交给 Windows PC。
Windows 端: 安装 Tailscale,在菜单中开启 Run as exit node。
Console 端: 在 Admin Console 的 Machines 列表中,找到 Windows 设备,点击 Edit route settings,勾选 Use as exit node。
电源设置: 务必将 Windows 的“睡眠”设置为“从不”,并关闭“合盖休眠”。
4. 验证与回滚 (Disaster Recovery)
网络基础设施改造最怕“DNS 配崩 = 全家断网”。在应用上述配置前,请务必准备好“后悔药”。
验证步骤
去广告验证 (黑洞测试):在 MacBook (连接外网热点 + Tailscale) 终端执行:
nslookup doubleclick.net
如果返回 0.0.0.0 或 ::,说明 AdGuard Home 生效。
流量路径验证:访问 ip.sb。
如果显示家庭宽带 IP,说明 Exit Node 生效。
如果显示 ThinkBook 的局域网 IP (IPv6),说明内网穿透直连成功。
紧急回滚与救砖
场景 A:AdGuard Home 崩溃/无法启动
此时全家断网(无法解析域名)。
恢复方法:SSH 登录路由器,临时改回 dnsmasq 接管 53 端口。
# 停止 AGH (如果还在运行)
/etc/init.d/AdGuardHome stop
# 恢复 dnsmasq 端口
uci set dhcp.@dnsmasq[0].port='53'
uci commit dhcp
/etc/init.d/dnsmasq restart
场景 B:DNS 解析全挂,无法 SSH 回家
如果你人在外地,DNS 挂了导致无法解析域名,Tailscale 可能会断连。
预防:在远程设备上保留记录路由器的 直连 IP (Tailscale IP) 或 DDNS 的 IP 地址。SSH 连接时直接使用 IP,不依赖域名。
ssh root@100.100.1.4
场景 C:彻底断网,需要下载修复包
临时自救:手动将电脑/手机的 DNS 设置修改为 223.5.5.5 或 8.8.8.8,绕过 Tailscale/路由器 DNS,恢复基础上网能力。
5. 常见问题排查 (Troubleshooting)
1. local_ptr_upstreams 导致的解析死循环
现象:AGH 日志大量报错 connection reset,CPU 飙升。
原因:AGH 开启了“使用私人反向 DNS”,并指向了 127.0.0.1:5300 (dnsmasq)。请求链条变成了:AGH -> dnsmasq -> 系统DNS -> Tailscale DNS -> AGH,形成死循环。
解决:在 Tailscale 环境下,建议关闭 AGH 的“使用私人反向 DNS”功能,或谨慎配置上游。
2. Windows Exit Node 导致的“客户端归一化”
现象:在 AGH 日志里,所有远程设备的 DNS 请求来源 IP 都显示为 ThinkBook 的 IP (100.100.1.10)。
原因:Windows Tailscale 运行在用户态,通过 NAT 转发流量。
影响:无法区分是 iPhone 还是 Mac 发起的请求,但不影响拦截效果。这是为了性能妥协的结果。
3. Android “私人 DNS” 导致的泄漏
现象:Android 手机广告没拦住,AGH 后台没记录。
原因:Android 系统设置中开启了“私人 DNS (Private DNS)”,优先级高于 Tailscale。
解决:进入 Android 网络设置,关闭私人 DNS。
总结
通过将计算密集型的任务(流量转发)迁移到 PC,将 IO 密集型的任务(DNS 解析)留在路由器,我们成功构建了一个既具备高性能、又拥有全网去广告能力的家庭网络。这种“各司其职”的架构,对于压榨老旧硬件性能尤为有效。