dig 显示 Truncated, retrying in TCP mode 后超时
DNS 的 UDP 回答被截断后转为 TCP 查询却超时,按同一解析器比较两条路径,确认监听和防火墙后只允许授权客户端的 TCP 53。
局域网客户端查询某些域名时,先看到 Truncated, retrying in TCP mode,接着报 connection timed out; no servers could be reached;换一个域名可能正常,在 DNS 服务器本机查询也可能正常。这组现象应先把 UDP 回答与 TCP 回退分开检查。
截断提示表示 UDP 回答带有截断标记,dig 默认会改用 TCP 重试。超时发生在后续路径时,UDP 53 可用并不足以证明 DNS 链路完整。防火墙只允许 UDP 53 是一种具体原因,TCP 未监听、路由错误或其他中间设备阻断也需要由检查结果区分。
下面讨论普通 DNS 的 TCP/UDP 53,示例是局域网客户端访问 Linux 上的解析器,主机使用 UFW 管理防火墙。它不适用于直接套用到 DoH、DoT,也不是某个顶级域名必然故障的规则。记录大小、EDNS 能力和路径条件会影响是否发生截断。
对同一个解析器、名字和类型做比较
把 192.0.2.53 换成客户端实际使用的解析器地址,把 service.example.com 和 A 换成当时失败的查询名与类型。不要两次查询同时更换服务器或记录类型:
dig @192.0.2.53 service.example.com A +tcp
dig @192.0.2.53 service.example.com A +notcp +ignore
第一条直接检查 TCP 查询;第二条仅用于观察 UDP 回答,+ignore 让 dig 不因截断而自动重试 TCP。若 UDP 回答里有 tc 标志,而直接 TCP 查询超时,就把检查范围缩小到客户端与这个解析器之间的 TCP 服务和网络路径。
+ignore 得到的回答可能不完整,不能把它作为永久修复,也不能只看到部分地址就认定查询成功。增大 UDP 接收尺寸也不能代替 TCP 支持,过大的 UDP 报文还可能遇到路径 MTU 与分片问题。
在解析器本机,对它实际监听的同一入口检查 TCP。若本机正常、远端客户端失败,重点检查监听地址和中间网络;若本机也失败,先核对解析器是否提供该 TCP 监听及相关日志。查询回环地址和查询局域网地址不是同一个网络路径。
Pi-hole 和 Unbound 的端口不能混在一起
Pi-hole 可以在 53 端口接收客户端请求,再向本机 Unbound 的另一个端口转发。本机直接查 Unbound 成功,只证明那个入口能够回答,不能证明客户端能通过 TCP 53 到达 Pi-hole。
按配置列出客户端到 Pi-hole、Pi-hole 到 Unbound 的地址与端口,再定位失败在哪一段。不要为了观察故障就把只监听回环的 Unbound 改为对所有地址开放。容器部署还应按实际端口映射、网络空间和管理方式检查,下面的主机 UFW 示例不能代表全部容器路径。
缓存命中与新查询可能得到不同大小或不同来源的回答,本机查一次后其他设备暂时恢复,也不足以证明根因是缓存损坏。先保留故障查询与 TCP 对照结果,避免清空缓存后丢失线索。
只对已授权的客户端补充 TCP 53
确认解析器确实监听正确的 TCP 地址、现有防火墙缺少相应允许规则后,先保存当前规则和管理入口。UFW 主机可查看:
sudo ufw status verbose
sudo ufw status numbered
若 UFW 未启用,不要把启用整个防火墙作为这条故障的临时修复。还应核对规则顺序、上游路由器、云防火墙或其他网络策略;一条较早的拒绝规则可能让后加的允许规则不起作用。
以下地址均为文档占位值。假设授权客户端网段为 192.0.2.0/24、解析器自身地址为 192.0.2.53,且这是直接运行在该主机上的解析服务,可以先预览再添加对应规则:
sudo ufw --dry-run allow proto tcp from 192.0.2.0/24 to 192.0.2.53 port 53
sudo ufw allow proto tcp from 192.0.2.0/24 to 192.0.2.53 port 53
保留原有 UDP 规则。不要把内部递归解析器的 TCP 53 对全互联网开放,也不要关闭整个防火墙来维持解析。实际使用 IPv6 的客户端要按已授权 IPv6 范围单独核对,IPv4 成功不代表 IPv6 路径已经修好。
如果阻断发生在路由器或网络访问控制层,应该在该层沿用已有管理方式修正精确的 TCP 路径,而不是给解析器增加无效规则。没有确认缺少允许规则时,不应直接执行上述变更。
验证完整回答和原客户端
修改后先重复直接 TCP 查询,再去掉诊断用的 +ignore,让 dig 按默认行为处理原来的查询:
dig @192.0.2.53 service.example.com A
检查响应状态、所需记录是否完整以及是否仍超时,并在原客户端验证实际应用和内部域名。不要以管理页面可访问或另一个短回答域名正常作为全部通过的依据。
若需要回退,只有确认下面规则确由本次新增且没有其他用途时,才删除这一条:
sudo ufw delete allow proto tcp from 192.0.2.0/24 to 192.0.2.53 port 53
恢复规则不会解决原有 TCP 回退故障;应保留查询和日志记录继续定位。不要使用 reset 清空整个防火墙,也不要撤销已有客户端所需的允许项。


