OpenWrt + AdGuard Home + Tailscale Exit Node:2026 年 1 月的去广告部署记录
这是一篇 2026 年 1 月的历史部署记录。文中描述的拓扑、设备分工和配置只反映当时的状态,当前的网络结构可能已经有变化,内容不保证仍然适用。
这是 AdGuard Home 去广告的第三次尝试。前两次分别是手动 DNS 的旁路由和路由器全包但放弃,都单独写过。这篇只记录第三次为什么改成“OpenWrt 管控制面、PC 管数据面、Tailscale 管连接”这个分工。
前两次尝试之后,需求收敛成两条:
- 尽量覆盖手头的几台设备,包括偶尔漫游在外的手机和笔记本
- 不想在每台设备上手动设 DNS
于是把职责拆开:
- OpenWrt 路由器:负责 DNS 过滤和 DHCP
- Windows PC:负责流量转发和加密解密(当时那台路由器 CPU 扛不住这个)
- Tailscale:负责组网,让外出的设备也能用上家里的 DNS
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. 用 PC 的 CPU 扛流量加密/解密转发,当时那台路由器扛不住这个。 3. 7x24 小时在线(设置了不睡眠)。 |
| MacBook/Phone | macOS / Android | 客户端 | 通过 Tailscale 接入,在内网和外网都走家里的 AdGuard Home。 |
场景流量分析
这部分容易产生误解:不同的连接模式下,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。
AdGuard Home 的安装方式和上游 DoH 配置与第一次尝试相同,见手动 DNS 的旁路由,此处不重复。
步骤 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。前提是路由器和客户端都已加入 Tailnet,路由器端的 Tailscale 安装与登录此处从略。
步骤 1:配置 Global Nameservers
登录 Tailscale Admin Console,进入 DNS 页面:
Global Nameservers: 添加路由器的 Tailscale IP(当时记为 100.x.y.4)。
Override local DNS: 当时开启了这一项。
当时的观察:开启后,远程设备的系统会忽略当前的本地 DNS(如 4G 网络的 DNS),把解析请求塞进 Tailscale 隧道,发往家里的 100.x.y.4。这个行为只在当时的客户端组合上验证过,不同系统版本的表现可能不同。
步骤 2:配置出口 (Windows)
那台路由器内存只有 512MB,担心处理加密转发会 OOM(内存溢出),于是把转发这摊活交给了 Windows PC。
Windows 端:安装 Tailscale,在菜单中开启 Run as exit node。
Console 端:在 Admin Console 的 Machines 列表中,找到 Windows 设备,点击 Edit route settings,勾选 Use as exit node。
电源设置:把 Windows 的“睡眠”设置为“从不”,并关闭了“合盖休眠”。
4. 验证与回滚
改 DNS 配置有断网风险,所以准备了回滚步骤。
验证步骤
去广告验证:在 MacBook(连接外网热点 + Tailscale)的终端执行:
nslookup doubleclick.net
返回 0.0.0.0,说明这条查询路径走到了 AdGuard Home,并被拦截规则命中。
流量路径验证:访问 ip.sb,显示的是家庭宽带的公网 IP,说明业务流量经 Exit Node 从家里的宽带出口出去了。这个测试只能支持这一个结论,无法据此判断隧道是否走了直连。
紧急回滚
场景 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 可能会断连。
预防:在远程设备上保留记录路由器的 Tailscale IP 或 DDNS 的 IP 地址。SSH 连接时直接使用 IP,不依赖域名。
ssh root@100.x.y.4
场景 C:彻底断网,需要下载修复包
临时自救:手动将电脑或手机的 DNS 设置为 223.5.5.5 或 8.8.8.8,绕过 Tailscale 和路由器 DNS,恢复基础上网能力。
5. 遇到的问题与排查
以下三条都是当时在特定设备和客户端组合上的观察,不保证适用于其他环境。
1. local_ptr_upstreams 导致的解析死循环
现象:AGH 日志里大量报 connection reset,CPU 占用飙升。
排查:AGH 开启了“使用私人反向 DNS”(对应配置键 local_ptr_upstreams),并指向了 127.0.0.1:5300 (dnsmasq)。请求链条变成了 AGH -> dnsmasq -> 系统 DNS -> Tailscale DNS -> AGH,形成循环。
处理:关闭了 AGH 的“使用私人反向 DNS”功能。
2. Windows Exit Node 下客户端来源归一化
现象:在 AGH 日志里观察到,所有远程设备的 DNS 请求来源 IP 都显示为 ThinkBook 的 Tailscale IP (100.x.y.10)。
推测:与那台 Windows 上 Tailscale 的用户态 NAT 转发有关。
影响:无法区分请求是 iPhone 还是 Mac 发起的,但不影响拦截效果,接受了这个妥协。其他平台或其他版本的 Exit Node 未必是这个表现。
3. Android “私人 DNS” 导致的绕过
现象:一台 Android 手机上广告没拦住,AGH 后台也没有查询记录。
排查:那台手机在系统设置中开启了“私人 DNS (Private DNS)”,在它的系统版本上优先级高于 Tailscale 下发的 DNS。
处理:进入那台手机的网络设置,关闭了私人 DNS。不同 Android 版本和厂商的行为可能不同。
小结
这次架构的取舍在于分工:流量转发(计算密集)交给 PC,DNS 解析(IO 密集)留在路由器。在那台 512MB 内存的路由器上,这样就不用让它扛加密流量,外出的设备通过 Tailscale 也能用上家里的 AdGuard Home。这只是 2026 年 1 月的一个快照,后续拓扑如有调整会另行记录。