OpenVPN 上的分离 DNS:路由域在每个系统上必须做什么
搜索后缀、路由域和 IP 路由是三件不同的事。先按平台设定策略,再证明到底是哪台服务器回答了查询。
每个分离 DNS 请求都以同一句话开头:公司名称交给公司 DNS,其余一切照常工作。把这句话变成配置,意味着要为每个操作系统回答三个问题,而每个系统的答案依赖的机制各不相同。在 Linux 笔记本上可用的配置文件,到了 Windows 上常常失败,原因与隧道毫无关系。两者的差距通常是把解析器设置误当成路由。
先为策略命名,再挑选能表达它的平台原语。
三个容易混淆的设置
搜索后缀会扩展短名称:输入files时,它就会变成files.corp.example,只要解析器按顺序尝试后缀。路由域决定命名空间内的查询由哪个解析器回答。IP 路由只负责让选中的解析器可达。这三者位于不同层次,把其中一个换成另一个,得到的配置看起来正确,却什么也解析不了。
混淆有代价:加上搜索后缀会把每个短名称都送去公司解析器,包括本属于别处的名称。选择路由域则让无关查询留在本地解析器,同时仍把*.corp.example通过隧道发出。
Linux:只做路由的域,而不是搜索后缀
在 systemd-resolved 上,带波浪号前缀的域是只做路由的域,意思是该命名空间的查询会交给关联的解析器,而不会同时变成搜索后缀。resolvectl domain tun0 '~corp.example'可以设置这一点,而resolvectl dns tun0 10.8.0.1则指定服务器。这两项设置都属于接口,因此会随接口一起消失。波浪号正是人们常漏掉的部分,没有它,短名称就会开始经由公司解析器解析。
不要把同一个域同时安装为全局搜索后缀。这两项设置并不冗余;一个负责路由,另一个改写你输入的内容。
Windows 需要命名空间策略,而不是后缀
Windows 把分离 DNS 策略保存在名称解析策略表中,而不是适配器的 DNS 后缀里。一条规则会把命名空间映射到特定服务器:Add-DnsClientNrptRule -Namespace .corp.example -NameServers 10.8.0.1。只设置后缀改变的是短名称的外观;它不会把查询发往另一台服务器。
连接之后,用Get-DnsClientNrptPolicy检查实际生效的策略,因为早先连接留下的规则可能比隧道活得更久。隧道断开时按名称删除规则,并保持显示名稳定,这样清理才能命中正确的条目。
每个平台只保留一个解析器负责人
桌面管理器、OpenVPN 的 up 脚本和本地解析器守护进程都可能试图写入同一份配置。当它们意见不一致时,最后写入者获胜,结果取决于拆除顺序。选一个组件负责解析器状态,让其他组件只报告而不写入,并测试一次重连:策略应当在重连后依然存在,且不重复规则。也要测试断开连接,因为残留状态正是让下次连接表现不同的原因。
自带加密解析器的应用会完全忽略操作系统的策略。那是应用本身的特性,而不是隧道的缺陷。
验证结果,而不是配置文件文本
在每个平台上分别解析一个应当走隧道的名称和一个不应当走的名称,并确认是哪台服务器回答的。resolvectl query host.corp.example和Resolve-DnsName host.corp.example都会报告作出响应的服务器。重连之后再重复一次。然后确认隧道的解析器在配置文件推送的地址上确实可达,因为指向不可达服务器的正确策略,失败方式与完全没有策略一模一样。
把预期行为记进配置文件的注释:哪个后缀走路由、哪台服务器回答它、其余一切会怎样。你要支持的下一个平台,需要这句话胜过需要配置文件本身。