摘要
- DNS 的 TC 位表示消息超过当前运输信道允许的长度。RFC 2181 后来划清语义:只有响应所必需的 RRset 无法完整放入时才应截断;客户端收到 TC 后应忽略这份响应,不能把露出来的记录当作全集。
- TCP 曾承担更大响应的重试,却没有永远停留在例外位置。RFC 7766 要求通用 DNS 同时支持 UDP 与 TCP,也允许解析器直接选择 TCP;RFC 9210 进一步把 TCP 容量、放行和监测变成日常运维责任。
512 字节装不下的,不只是数据
RFC 1035 在 1987 年规定 DNS 可经 UDP 或 TCP 使用 53 端口。普通查询偏爱 UDP,因为无需先建连接,服务器与解析器承担的状态很少;代价是 UDP 消息限于 512 字节,不计 IP 与 UDP 头部。
超过上限的响应会被截断,头部 TC 位设为 1。若只看字节,这像一次简单的空间不足;若从证据看,问题严重得多。一个名字下若有五条同类记录,而包里只留下三条,接收方不能据此断言“答案就是三条”。运输容量不应改写命名空间的事实。
TC 因而不是错误码,也不是不存在证明。它只承认这条信道没能交付完整消息。服务器仍掌握答案,解析器得到的是对当前容器的否定判断。
RRset 是不能被随意切开的证据单位
1997 年的 RFC 2181 把边界说得更严谨:拥有相同所有者名、类别与类型的资源记录构成一个 RRset。查询这组数据时,整组才是有意义的回答单位。
只有响应必需的 RRset 无法全部装入,才应设置 TC。若只是 Additional 区里本可顺手附带的数据放不下,服务器可以把那整个额外 RRset 省略,并保持 TC 为 0;需要它的客户端可另发查询。
一旦 TC 为 1,处理方式完全不同。客户端应忽略该响应,用能容纳更大回复的机制重新查询,例如 TCP。包里即使残留部分 RR,也只是截断的物理痕迹,不能进入缓存成为“可用的一半”。
这条规则阻断了一条危险捷径:接收者不能把新收到的碎片与旧缓存拼接,也不能依据“看起来够用”挑选记录。答案不完整,就没有资格代表本次问题的事实。
一个比特只报告边界,不代替解析器决策
TC 告诉解析器“这次运输不够大”,并不替它发起下一条连接。典型流程是 UDP 查询收到 TC=1 后,再用 TCP 向同一服务器重复问题,或按策略尝试其他合适服务器。
TCP 用长度字段框定 DNS 消息,不受单个 UDP 数据报容量所限;同时也引入握手、连接表、并发与空闲超时。成本落在实际使用这些资源的节点上:解析器选择重试、复用或换服务器,服务端决定连接准入和回收策略。
这种安排很接近可靠制度的最小形态。低成本信道可以先工作,也可以坦白能力到此为止;消费证据的一方必须在知道“不完整”后主动取得完整版本。任何中间节点都没有因为搬运困难而改写答案的权力。
EDNS 扩大预算,却没有签发路径保证书
RFC 6891 让请求方在 EDNS(0) 中声明自己能接收的 UDP 负载大小,也给 DNS 留出扩展空间。512 字节不再是所有交换的固定天花板,更多答案可以留在无连接的数据报路径上。
声明可收多大,并不等于沿途每个链路、隧道、防火墙与主机都会交付同样大的数据报。超过路径 MTU 后的 IP 分片可能丢失、被过滤或被利用。DNSSEC 的签名与否定证明也会扩大响应,IPv6 与新记录用途继续增加大答案出现的机会。
EDNS 与 TC 因而回答不同问题。前者是请求方提出的容量预算;后者是响应方承认实际答案没有装进可用预算。预算提高不能消除溢出信号,也不能让 TCP 失去存在理由。
更棘手的是,大 UDP 包若在途中无声消失,解析器甚至收不到 TC。把 EDNS 数值误当成路径事实,会让超时与权威否定混在一起;把 EDNS 当作 TCP 的替代品,则会抹掉大答案的恢复路径。
TCP 从“偶尔备用”成为正式成员
很长时间里,人们把 DNS over TCP 简化成“区域传送或截断后才用”。这种叙述让防火墙和实现者把 TCP/53 当作可选负担:协议一边用 TC 要求更大信道,网络另一边却把那条路封死。
2016 年发布的 RFC 7766 纠正了这个错位。通用权威服务器、递归服务器、转发器与 stub resolver 都必须同时支持 UDP 和 TCP。旧有“非区域传送必须先发 UDP”的要求也被放宽;解析器可以根据本地运维理由先用 TCP,已有连接则应复用。
所以,写成“TC 永远命令 TCP 重试”仍不够准确。TC 常常触发 TCP,但 TCP 已是可直接选择的运输方式;后来的 DNS 加密运输也让可选路径更多。持久不变的不是某种协议名称,而是不完整响应不能被消费成完整事实。
可靠信道要靠连接纪律才能扩展
若每个问题都新建并立即关闭 TCP,握手延迟和状态成本会迅速放大。RFC 7766 因此鼓励复用连接与流水线:客户端不必等上一条回复才发送下一条问题,服务器并发处理,结果可以乱序返回。
这也改变了实现与观测方式。客户端必须按 DNS 标识和问题匹配响应,不能把流中的先后顺序当成对应关系。服务器必须按 DNS 的长度框架重组字节,不能假设一个 TCP segment 就是一条完整消息。
服务端仍可限制单个客户或网段的并发连接,客户端也应减少对同一服务器的连接数。空闲会话需要按策略关闭;超时应在收到完整 DNS 消息后重置,不能让缓慢滴入的字节无限占用资源。
标准没有假装 TCP 免费,而是把互操作义务和资源控制放在同一张账上。
运维必须看见 DNS 的两种运输
RFC 9210 把实现能力推进为运维合同:解析器与服务器必须服务 UDP、TCP,网络运营者通常也必须放行两者。过滤 TCP DNS 会毁掉大响应的恢复路线,其危害高于省下一类流量处理的便利。
这并不取消容量限制。服务器可以保护自身资源,却不能只因为某个查询“本可在另一种运输成功”就拒绝它。限制应针对成本与滥用,而非把某个运输降格成不可信渠道。
日志与监测也要覆盖 TCP。只看单个包会错过跨 segment 的 DNS 消息;忽略连接复用、流水线与乱序响应,会同时漏掉正常流量和攻击。可靠信道若成为可观测性的盲区,就无法证明它真的救回了截断答案。
分片脆弱性让旧信号继续有用
2025 年的 RFC 9715 建议 DNS over UDP 避免 IP 分片:响应大小应服从请求方声明、接口 MTU、运营者已知网络 MTU 与建议的 1400 字节上限中的最小值。分片不只容易丢失,也会扩大缓存投毒风险。
文档没有改变 TC 的因果关系。若响应方知道包太大,可以缩小响应或设置 TC;若分片在途中消失,请求方最终应尝试替代运输。这不是保证 TCP 永不失败——端口过滤、服务过载与路径故障都可能存在——而是拒绝用脆弱数据报的沉默替代明确恢复。
TC 从未证明什么
TC=1 不证明 DNSSEC 验证失败,不证明域名不存在,也不证明审查、攻击、所有权或配置错误。省略非必需的附加信息也不必然触发 TC。一个中间代理更不能利用它自行删改记录。
它证明的范围非常窄:这份响应在当前信道上没有完整交付。正因范围窄,它才可靠。服务器不用猜客户端意图,解析器不用猜缺失字节含义,各方只需守住“半份 RRset 不是答案”。
互联网没有要求第一只信封容纳一切。它要求信封装不下时,必须诚实承认。
来源与证据边界
TC 与原始 UDP 上限来自 RFC 1035,RRset 完整性与客户端行为来自 RFC 2181,EDNS 容量声明来自 RFC 6891,TCP 的实现和运维责任来自 RFC 7766 与 RFC 9210,分片规避来自 RFC 9715。这些规范不能证明当前全球 TC 比例、TCP 放行率、实现默认值或解析成功率。
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
