如何从 resolvectl 输出中读懂按连接的 VPN DNS 路由
resolvectl status 会按连接显示服务器、域和默认路由。把它们放在一起读,然后查询域名,并记下是哪个连接作答。
运行 resolvectl status,你会得到一堵按连接分块的输出,每个块都有自己的服务器和自己的域行。决定路由的是域列表,而不是名称服务器地址,因为本地 stub 会把每个查询转发给声明该域名的连接。先读这些声明,再读答案,然后查询域名,看是哪个连接产生了它。来自正确连接的错误答案,与来自错误连接的正确答案,是两种不同的问题。
每个按连接的块告诉你什么
每个块列出解析器将用于该接口的服务器、域列表,以及该连接是否为默认路由。域列表是一组声明,解析器按最长后缀匹配:对 host.corp.example 的查询会先被带有 corp.example 的连接认领,而不是只带默认路由的连接。两个连接声明同一后缀时,结果取决于优先级和顺序,因此重复项最值得先看。当前服务器那一行显示所列服务器中此刻正在使用的是哪一个。
/etc/resolv.conf 中像 127.0.0.53 这样的 stub 地址只说明 stub 在前面。它并没有指出作答的上游,因此仅凭 resolv.conf 的诊断会卡住。
正确读懂三类域条目
| 条目 | 声明什么 | 常见错误 |
|---|---|---|
| corp.example | 路由域兼搜索后缀:其下的名称走这个连接,并且该字符串会附加到裸名称后 | 因路由看起来照常工作而被删除 |
| ~corp.example | 仅路由:其下的名称走这个连接,但不附加后缀 | 被假定为路由所必需 |
| ~. | 默认路由:认领没有其他连接匹配的查询 | 在分流配置中被留着生效,于是公共名称走了隧道 |
波浪号改变的是搜索行为,而不是路由。没有波浪号的条目既是路由域又是搜索域,因此其下的名称会发往该连接,单标签名称会附加后缀。带波浪号的条目路由同一后缀,但把它排除在搜索列表之外。所以去掉波浪号会改变哪些裸名称能被解析,也所以缺少波浪号是搜索问题,而不是分流 DNS 的故障。
默认路由条目认领没有其他连接匹配的一切。全隧道配置通常需要它,分流配置通常不需要,因为公共名称那时会去往私有解析器,并可能在那里失败。要对照配置的意图来读这张表,而不是在配置之间复制标志。当两个连接声明同一后缀时,先把优先级问题解决,再改其他东西。
查询一个名称,看是哪个连接作答
query 子命令会打印地址、协议,以及产生答案的连接或作用域。测试一个应由私有后缀认领的名称和一个普通公共名称,然后比较报告的来源。如果私有名称从无线连接作答,说明声明缺失或隧道断开;如果分流配置中的公共名称从隧道作答,说明默认路由过宽。这两种失败在浏览器里看起来一样,在这个输出里却相反。
resolvectl status
resolvectl query host.corp.example
也要留意报告的协议,因为来自缓存或 hosts 文件的答案可能在没有询问任何上游的情况下到达。来自缓存的答案只证明该名称曾经被解析过,并不证明当前策略把它路由对了。
把名称路由与数据包路由分开
解析器的决定不会创造路径。被选中的服务器仍然需要通往其地址的路由,返回的地址也仍然需要进入私有网络的路由,因此正确的 DNS 策略可以与一条永不建立的连接并存。当名称解析成功而应用失败时,应当检查地址和路由,而不是再次改 DNS。名称解析与可达性是两个问题,有两个不同的负责人。
应用可以通过自己的安全 DNS 设置或内置解析器完全绕过系统解析器。resolvectl 的结果描述的是系统路径,而忽略它的浏览器会与你做的每一项测试相矛盾。在断定策略有问题之前,先检查那个设置。
把名称解析到的地址记在连接旁边。指向错误地址的正确名称是记录问题,而不是路由问题。
连接变化后重新检查
重新连接或切换无线会重建连接状态,网络管理器可能把手动设置的一切覆盖掉,重新安装自己的域和服务器。之后查询同样两个名称,并与记录的基线比较。如果手动修改消失了,修复应放在连接配置里,而不是 shell 命令里。正是前后记录让这一点可见。
只分享报告需要的名称和服务器背景,因为内部后缀会暴露拓扑。关于域路由的 systemd-resolved 文档涵盖了最长匹配规则和波浪号行为,读一遍就能避免上面表格里的大部分错误:systemd-resolved 中的查询路由。