摘要

  • DNS Cookies 把一次成功往返变成有限的回程可达性证据,让路径之外的攻击者更难冒用受害者源地址,却不建立用户身份。
  • RFC 7873 定义了 Client Cookie 与 Server Cookie 的交换;RFC 9018 又固定了可互操作的 16 字节版本 1 Server Cookie,使混合软件的 anycast 节点能够验证同一份状态。
  • 这套机制不加密 DNS,也挡不住能看到明文 cookie 的路径内观察者;NAT、失陷主机和滥用流量仍要求限速与其他防御共同处理。

第一次查询没有账户、证书或预先协商的密钥。服务器看到的只是一个 UDP 数据报,其中的源地址可能真实,也可能是攻击者填写的受害者地址。客户端在 EDNS COOKIE 选项中放入 8 字节 Client Cookie。支持该机制的服务器会把这段值原样带回,并附上自己生成的 Server Cookie。此后的查询再同时携带两者。

第二次请求因此多了一小段可验证的历史。Server Cookie 取决于 Client Cookie、客户端在服务器眼中的地址,以及服务器掌握的秘密。路径之外的攻击者可以伪造 IP 头,却通常看不到发往受害地址的上一份响应,也就拿不到相符令牌。服务器据此只能做一个克制的判断:这个“地址与 Client Cookie 的组合”先前确实完成过往返。客户端也可以检查响应是否带回自己预期的 Client Cookie,排除一部分盲目伪造的答复。

这里没有身份认证。家庭网关、运营商级 NAT 或企业出口,都会让大量设备共享一个公网地址。位于正确地址上的失陷主机照样可能作恶。能够观察链路的对手可以直接抄走明文 cookie,在有效期内复用。DNS Cookies 不会隐藏查询名,不证明域名所有权,也不替代 DNSSEC。它证明的只是:某条回程曾经走通。

这个狭窄结论之所以重要,源于 UDP DNS 的放大与伪造问题。短请求可以用虚假源地址诱使服务器向受害者发送更长响应;伪造请求也可能迫使递归服务器执行查询和 DNSSEC 验证。反过来,攻击者还会向解析器投递猜测的响应,争夺缓存写入机会。DNSSEC 认证的是 DNS 数据;TSIG 能提供更强的事务认证,却需要密钥管理;端口与事务 ID 随机化提高盲猜难度;响应限速约束输出。DNS Cookies 补上的是无需服务器保存逐客户端会话的轻量回程证据。

2016 年 5 月发布的 RFC 7873,把 COOKIE 定为 EDNS 选项代码 10。未知 Server Cookie 时,选项只含 8 字节 Client Cookie;完成学习后,再加入 8 至 32 字节的 Server Cookie。原规范允许实现自行选择生成方式。服务器可用请求源地址、Client Cookie 和自身秘密重新计算结果,不必维护客户表。

协议状态机为渐进部署留了余地。不支持 cookie 的服务器会忽略该选项。支持者收到仅含 Client Cookie 的请求时,可依策略丢弃、返回 BADCOOKIE,或正常处理;只要响应,就应带回 Server Cookie,让客户端进入下一状态。长度非法会产生 FORMERR。过期或错误的 Server Cookie 按“尚未持有”处理。验证成功后,服务器可以放宽专门针对 UDP 源地址伪造的限制,但不能因此关闭所有滥用防线。

BADCOOKIE 因而是状态转换,不只是失败码。响应若带回匹配的 Client Cookie,客户端可以接收新的 Server Cookie 并重试。新值立即再次失败时,规范建议转向 TCP。重复失败也可能暴露 anycast 内部问题:同一服务地址背后的节点没有共享秘密,或使用了不同的计算方法。

NAT 解释了 Server Cookie 为什么必须同时绑定源地址与 Client Cookie。若只绑定公网地址,一个内网设备取得的令牌就可能被同一出口后的其他设备使用。加入 Client Cookie 后,服务器无需存储个人状态,也能区分这些流。区分仍停留在网络可见的粒度,绝不能上升为个人身份。

Anycast 带来了更棘手的历史缺口。同一服务地址的连续请求可能落到不同机器,甚至不同厂商的软件。RFC 7873 建议节点共享 Server Secret,却没有统一把输入变成 cookie 的方法。于是,两套实现即使掌握相同秘密,也可能互不认可对方生成的值。一次正常路由变化,就会制造出仿佛攻击发生的错误。

2021 年 4 月发布的 RFC 9018 用版本 1 结构补上了互操作性:Server Cookie 固定为 16 字节,依次包含 1 字节版本、3 字节保留位、4 字节时间戳和 8 字节 SipHash-2-4 结果。加上 8 字节 Client Cookie,完整 COOKIE 选项必须是 24 字节。哈希覆盖 Client Cookie、结构字段、客户端 IP 与 Server Secret;客户端 IP 参与验证,却不会被抄进令牌。

时间戳给重放划定边界。RFC 9018 建议接受一小时以内的旧值,并为 anycast 节点时钟偏差容许最多五分钟的未来值;cookie 超过半小时后,服务器应至少考虑刷新。这些是标准建议,并不代表所有部署的实测配置。它们说明令牌本来就该过期,也说明路径内观察者能够看见其可利用窗口。

秘密轮换因此成为一项分阶段的集体操作。新秘密先分发到所有节点,此时节点继续用旧秘密签发,同时验证新旧两套;随后改用新秘密签发,但仍接受旧值;等客户端完成刷新后,才停止验证旧秘密。统一算法还不够,时钟、分发与阶段一致性同样属于协议控制面。

RFC 9018 也改写了 Client Cookie 建议:面向每个不同服务器 IP 使用独立的 64 位随机值;客户端自身 IP 改变后,不得继续复用原有 Client Cookie 或 Server Cookie。否则,稳定令牌会跨网络跟踪设备。NAT 后的主机未必知道公网出口地址已经变化,这一残余跟踪问题被明确留在机制范围之外。

DNS Cookies 的历史,不是 DNS 获得了“身份”,而是证据终于与它能支持的结论对齐。第一次往返没有证明意图,只生成了一枚让路径外冒充变难的令牌。RFC 7873 规定了这笔交换,RFC 9018 让它能在异构 anycast 集群中成立。真正的控制权仍掌握在客户端复用策略、服务器响应政策、统一时钟和秘密托管之中。

来源