OpenWrt 25 安装 AdGuardHome 接管 IPv4 / IPv6 DNS
搞了个新路由器 Tenda BE12 Pro,顺手把全屋 DNS 接到 AdGuardHome 上 —— 一处屏蔽,全屋去广告,顺带把那些"私自加点广告"的运营商 DNS 全甩开。本文记录在 OpenWrt 25 (snapshot) 上把 AGH 装好、让 dnsmasq 让位、IPv6 也走 AGH 的完整步骤。
设计原则:
- 改动最小:不重装 dnsmasq,不动 LAN/DHCP/网段,只调几个配置项
- 可逆:§0 做整套 UCI 备份,任何一步炸了能一键回滚
- 每步可验证:节末给一条
cmd → 期望输出,不过就回头查
§0 准备
环境(本文示例,你按自己实际改):
- 路由器:Tenda BE12 Pro
- 系统:OpenWrt 25 snapshot(包管理已切 apk)
上游运营商:日本软银 SoftBank(SB)宽带,入户 NTT 光猫
- IPv4 走 PPPoE 自己拨号(SB 的 IPoE / MAP-E 只认官方光猫,第三方路由器用不了)
- IPv6 由 NTT 光猫从 SB 拿原生前缀,SLAAC 透传给下游 —— 路由器走 wan6 + LAN relay,详见 §4.2
- LAN:
10.0.0.0/16,路由器10.0.0.1 - LAN IPv6:wan6 relay + LAN relay,客户端直接拿原生 GUA(
2400::xxx),不经路由器 NAT66
§1 刷 OpenWrt(略写)
Tenda BE12 Pro WiFi7
根据恩山的教程免拆机刷入 过渡固件 过渡固件再刷 openwrt
§2 安装 AdGuardHome
OpenWrt 25 snapshot 已收录官方 adguardhome 包,直接装。
2.1 装包
apk update
apk add adguardhome luci-app-adguardhome包关系:
adguardhome—— 二进制 + procd init(/etc/init.d/AdGuardHome)+ 默认/etc/adguardhome.yamlluci-app-adguardhome—— LuCI 上的 "AdGuard Home" 页面(状态、配置入口、日志)
验证:
which AdGuardHome
ls /etc/init.d/AdGuardHome
ls /etc/adguardhome.yaml || echo "首次启动后生成"2.2 首次启动(走 3000 端口的 Web UI)
启 AGH:
/etc/init.d/AdGuardHome enable
/etc/init.d/AdGuardHome start
sleep 2
netstat -tnlp 2>/dev/null | grep -E ':3000|AdGuard'
# 期望: 看到 AdGuardHome 监听 :3000浏览器打开 http://10.0.0.1:3000:
- 安装向导第一屏:管理界面 =
All interfaces / 端口 3000 - 第二屏:DNS 服务器 =
All interfaces / 端口 53(就算此时端口冲突也照填,§3 把 53 让出来后会自动 OK) - 设管理员账号 / 密码
- 完成
如果向导第二屏立刻报 53 被占,先填 5353 应付过去,§3 做完后回到设置改回 53。
2.3 配置 AGH 上游 DNS
AGH 主页 → 设置 → DNS 设置 → 上游 DNS 服务器(按需,推荐至少配 2 家做冗余):
https://dns10.quad9.net/dns-query
https://cloudflare-dns.com/dns-query
https://doh.pub/dns-query
https://dns.adguard-dns.com/dns-query
https://dns.google/dns-query并行模式选 "并行请求" 或 "快速",体验最好。
下面这三行先加上,留给 §3 用(让 .lan 域名 + 内网反查走 dnsmasq):
[/in-addr.arpa/]127.0.0.1:12353
[/ip6.arpa/]127.0.0.1:12353
[/lan/]127.0.0.1:12353[/lan/] 这种语法是 AGH 的"分域上游" —— 仅 .lan 后缀的查询走指定上游,其它走主上游。我们让 .lan 走 dnsmasq(下一节会把它搬到 12353),这样客户端 ping printer.lan / ssh nas.lan 这些内网域名照常解析。
过滤规则(广告列表)默认开了 "AdGuard DNS filter" 一条就够日常,愿意加可以再加 "Anti-AD"、"halflife list"、"EasyList China" 等。
保存。
§3 dnsmasq 让出 53 端口
目标:
- AGH 占 53,对外总入口
- dnsmasq 搬到 12353,只负责 DHCP + .lan 域名解析
- AGH 把 .lan / 内网反查转发给 127.0.0.1:12353(§2.3 已配)
3.1 改 dnsmasq 监听端口为 12353
LuCI:网络 → DHCP/DNS → 高级设置 → "DNS 服务器端口" 改成 12353
UCI:
uci set dhcp.@dnsmasq[0].port='12353'
uci commit dhcp
service dnsmasq restart验证:
netstat -unlp 2>/dev/null | grep ':12353'
# 期望: dnsmasq 监听 :12353
netstat -unlp 2>/dev/null | grep -E ':53 .* dnsmasq'
# 期望: 空(dnsmasq 不再占 53)3.2 关掉 DNS 重定向(fw4 强制劫持)
LuCI:网络 → DHCP/DNS → 常规设置 → 取消勾选 "DNS 重定向"(DNS Redirect)
UCI:
# OpenWrt / ImmortalWrt 都用这个字段, 字段名可能因版本不同稍异
uci set dhcp.@dnsmasq[0].dnsredirect='0'
uci commit dhcp
service firewall restart
service dnsmasq restart验证:
nft list ruleset | grep -E 'dport.*53.*(redirect|dnat)'
# 期望: 空 (没有任何把 53 端口 redirect / dnat 走的规则)为什么必须关:
OpenWrt(尤其 ImmortalWrt 等改版)默认开启 DNS 重定向 —— 在 fw4 层加一条规则,把客户端去往任何外部 53 端口的查询统统 DNAT 回本机 dnsmasq 监听端口。原本(dnsmasq 在 53)的设计意图是"客户端硬编码 8.8.8.8 也强制走本机 DNS,顺带挡运营商劫持"。
问题在 §3.1:dnsmasq 端口改成 12353 后,这条 fw4 规则跟着把 DNAT 目标改成 12353,直接把客户端流量塞给 dnsmasq:12353,完全绕开 AGH:53。结果是:
- 客户端 DNS =
10.0.0.1的查询 → 命中 fw4 规则 → DNAT 到 dnsmasq:12353 → 绕过 AGH ✗ - 客户端硬编码
8.8.8.8的查询 → 同上 → 绕过 AGH ✗
广告过滤、查询日志、过滤规则统统看不到流量,AGH 仪表盘空空如也。
关掉这条 fw4 规则后:
- 客户端 DNS =
10.0.0.1→ 直达本机 53 → AGH ✓ - 客户端硬编码
8.8.8.8→ 走外网,不进 AGH(也不再被劫持去 dnsmasq)
uci add firewall redirect
uci set firewall.@redirect[-1].name='Force-DNS-to-AGH'
uci set firewall.@redirect[-1].src='lan'
uci set firewall.@redirect[-1].proto='tcp udp'
uci set firewall.@redirect[-1].src_dport='53'
uci set firewall.@redirect[-1].dest_port='53' # AGH 监听的 53, 不是 12353
uci set firewall.@redirect[-1].target='DNAT'
uci commit firewall
service firewall restart代价:IoT / 公司 VPN / 部分游戏服务想用自己 DNS 时会失败。看个人取舍。
§4 IPv6 DNS:不需要单独接管(原理 + 防御 + 验证)
直觉上"全屋 DNS 接管"会让人想"v6 那边肯定也得专门搞一套吧" —— 不用。DNS 协议跟 IP 协议是解耦的,v4 一份 AGH 已经能解所有记录类型(A / AAAA / CNAME / ...)。本章先讲为啥不需要,然后讲本机 SB + NTT 环境的实测情况,再加一条防御性 fw4 规则挡掉硬编码绕过,最后验证。
真要给 LAN 客户端通告 v6 DNS 的(国内电信 / 联通有 PD 前缀的 server 模式场景,或纯 v6-only 客户端的特殊需求),看本文末尾的 附录 A。
4.1 为什么 v4 一个 AGH 够全屋用
关键认识:很多人下意识把"v6 DNS 服务器"理解为"解析 v6 地址的 DNS",其实不是 —— DNS 协议本身是载体无关的:
- 客户端用 v4 transport 问 AGH(
10.0.0.1)www.youtube.com的AAAA记录 - AGH 通过上游 DoH 拿到
2607:f8b0:... - AGH 用 v4 transport 把这个 v6 地址回给客户端
- 客户端拿到 v6 地址,直接走 v6 transport 连过去
全程没有任何"v6 DNS 服务器"参与,但 v6 访问完美工作。
不通告 v6 DNS 实际影响表:
| 场景 | 影响 |
|---|---|
| 客户端解析 AAAA 记录 | ✅ 不影响,AGH 照样返回 v6 地址 |
| 客户端通过 v6 访问网站 | ✅ 不影响,拿到 v6 地址就能连 |
| Happy Eyeballs 双栈选择 | ✅ 不影响,客户端早拿到 v4+v6 两个地址自己选 |
| 纯 v6-only 客户端(无 v4 stack) | ❌ 需要 v6 DNS,但家庭网几乎不存在 |
| 强制只用 v6 DNS 的 IoT | ❌ 罕见,真碰上单独配它 |
家用场景下,事实上不需要给 LAN 通告 v6 DNS。这能避开 odhcpd 在 relay 模式下 DNS 选项覆写的不确定性,配置最简,行为最可预测。
4.2 本机环境:SoftBank + NTT 光猫 + relay
为啥单开一节讲本机环境:典型的"没拿到 PD 前缀,只能 relay"场景,而且实测验证了 §4.1 的结论 —— 这种场景下 v6 DNS 已经事实上是空的,不用做任何动作。
- IPv4:SB 的 v4 走 IPoE 上的 MAP-E / DS-Lite —— 只有 SB 官方光猫 / 认证路由器能用。第三方路由器(本机 OpenWrt)只能退一步用 PPPoE 自己拨号(慢一点延迟高一点,但能用)。
- IPv6:NTT 光猫从 SB IPoE 拿到原生 v6 前缀(
2400::/29段),在自己 LAN 口下发 SLAAC + 无状态 DHCPv6(地址走 SLAAC,DNS 等附加项走 DHCPv6),但不下发 DHCPv6-PD(没把前缀切给下游)。OpenWrt 拿不到可分配子前缀,只能 relay 把光猫的 RA / DHCPv6 透传给 LAN。
想自己确认光猫下发模式,看ifstatus wan6的data段:有ipv6-prefix字段 = 有 PD,可以走 server / hybrid;只有passthru= 纯 SLAAC + 无状态 DHCPv6,只能 relay。
最终拓扑:
[SB IPoE 网络]
│ 光纤
▼
NTT 光猫 ──┐ v6 SLAAC + 光猫自己的 v4 网络
│
▼
OpenWrt(本机)
├── wan = PPPoE(自己拨, v4 出口)
└── wan6 = DHCPv6 客户端 → SLAAC 拿 GUA
│
▼
LAN(odhcpd 全 relay)
└── 客户端走 SLAAC 直接拿原生 GUA `2400:xxx::xxx`UCI(/etc/config/dhcp 里 LAN 部分):
config dhcp 'lan'
option interface 'lan'
option ra 'relay'
option dhcpv6 'relay'
option ndp 'relay'
option master '0'LuCI:网络 → 接口 → LAN → DHCP 服务器 → IPv6 设置,三个下拉全设 relay(中继)。
实测客户端 v6 DNS 状态(Windows 主机):
PS> Get-DnsClientServerAddress -AddressFamily IPv6 | ?{$_.InterfaceAlias -in '以太网','WLAN'}
InterfaceAlias ServerAddresses
-------------- ---------------
以太网 {}
WLAN {}物理网卡的 v6 DNS 列表是空的,因为:
- NTT 光猫 RA 里
M=0 / O=1,叫客户端用 DHCPv6 stateless 拿 DNS - OpenWrt odhcpd 在 relay 模式下转发 DHCPv6 INF-REQ 出去,但 reply 在 relay 链路上没能正确送回客户端
- 结果:客户端 v6 DNS 实际空 → 所有 DNS 自动走 v4 → 全部进 AGH
阴差阳错,这套环境已经处于"v4-only AGH 完美生效"状态,不用碰任何 odhcpd 配置。
nft list ruleset | grep -A2 'forward_wan',看到 meta nfproto ipv6 ... reject 就放心。
server 或 hybrid 模式。这种场景下要不要走"不通告 v6 DNS"路线看你 —— 偷懒走本章路径完全可以(原理一样),洁癖追求 v6 DNS 也接管的看附录 A。
4.3 防御性兜底:阻断 LAN v6 DNS 出站(强烈推荐)
虽然 §4.2 实测客户端默认拿不到 v6 DNS,但有几种情况会绕过:
- 用户手动给某台设备配了 v6 公共 DNS(
2606:4700:4700::1111Cloudflare 等) - 安卓 9+ 的"私人 DNS"用 DoT 到外部
- 某些 IoT 内置 hardcoded v6 DNS
加一条 fw4 规则,把 LAN 出方向的 v6 53 流量统统 REJECT,强制 fallback 到 v4(AGH):
uci add firewall rule
uci set firewall.@rule[-1].name='Block-LAN-v6-DNS-outbound'
uci set firewall.@rule[-1].src='lan'
uci set firewall.@rule[-1].dest='wan'
uci set firewall.@rule[-1].family='ipv6'
uci set firewall.@rule[-1].proto='tcp udp'
uci set firewall.@rule[-1].dest_port='53'
uci set firewall.@rule[-1].target='REJECT'
uci commit firewall
service firewall restart验证:
nft list ruleset | grep -A2 'Block-LAN-v6-DNS'
# 期望: 看到 ip6 ... udp/tcp dport 53 reject 规则1.1.1.1 / 2606:4700:4700::1111 / 8.8.8.8 / 2001:4860:4860::8888 等),代价是这些 IP 不能再用,看个人取舍。详见 §7.3。
4.4 验证
客户端断开 WiFi / 拔网线再连,然后逐项过:
1. 物理网卡 v6 DNS 应为空
# Windows:
PS> Get-DnsClientServerAddress -AddressFamily IPv6 | Select InterfaceAlias, ServerAddresses
# 期望: 物理网卡(以太网 / WLAN)ServerAddresses 是 {}# Linux:
resolvectl status | grep -A3 'DNS Servers'
# 期望: 看到 v4 (10.0.0.1), 没有 v6 (2404::xxx 或 fd::xxx 都不应有)
# macOS:
scutil --dns | grep nameserver
# 期望: 全是 10.0.0.1, 没有 v62. v4 transport 解析 AAAA 记录工作正常
nslookup -type=AAAA youtube.com 10.0.0.1
# 期望: 返回 AAAA 记录 (2607:f8b0:xxxx::xxxx)
# 说明: v4 transport 问 AGH, AGH 返回 v6 地址 → 客户端能走 v6 出去3. AGH 屏蔽 AAAA 记录也生效
nslookup -type=AAAA googleadservices.com 10.0.0.1
# 期望: AGH 屏蔽 → 返回 :: 或 NXDOMAIN
# 说明: 广告域的 v6 也被挡住, 不会通过 v6 路径加载广告4. fw4 兜底真的拦截 v6 DNS
# 在 LAN 客户端:
nslookup baidu.com 2606:4700:4700::1111
# 期望: 失败(Connection refused / 立刻报错, 不超时)
# 说明: fw4 REJECT 工作正常, 想绕的也绕不了四条全过 = §4 完工,全屋 DNS(v4 + AAAA 解析 + v6 屏蔽)都在 AGH 手里。
§5 切换 AGH 到 53 端口 + 端到端验证
5.1 让 AGH 接管 53
如果 §2.2 安装向导那一步你填的是 53,这步只需重启:
/etc/init.d/AdGuardHome restart
sleep 2
ss -nlp 2>/dev/null | grep -E ':53 ' | grep -i adguard
# 期望: 同时看到 *:53 (v4) 和 [::]:53 (v6)如果 §2.2 你填了 5353 应付,现在去 AGH 设置 → DNS 设置 → 监听端口改回 53,保存,然后上面的 restart + 验证。
5.2 客户端端到端验证
客户端断开 WiFi / 拔网线再连,重新拿 DHCP/RA,然后:
1. 客户端拿到的 DNS 是路由器
- Windows:
ipconfig /all看 "DNS 服务器" - macOS:
scutil --dns | grep nameserver - Linux:
resolvectl status - Android:设置 → 关于本机 → IPv4/IPv6 地址栏旁边 / 或装 PingTools 看
- 期望:IPv4 =
10.0.0.1,IPv6 = 空 / 未分配(§4 解释了为什么不通告 v6 DNS;空才对,有 v6 DNS 反而要查是不是有客户端硬编码绕过)
2. AGH 真的看到查询
LuCI → AdGuard Home → 查询日志,期望刷出客户端 IP + 实时查询记录。
3. 广告真被屏蔽
- AGH 仪表盘 "Blocked by filters" 计数在涨
- 浏览器开任意广告大站,广告位空了 / 占位
4. .lan 内网域名照常解析
nslookup router.lan 10.0.0.1
# 期望: 解析回 10.0.0.1四条全过 = 完工。
§6 自用脚本(占位,后补)
预留几个口子,后面补具体内容:
§7 踩坑速查
7.1 装完瞬间全屋 DNS 炸
90% 是 dnsmasq 已经搬走但 AGH 没占上 53。看一眼谁占着:
netstat -tnlp 2>/dev/null | grep ':53 '
netstat -unlp 2>/dev/null | grep ':53 '应急还原(让 dnsmasq 先把 53 接回去,慢慢排查):
/etc/init.d/AdGuardHome stop
uci set dhcp.@dnsmasq[0].port='53'
uci commit dhcp
service dnsmasq restartDNS 立刻恢复,然后回 §3 重做。
7.2 IPv6 客户端有 v6 DNS,且不是 AGH
按 §4 的设计,客户端 v6 DNS 应该是空。如果实际看到客户端 v6 DNS 是某个非 10.0.0.1 的地址(典型是 2404:1a8:7f01:b::3 NTT,或者 2606:4700:4700::1111 Cloudflare),说明有东西绕过了 AGH:
- odhcpd 在 relay 模式下把上游的 DNS 选项透传给了客户端:
uci show dhcp.lan | grep ra_dns,如果没设,把它显式关掉:uci set dhcp.lan.ra_dns='0'; uci commit dhcp; service odhcpd restart。 - 客户端手动配了 v6 公共 DNS:Windows 在 "网络与 Internet → 高级网络设置 → 网卡属性 → IPv6" 里看;Linux 在 systemd-networkd / NetworkManager 配置里看;手机在 "私人 DNS / Private DNS" 设置里看。逐个关掉。
- fw4 阻断规则没生效:回 §4.3 重做那条
Block-LAN-v6-DNS-outbound,然后nslookup baidu.com 2606:4700:4700::1111测一下应该失败。 - 某 IoT 内置硬编码 DNS:fw4 规则会把它的 v6 53 出站请求 REJECT,设备应该自动 fallback 到 v4。如果设备不 fallback(IoT 死硬),它就上不了网,这时要么换设备,要么单独给那 MAC 放行(自己拿主意)。
7.3 某些设备(iOS / Android / 浏览器)继续绕过 AGH
iOS 私有中继、Android 9+ 私人 DNS、Chrome / Edge 内置 DoH,默认都会绕过本地 DNS。逐个关:
- iOS:设置 → 自己头像 → iCloud → 私人中继 → 关
- Android:设置 → 网络与互联网 → 私人 DNS → "自动" 或 "关闭"
- Chrome:设置 → 隐私和安全 → 安全 → "使用安全 DNS" → 关
- Edge:同上(
edge://settings/security)
想强行兜底就把 §3.2 选项 B 反向开着(fw4 劫持所有 53),但 DoH(443 端口)还是拦不住,要彻底封需要黑名单 known DoH 服务器 IP(cloudflare-dns.com / dns.google 一长串),代价是误伤,看个人取舍。
7.4 sysupgrade 升级后 AGH 配置丢
升级前把这几条加到 /etc/sysupgrade.conf:
/etc/adguardhome.yaml
/usr/share/AdGuardHome/
/var/AdGuardHome/具体哪个目录是 AGH 工作目录看你装的版本 —— 找含 filters/ data/ sessions.db 的那个就是。sysupgrade -l | grep -i adguard 确认保留名单。
7.5 时间不准导致 DoH/DoT 上游 TLS 握手失败
部分硬件无 RTC,断电时间归零,AGH 连 https://dns.alidns.com/dns-query 会因证书 "not valid yet" 失败。
service sysntpd status # 应 running
date # 看时间合理不准的话 service sysntpd restart 强制同步;snapshot 里没 sysntpd 就装 chrony(apk add chrony && /etc/init.d/chronyd enable && start)。
§8 关键文件位置
| 文件 / 目录 | 作用 | 谁维护 |
|---|---|---|
/etc/adguardhome.yaml | AGH 主配置(上游、监听、过滤、用户) | AGH / LuCI |
/usr/share/AdGuardHome/ 或 /var/AdGuardHome/ | 工作目录(filters / querylog / stats / sessions) | AGH 运行时 |
/etc/init.d/AdGuardHome | procd init 脚本 | 包 |
/etc/config/dhcp | dnsmasq 端口、DNS 重定向开关、LAN v6 ra/dhcpv6 模式 | uci(§3 / §4.2) |
/etc/config/firewall | 阻断 LAN v6 DNS 出站规则(§4.3)、(可选)强制 53 DNAT 规则(§3.2) | uci |
/etc/config/network | wan PPPoE、wan6 DHCPv6 客户端、LAN IPv6 ULA 前缀 | uci |
/root/agh-backup/ | §0.1 备份 + §6.1 自动备份(待补) | 你 |
附录 A:想给 v6 客户端通告 DNS 的扩展阅读
正文 §4 主张"不通告也不影响 v6 访问",这是 NTT relay 场景实测验证过的结论。本附录留给以下三类读者:
- 在国内电信 / 联通环境,光猫给到 OpenWrt 完整 PD 前缀,自然走 server / hybrid 模式 —— 顺便通告 v6 DNS 成本几乎为 0
- 有纯 v6-only 客户端(无 v4 stack),必须有 v6 DNS 才能解析
- 单纯追求"v6 DNS 也接管"的纯粹路径
A.1 IPv6 工作模式速览
LuCI 里 LAN 接口的"DHCP 服务器 → IPv6 设置"几个下拉:
| 字段 | 取值 | 行为 |
|---|---|---|
| 路由通告服务(RA) | server | 路由器自己生成 RA,通告给 LAN(包含前缀、网关、DNS) |
| relay | 把上游 wan6 收到的 RA 原样转发给 LAN | |
| hybrid | 有 PD 前缀走 server,没有走 relay,自动 | |
| disabled | 不发 RA | |
| DHCPv6 服务 | server / relay / hybrid / disabled | 同上,管 DHCPv6 |
| NDP 代理 | hybrid / relay / disabled | 邻居发现代理 |
| DHCPv6 模式(server 模式才有意义) | stateless | SLAAC(客户端用 EUI-64 / 隐私扩展自己生成 IP,从 RA 学前缀) |
| stateful | DHCPv6 显式分配 IP(像 v4 DHCP 那样) | |
| stateless+stateful | 两者并行 |
Server vs Relay 关键差异:
- Server:路由器有自己的 v6 前缀(ULA 或 PD 给的 GUA),自己当 v6 网关 + DNS。"通告哪个 DNS"完全路由器说了算 —— v6 DNS 接管最简单。
- Relay:路由器是透明转发,上游 RA 写啥就传啥。能不能改 DNS 选项取决于 odhcpd 版本,较新版本支持覆写,但行为不稳定,实测可能失效(本文 NTT 环境就是栽在这里)。
A.2 Server / hybrid 模式下接管 v6 DNS
适用于:LuCI → 网络 → 接口 → LAN → DHCP → IPv6 设置 → RA / DHCPv6 = server 或 hybrid,且 br-lan 上有稳定的 v6 地址(ULA fd*::1 或 PD 给的 GUA)。
A.2.1 关掉 odhcpd 默认的 DNS 通告
LuCI:网络 → 接口 → LAN → 编辑 → DHCP 服务器 → IPv6 设置 → 取消勾选 "本地 IPv6 DNS 服务器"
UCI:
uci set dhcp.lan.ra_dns='0'
uci commit dhcpA.2.2 选一个稳定的 v6 地址作为 AGH 的"v6 入口"
ip -6 addr show br-lan | grep inet6
# 优先取 fd**::1 这种 ULA;没有的话用 GUA(光猫前缀给路由器自己的)ULA 没自动生成的话手动建一个(RFC 4193 标准):
ULA=fd$(head -c 5 /dev/urandom | hexdump -e '5/1 "%02x"' | sed -E 's/(..)(....)(.*)/\1:\2:\3::\/48/')
uci set network.globals.ula_prefix="$ULA"
uci commit network
service network reload记下这个地址,下文统一写作 <ROUTER_V6>。
A.2.3 写入 RA / DHCPv6 通告 DNS
LuCI:同一页 → "通告 DNS 服务器"填 <ROUTER_V6>
UCI:
uci add_list dhcp.lan.dns='<ROUTER_V6>'
uci commit dhcp
service odhcpd restartA.2.4 确认 AGH 在 v6 上监听
sed -n '/^dns:/,/^[a-z]/p' /etc/adguardhome.yaml | head -10
# 期望 bind_hosts 包含 "::"不对就在 AGH 设置 → DNS 设置 → "监听接口" 选 "所有接口",/etc/init.d/AdGuardHome restart。
A.2.5 客户端验证
# Linux:
resolvectl status | grep -A3 'DNS Servers'
# 期望: 列表里有 <ROUTER_V6>, 没有运营商 DNSA.3 Relay 模式下硬尝试覆写 DNS(可能失效)
如果你和 NTT 场景一样在 relay 模式但就是想试,做完 A.2.1 + A.2.2 + A.2.3 后,抓 DHCPv6 reply 看 DNS 选项:
tcpdump -i br-lan -nvve 'ip6 and (udp port 547 or udp port 546)' -c 20让一台 LAN 设备断 WiFi 重连触发 DHCPv6,reply 里 DNS-server 字段:
- 是
<ROUTER_V6>→ 生效,完成 - 还是上游
2404::xxx/2001:240::xxx→ 没生效
没生效的话只剩两条路:
- 切 hybrid 模式碰运气:
uci set dhcp.lan.ra='hybrid'; uci set dhcp.lan.dhcpv6='hybrid'。有 PD 就 server,没有就 relay —— 但你既然没 PD,这等于没改。 - 回正文 §4 路线(不通告 v6 DNS,fw4 兜底)—— 已经是最优解。
不推荐 NAT66:server 模式 + 自己起 ULA 段 + nft 做 v6 NAT 出去。性能 / 隐私 / 连通性都让步,只换来一个"v6 DNS 也走 AGH"的虚名,得不偿失。
A.4 v6 反查转给 dnsmasq(可选)
让 LAN 内 v6 设备的反向 PTR 解析(根据 IP 反查主机名)也能查到:
AGH 设置 → DNS 设置 → 上游 DNS,加一行(<ULA_PREFIX_REV> 替换为你 ULA 前缀的 nibble 反转):
[/<ULA_PREFIX_REV>.ip6.arpa/]127.0.0.1:12353例:ULA 是
fd5a:abcd:1234::/64,反查段就是0.0.0.0.0.0.0.0.4.3.2.1.d.c.b.a.a.5.d.f.ip6.arpa。嫌算麻烦就跳过,内网 v6 反查走 AGH 主上游会失败,不影响正向解析。
完工。
