一个网卡上的两台 DNS 服务器并不会划分命名空间
在同一个网卡上列出两个解析器,并不会让每个域各自拥有授权。应建立两条作用域规则、验证选择结果,并只删除这两条规则。
在同一个网卡上列出两个解析器,看上去能把一个域交给一台服务器、把另一个域交给另一台,但解析器列表中的任何内容都不是这样工作的。Windows 按名称解析,而向哪台服务器发问的决定来自策略对象,而不是来自一份有序的地址列表。需要替换的心智模型是队列:不存在“域 A 用第一台服务器、域 B 用第二台服务器”这回事。每个命名空间都有一套明确指定服务器的规则,一旦这些规则存在,网卡列表就不再重要。
误区:两个地址划分两个域
这种看法之所以流传,是因为当一台服务器恰好回答所有问题、第二台只是备用时,它碰巧能工作。客户端去问第一台服务器,那台服务器转发或递归,答案就回来了;没有人注意究竟是哪个解析器真正持有该区域。当两个命名空间位于彼此之间没有转发的独立私有区域时,这一错觉立刻破灭,因为第一台服务器会权威地回答该名称不存在。第一台服务器的否定回答不会触发备用,因为客户端收到的是确定答复,而不是故障。
有序列表没有域的概念,因此无法表达这一意图。列表真正控制的是先问哪台服务器、再试哪一台,而这两个答案对每个名称都同样适用。
Windows 实际用什么来选择
名称解析策略表把名称与已配置的命名空间进行匹配,并为该匹配选择服务器和选项。规则可以在本地配置、通过组策略下发,或由 VPN 配置文件提供,而生效策略是组合而不是单一列表。这就是为什么第一项诊断永远是生效状态:本地创建的规则若输给受管策略,就会造出一个与配置所示完全不符的实验环境。规则还按具体程度匹配,因此宽泛的命名空间条目可能以在已配置项列表中看不见的方式盖过狭窄条目。读取生效顺序是看清哪条规则胜出的唯一办法。
Get-DnsClientNrptRule
Get-DnsClientNrptPolicy -Effective
第一条命令列出机器上配置了什么;第二条显示客户端实际会应用什么,包括来自别处的条目。若生效输出中包含受管命名空间,正确的申请改动对象是那项策略的所有者,而不是本地规则列表。两条命令都只读取状态,因此在任何人同意改动之前运行它们不需要成本。
每个命名空间一条规则,并保留对象
理解生效状态之后,为每个命名空间建立一条规则,并保存每条命令返回的对象。显示名只是给人看的标签,返回对象中的唯一标识符才是之后可靠的删除目标。把两个标识符写进同一条变更记录,连同命名空间和解析器一起记录,因为创建它们的会话不会是负责清理的会话。
$svcRule = Add-DnsClientNrptRule -Namespace ".svc.internal.example" -NameServers "10.60.0.53" -DisplayName "VPN lab services" -PassThru
$resRule = Add-DnsClientNrptRule -Namespace ".research.internal.example" -NameServers "10.61.0.53" -DisplayName "VPN lab research" -PassThru
$svcRule | Select-Object Name, Namespace, NameServers
$resRule | Select-Object Name, Namespace, NameServers
开头的点表示后缀匹配,因此该规则覆盖 app.svc.internal.example 及其下的任何内容。这里的两个地址属于本实验环境自己的路由规划;规则不会创建区域、不会安装路由,也不会授权最终连接的应用,而 Add-DnsClientNrptRule 参考 精确说明了哪个参数起什么作用。
注意这些命令不做什么:它们是 全机生效的,并不局限于某次 VPN 会话,并且在关闭窗口后仍然存在。忘记这一点的实验环境会在隧道消失后把策略留在原处。
证明客户端确实选择了那台服务器
向某台特定服务器询问它是否认识某个名称,只能证明该服务器能回答,这与“客户端选择了那台服务器”并不是同一个命题。真正重要的测试是沿客户端常规路径解析一个真实名称,再确认是哪个解析器处理了它,最好在提供路由的隧道处于开启状态时进行。如果隧道已断开,作用域正确的规则仍会指向不可达的服务器,那是路由问题而不是策略问题。两种状态都要测试,以便日后区分。
Resolve-DnsName app.svc.internal.example
Resolve-DnsName build.research.internal.example
Resolve-DnsName app.svc.internal.example -DnsOnly -NoHostsFile
留意规则存在之前那段时间留下的缓存答案,也留意用自家加密 DNS 完全绕过系统解析器的应用。搜索后缀是另一项独立功能:规则可以为完整名称选择解析器,却不会教 Windows 把裸主机名扩展到该命名空间。
只删除你创建的东西
清理正是实验环境变成反面教材的地方。删除机器上的每一条规则很快,却会移走别人依赖的策略,因此要使用创建规则时捕获的标识符,之后再读一次生效状态,确认机器回到了起点。如果创建它们的会话已经不在,变更记录就是这些标识符唯一存在的地方。这就是要在第一条命令运行之前写下来、而不是事后再补的原因。
Remove-DnsClientNrptRule -Name $svcRule.Name -Force
Remove-DnsClientNrptRule -Name $resRule.Name -Force
Get-DnsClientNrptPolicy -Effective
对于部署而不是实验环境,生命周期问题与规则同样重要。VPN 配置文件可以携带命名空间规则,并 选择它们在连接结束后是否继续存在;在解析器不可达时仍然存在的规则会让客户端偏好一台死掉的服务器,而连接作用域的规则会随隧道一起消失。决定服务需要哪种行为,标明规则归谁所有,并把权限划分记录在配置文件旁边,而不是留在某人对实验环境的记忆里。