你写下一行,包含解析器地址和公司域名,期望只有该域名内的名称会使用隧道解析器。在 Apple 客户端上,现在所有名称都会发往那里,域名内的短名称也会被解析。这一行做了两件彼此独立的事,其中只有一件关乎隧道处理哪些查询。另一件只是输入便利,却被一厢情愿的解读提升成了策略。

DNS 行被解析成什么

客户端把该条目读成列表,并按形状对每一项分类。看起来像地址的东西会成为 DNS 服务器;看起来像域名的东西会成为搜索后缀。两者都进入隧道设置,但落在不同字段里。一条承载私有解析器和一个内部域名的隧道,其示例行如下。

DNS = 10.24.8.53, lab.internal.example

地址提供解析器。域名提供一个后缀,让客户端可以输入短名称,由系统在询问前补上其余部分。两者都没有说明把解析器限制在该域名内,而这正是人们期待却得不到的部分。平台上只有一个字段能表达这种限制,而这个字段不是它。

Apple 的两个字段,两种不同的职责

Apple 在其 DNS 设置对象中体现了这一区别。搜索域列表的文档说明,它用于为一标签的主机名补全限定:输入裸主机名,系统会依次尝试追加每个后缀。这是补全规则,不是路由规则。该列表中的任何内容都不决定去问哪台服务器。

匹配域列表是另一个属性。它决定哪些命名空间使用这组 DNS 设置,而空条目意味着默认域,而不是某个特定后缀。 分组隧道设置生成器 在 Apple 客户端中遵循这一模型。它把解析出的搜索后缀放入搜索列表,并在存在服务器时把匹配列表设为空字符串。结果是一个会回答系统发来的一切的隧道解析器,外加一个帮助处理短名称的后缀。

所以那一行上的域名并不是命名空间选择器。再加一个不会收窄隧道使用的查询,去掉它也不会放宽。唯一改变的是有多少短名称会被补全。

为什么每个名称仍然会到达隧道解析器

在匹配条目为空的情况下,隧道是普通名称的候选解析器,而不只是公司域名的。在全局隧道配置中这通常影响不大,因为所有流量本来就在隧道里。在分离隧道中这就很重要了。公共名称现在可能由一个只持有私有区域的解析器来解析,故障看起来像 VPN 坏了,实际上却是解析器只回答了命名空间的一部分。隧道本身没问题,查询发出去了,答复却空着回来。

有两种修复方式,而它们是不同的决定。把隧道解析器做成完整解析器,通过已批准的路径转发公共名称;或者改客户端配置而不是域名列表,停止把公共名称发往那里。前者把每条查询留在隧道里并信任上游。后者把部分查询留在本地,并接受隧道断开时私有名称可能无法解析。

分离 DNS 真正需要什么

限定命名空间的解析器策略需要一个能让你表达它的客户端:在 Apple 平台上匹配域名,或在你使用的产品里做等效设置。只接受服务器和后缀的配置字段无法表达它,无论怎么加标点。配置文件能承载该策略,因为它描述的是一份受管理的配置,而不是连接时的提示。它可以指明域名、服务器,以及该域名不可达时应当如何处理。这就是设置与契约的区别。

在受管理的 Apple 设备上,这通常通过一份携带域特定 DNS 设置的配置描述文件下发。这与 WireGuard 配置文件是不同的机制,两者只有在客户端尊重该描述文件时才能共存。在假设两个产品行为一致之前,先确认你的客户端实际上怎么称呼这个字段。Mac 上的 wg-quick 脚本和 iPhone 上的 WireGuard 应用读取类似的命令行,并通过不同层次安装它们。

读已安装的设置,而不是配置文件

在 Mac 上你可以检查系统最终得到什么,这比重新读你写的文件更有信息。解析器列表显示哪些服务器配置给了哪些域名,带作用域的查询显示哪一个胜出。把这一行搞坏的客户端会在这里显示,而不是在你写的文件里。iOS 上没有等效的命令行,所以那里的证据是结果:一个通过隧道解析的私有名称,以及一个其答复能揭示哪台解析器作答的公共名称。

scutil --dns | grep -A3 resolver
networksetup -getdnsservers Wi-Fi

这两条命令会打印当前的解析器配置和活动服务的 DNS 服务器。如果隧道解析器显示为没有域名限制的默认解析器,那么配置所做的正是客户端要求的。要修就改机制,而不是再加一个后缀,指望行为会改变。

相关文章