摘要

  • RFC 9953 建议 DoC 客户端把 DNS 头部 ID 设为 0,使携带同一 DNS 数据的 CoAP 请求能共享 Cache-Key。
  • 共享一份缓存表示不等于共享对答案的信任;Max-Age、DNS TTL、RCODE、来源、验证和本地使用仍须分别留下证据。

一台休眠后醒来的现场设备,可能只想知道一个名字现在指向什么。若路径上的 CoAP 缓存已有匹配表示,设备少发一次上游请求、少耗一次电,这正是设计价值。可是一句“缓存命中了”并没有说明回答来自权威服务器还是递归服务器,没有说明是否经过 DNSSEC 验证,也没有说明它在本地策略下是否仍可使用,更没有说明某个后续程序是否真的据此执行了动作。

RFC 9953 于 2026 年 3 月发布,定义 DNS over CoAP(DoC)。它只规定 DNS 的 OPCODE 0 查询:一对 DNS 查询与响应映射为一次 CoAP 请求—响应操作。查询放在 CoAP FETCH 的正文里,DNS 线上的消息格式使用 application/dns-message,其 Content-Format 编号为 553。这种安排适合内存、帧长、吞吐量和能耗都受限制的环境;它没有把 CoAP 的承载层变成 DNS 真实性的总证明。

ID 归零的理由很窄,也因此可靠。DoC 客户端 SHOULD 将 DNS 头部 ID 设为 0,使针对同一 DNS 数据的多次请求不会仅因传统事务 ID 不同而拥有不同的 CoAP Cache-Key。这样,位于路径上的 CoAP 缓存或代理就能复用回应。DoC 服务器 MUST 将查询中的 ID 原样复制到对应响应。这个零既不是身份标识,也不是安全状态,更不是授权令牌;它只是消除了缓存键中与查询内容无关的变化。

紧接着,RFC 9953 给这种复用装上了时钟。DoC 服务器 MUST 保证 CoAP 响应 Max-Age 与其中每一条 DNS TTL 之和,小于或等于从上游 DNS 收到的相应 TTL。即使响应没有显式写出选项,CoAP 默认的 60 秒 Max-Age 也在计算之内。客户收到响应后 MUST 把承载该响应的 Max-Age 加到所有 DNS TTL 上,并使用计算后的 TTL。传输缓存保留了多久,与 DNS 记录还剩多久,是同一寿命预算的两部分,而不是可以任选其一的标签。

推荐算法让这一点更具体:把 DNS 响应中的最小 TTL 作为 Max-Age,再从所有 DNS TTL 中减去它。这样,中间 CoAP 缓存不会无意间提供已经过期的记录;如果 ETag 根据响应内容产生,即使上游缓存刷新了剩余 TTL,ETag 也可保持稳定。对只应短暂缓存的错误,可以使用更小的 Max-Age,包括零。这里处理的是时间边界,不是在给某类错误盖上永久正确或永久错误的印章。

还必须同时保留两层结果。一份可解析的 DNS 回应,即使内部是 NXDOMAIN 或其他 RCODE 失败,仍建议放在 CoAP 2.05 Content 回应中。非成功的 CoAP 代码则只应用于 CoAP 层错误,或请求不符合 DoC 协议要求的情形,例如不支持的内容格式。只看 2.05 会把 DNS 失败写成成功;只看 RCODE 又会错把上游 DNS 问题说成传输没有完成。两条结论都不完整。

缓存也没有决定回答者的角色。RFC 9953 允许 DoC 服务器是权威服务器、stub 或递归解析器,并说它 MAY 为受限客户端充当 DNSSEC 验证器。它也允许用 (D)TLS 或 OSCORE 保护消息。可能使用保护,或可能验证 DNSSEC,并不推出每个实例都具备该属性,也不替本地系统作政策判断。Daniel Kade 以 Heng Lu 的运行代码视角作编辑性提醒:能被缓存的字节、它的来源、验证状态、有效时间和实际效果是不同的事实层。

来源