摘要

  • RFC 3397 把 DHCP 选项 119 定义为有序的 DNS 域搜索列表。客户端必须先依照 RFC 3396 拼接全部片段,再在完整聚合数据中解释 RFC 1035 压缩指针。
  • 搜索列表发生在 DNSSEC 之前。一个恶意但被接受的后缀可以构造出另一个完整域名,而该域名的控制者完全可以发布合法签名的记录,于是系统得到的是“对另一个问题的真实答案”。

myhost 并不是一个足以唯一查询的 DNS 名称。用户敲下这个短字符串之后,主机还要选择后缀、排列候选项,并把其中一个候选项写进 DNS 问题。RFC 3397 标准化的不是答案,而是 DHCP 向客户端交付这份选择列表的方式。

这份标准轨文件发布于 2002 年 11 月,为 Domain Search 分配了 DHCP 选项代码 119。它的权限范围很窄:只配置 DNS 使用的域搜索列表,不负责在不同名称解析机制之间排序。RFC 2937 曾定义另一项名称服务搜索选项;把两者混为一谈,会让选项 119 获得它从未拥有的跨系统含义。

列表并不是普通文本。Searchstring 把多个域名按 RFC 1035 的 DNS 标签格式连续编码,并允许使用名称压缩。一个完整域名或其重复后缀,可以由两个八位组的指针替代。如果两个列表项都以 apple.com. 结束,第二项无需再次携带全部标签。这种节省对空间紧张的 DHCP 选项尤其重要。

指针的坐标系有明确边界。偏移从选项数据的开头计算,不包含选项代码和长度两个八位组。它不是外部 DNS 引用,不会请求另一个包,也不是网络地址;它只指向同一逻辑数据块中更早出现的位置。

问题在于,这个逻辑数据块可能物理上并不连续。RFC 3397 采用 RFC 3396 的规则:同一代码 119 的多个实例必须先把数据部分按顺序拼成一个聚合块。只有拼接完成之后,解析器才可以跟随 RFC 1035 指针。因此指针的目标完全可能跨过两个片段之间的边界;片段边界不是名称语法的一部分。

文件中的例子把 eng.apple.com. 与 marketing.apple.com. 分散到三个选项实例。第二个名称以 C004 结束,指向聚合块偏移四的位置,也就是 apple.com. 开始处。如果收到一个实例就立即解释一次,这个坐标便无从成立。DHCP 重组必须先于 DNS 解压,这不是实现偏好,而是互操作合同。

终止规则又划出一条证据边界。每个搜索域必须以长度为零的根标签结束,或者以一个有效的双八位组压缩指针结束。如果聚合数据在名称中途耗尽,而两种终止形式都未出现,客户端必须丢弃这个不完整名称。已经收到大部分标签,并不构成猜测剩余部分的授权。

列表还原以后,解析器才开始把用户输入变成问题。RFC 3397 引用了 RFC 1535 与 RFC 1536 的安全建议:搜索列表应当显式配置,而不是从主机名推断。含有点号的输入应先作为完整域名尝试,失败后再附加本地域;不含点号的输入则可以立刻进入后缀搜索。

攻击面就位于这一步。用户输入 myhost,期待系统找到 myhost.bigco.com。恶意 DHCP 服务器却下发 roguedomain.com,使机器实际查询 myhost.roguedomain.com。到此为止,攻击者甚至不必伪造任何 DNS 数据;改变问题本身已经完成了跨管理域的转向。

RFC 3397 最锋利的判断,是 DNSSEC 无法阻止这种攻击。恶意域的运营者可以为自己控制的名称发布记录,并用合法密钥正确签名。DNSSEC 能证明返回数据确实属于 myhost.roguedomain.com,也能证明传输后内容未被篡改;它不能证明用户原本就想访问这个名称。

因此,把结果称为“DNSSEC 失败”反而会掩盖真正的机制。这里有多层相互独立的权力:本地配置决定手动设置是否优先,DHCP 提出搜索后缀,客户端决定是否认证与接受,解析器构造候选名称,DNS 对选中的名称作答,DNSSEC 验证答案,应用程序再决定是否连接。后一个环节的证据不能追溯授权前一个环节。

文件认为,操纵搜索后缀可能比简单下发一个非法 DNS 服务器更有效。攻击者可以使用自己域名的正常权威服务器和真实记录,无需维持一个显眼的异常解析器,也无需伪造签名。观测者看到的 DNS 链条可以全部正常,因为改道发生在链条开始之前。

相应的缓解措施也针对前置权力:落实 RFC 1536 的搜索处理方式,不让 DHCP 覆盖手工配置的 DNS 参数,必要时在接受选项 119 之前要求 DHCP 认证。不过,认证只能证明消息来自被接受的主体,并不自动证明其中的后缀符合某个用户当下的意图。

这要求运行证据保留一条完整因果链。首先记录用户原始输入、手动搜索列表、DHCP 学到的列表、两者优先级、服务器身份与认证决定。其次保存原始的 119 实例、RFC 3396 聚合块、压缩指针目标、无效名称丢弃记录与候选名称顺序。最后把真正发出的 DNS 问题、DNSSEC 结果、返回地址和应用连接关联起来。

抓包中出现选项 119,只证明它到达观测点,不证明客户端接受。列表成功解压,不证明解析器实际采用。一个 DNS 查询未必保留用户最初输入。签名验证成功,也不会透露后缀来自手工设置还是某个 DHCP 租约。任何一步被压平成“解析成功”,都可能把决定目的地的关键权力隐去。

IANA 的 BOOTP/DHCP 参数注册表记录了代码 119,证明编号经过协调,却不证明部署规模、接受状态或实现正确。RFC Editor 当前检索不到 RFC 3397 的匹配勘误,这也不是对解析器、优先级或运行行为的合格证书。

Lu Heng 的最小初始规范原则解释了这份文件为何克制。它只规定独立实现必须共享的边界:DNS 专用范围、标签编码、聚合坐标和有效终止;它不强迫所有系统采用同一种内部缓存、接口或错误模型。运行代码优先则补上验证要求:让指针跨越真实片段,观察聚合结果、候选顺序、发出的包与最终连接。

RFC 3397 的历史价值,不在于要求人们怀疑所有签名答案,而在于把签名的证明对象说清楚。签名验证的是一个已经选定名称的记录。要判断这个名称是否正确,还必须回答更早的问题:是谁用什么依据构造了查询。

来源