DNS over TCP 与截断回退
DNS 主要跑在 UDP 53 上,但规范同时要求 TCP 53 必须可用。当响应超过当前 UDP 缓冲上限时,服务端把头部里的 TC 标志置位,表示「这次放不下」,解析器必须改用 TCP 重新查询。区域传送、体积较大的 TXT 记录与 DNSSEC 签名响应也常走 TCP。RFC 7766 进一步建议解析器长期复用 TCP 连接,以摊薄握手开销,现代实现已普遍支持。
基本信息
| 端口 | UDP 53 与 TCP 53 同用 |
|---|---|
| 触发条件 | 收到 TC 置位的响应,或查询本身要求 TCP |
| 典型场景 | 区域传送、大 TXT、DNSSEC 签名响应 |
| 连接方式 | RFC 7766 鼓励长连接复用 |
| 排查要点 | TCP 53 被拦时,大响应域名会解析失败 |
| 前置消息 | TCP 上同样有 2 字节长度前缀标识报文边界 |
测试与对照
测试与对照
dig +tcp example.com # 强制走 TCP
dig +tcp +short @8.8.8.8 example.com # 指定服务器并强制 TCP
dig +ignore example.com # 忽略截断,仅用于调试
dig +bufsize=512 example.com +noall +comments # 复现 TC 置位再切 TCP什么时候会走 TCP
| 情形 | 原因 | 验证方式 |
|---|---|---|
| 收到 TC 置位 | UDP 响应超出缓冲上限 | 小缓冲复现后加 +tcp 对照 |
| 区域传送 | 全量记录流必须可靠传输 | 主从上用 TCP 同步 |
| 大 TXT 记录 | 多条长文本超出经典上限 | 用 +tcp 检查结果是否完整 |
| DNSSEC 响应 | 签名记录显著增大报文 | 比对 UDP 与 TCP 的答案是否一致 |
典型使用场景
- 排查间歇性解析失败:只放行了 UDP 53 的策略会让大响应域名反复失败
- 主从同步验证:区域传送必须走 TCP,端口不通会直接导致同步中断
- 安全设备策略审查:确认 TCP 53 是否被误判为隧道流量而拦截
- 解析器性能调优:评估是否启用 TCP 长连接复用以减少握手
- 抓包分析:识别带长度前缀的 TCP 报文与 UDP 报文的分段差异
现代解析器普遍优先使用 UDP,再按需回退到 TCP。回退本身是正常行为,不必刻意禁用;真正需要关注的是回退比例突然升高,那通常意味着链路出现了丢分片或 EDNS 缓冲协商被破坏,应该从中间设备的策略入手排查。