为什么 Pi-hole v6 会忽略来自 WireGuard 客户端的 DNS 查询
Pi-hole v6 决定哪些 VPN 客户端能获得 DNS,依据的是接口和监听模式,而不只是端口。把两者对齐,然后再测试被拒绝的路径。
Pi-hole v6 在 53 端口收到 DNS 查询后,会判断到达的报文是否允许被应答。在 WireGuard 主机上,第二个判断往往就是客户端超时、而从局域网看解析器却一切正常的原因。端口是开的,FTL 也在运行,但 10.90.0.1 就是什么都不返回。在应答离开之前,有三件事相互作用:dns.interface、dns.listeningMode 以及挡在二者前面的防火墙。
监听套接字并不决定谁能得到应答
FTL 在 53 端口上打开 UDP 和 TCP 监听。默认配置下套接字常常是通配地址,因此 ss -lunp | grep :53 无论是否服务 VPN 客户端,都会显示 0.0.0.0:53 和 [::]:53。通配套接字接受报文,随后 FTL 在应答之前先应用接口与来源规则。这就是为什么「端口在监听」几乎不能证明隧道客户端可用。
要读正在运行的配置,而不是你以为生效的文件。pihole-FTL --config dns.interface 与 pihole-FTL --config dns.listeningMode 会打印实际生效的值;当设置由容器、环境变量或部署管理器掌管时,它们可能与该主机上的文件不同。Pi-hole FTL 配置参考 列出了各种模式,以及哪一种以接口为准。
LOCAL 问的是哪个子网,SINGLE 问的是哪个接口
默认的 LOCAL 会应答来源地址属于主机某个接口上所配置子网的查询。带 10.90.0.1/24 的简单 wg0 能通过这一测试,因为 10.90.0.2 上的客户端就在隧道子网内。对端另一侧被路由的客户端,或是在另一个前缀里藏在 NAT 后面的客户端,即便报文确实从 wg0 进来也通不过,日志里也不会出现任何查询。
SINGLE 换了一个问题。它接受从 dns.interface 指定的接口进入的查询(包含回环),并忽略来源子网。链路化或路由化的 VPN 拓扑能活下来的正是这个模式。两个键要一起设置,因为没有指定接口的模式不是完整指令:
sudo pihole-FTL --config dns.interface "wg0"
sudo pihole-FTL --config dns.listeningMode "SINGLE"BIND 改变套接字,而这是有代价的
BIND 并不过滤通配套接字;它只把 53 端口绑定到指定接口上真实存在的地址,因此内核会拒绝从别处到达的报文。它比 SINGLE 更严格,也不是它的同义词。代价出现在启动时:如果 FTL 启动时 wg0 还没起来,可能根本没有地址可绑,解析器就会在没有监听者的情况下运行,直到接口出现并且 FTL 重启。
当你能控制启动顺序时(例如把某个 systemd 单元排在 WireGuard 接口之后),并且希望内核在 FTL 看到之前就丢掉游离报文,就选 BIND。当隧道时来时走,或接口由比 FTL 更晚启动的工具创建时,选 SINGLE。
防火墙是第二道门
即使 FTL 模式正确,只要主机防火墙在 wg0 上丢弃 53 端口,仍然会失败。为两种协议都放行 VPN 来源网段,并让互联网一侧保持关闭。在 nftables 中,沿用 inet filter 表里已有的 input 链,规则大致如下:
sudo nft add rule inet filter input iifname "wg0" ip saddr 10.90.0.0/24 udp dport 53 accept
sudo nft add rule inet filter input iifname "wg0" ip saddr 10.90.0.0/24 tcp dport 53 accept如果隧道承载 IPv6,就补上对应的 IPv6 规则,并放在链的 drop 策略之前。如果主机用 ufw 或 firewalld,就在那个管理器里表达同样的匹配,不要混用工具。不要把 53 端口从互联网路由器转发进来;客户端应当通过隧道访问解析器的 VPN 地址。
两条路径保持分离。客户端的查询在 FTL 终止;FTL 自己的上游查询则按主机的路由表发出,可能走隧道也可能不走,所以「能应答但返回不出有用结果」属于上游问题。Web 管理与 API 监听各自的端口,需要各自的限制。
验证应答与拒绝
从 VPN 客户端出发,用两种协议分别查询解析器地址:dig @10.90.0.1 example.com 与 dig +tcp @10.90.0.1 example.com。然后到管理界面查看查询日志,确认 FTL 记录了该查询。客户端超时且日志无记录,指向防火墙或接口过滤;有日志却无应答,则指向上游解析。
再从 VPN 之外的某台主机测试负向路径。dig @10.90.0.1 example.com 应当超时,而 ss -lunp 在解析器上不应显示 53 端口绑定到公网地址。重启一次服务,然后重启主机,确认 wg0 重新出现后解析器仍然能应答。只在下次重启之前有效,就不算改完了。