macOS 的服务顺序并不控制你的 VPN 路由
服务顺序只在普通接口之间做选择。VPN 本就排在它们之上,而它包含的路由来自配置文件,不来自那份列表。
网站上出了问题,同事想起还有服务顺序,于是把 Wi-Fi 拖到以太网上面。什么都不会改变,因为那份列表从来没有决定过 VPN 目的地往哪里走。Apple 让 VPN 连接优先于普通连接,并把它们排除在这次重排之外,所以这个开关回答的是一个比所问问题更窄的问题。故障需要的是被选中的路由和解析器,而不是一个新的排序。
服务顺序改变什么,又从不触碰什么
“设定服务顺序”位于系统设置、网络的操作菜单中,它在两条或更多普通连接同时活跃时对它们排序。这个排序选出主服务,由它提供默认路由和一部分解析器行为。这是同等接口之间的取舍,不是通往隧道后方专用目的地的开关。同时有 Wi-Fi 和 USB 以太网适配器的笔记本用它来回答一个合理的问题,而那个问题与隧道无关。
VPN 配置文件带有包含的路由、排除的目的地,有时还有按应用的规则,这些才决定什么进入隧道;排序菜单并不编辑它们。正因如此,分离隧道的配置文件可以把公共流量留在外面,而 VPN 仍然高于每一个物理接口。把 Wi-Fi 拖到最上面既不能让专用网段变得可达,也挡不住配置文件已经包含的目的地。列表移动的是接口,配置文件移动的是前缀。Apple 在其网络服务顺序页面上记录了这条优先级,在你重新排序任何东西之前值得读一遍。
读取机器实际选择的路由
用 route get 10.20.4.10 询问机器某个地址走向何处,再用 route -n get -inet6 2001:db8::10 对 IPv6 重复一次。这两个协议族是彼此独立的决定,所以一条能用的 IPv4 路由对 v6 什么也说明不了;直连子网或更具体的前缀无论如何都会压过通用的连接标签,这正是该标签一直误导人的原因。
如果输出点名了隧道接口,说明配置文件捕获了该目的地,排序就无关紧要。如果点名的是物理接口,说明配置文件没有捕获,再怎么拖也不会改变前缀表。两种输出还都会点名机器将使用的源地址,这正是比较两次运行时应当引用的字段。在改动任何东西之前先保存输出,因为那是你事后唯一会有的证据。
DNS 按名称解析,而不是按接口
带作用域和域特定的解析器意味着答案可能随名称而不同,而不是随接口。scutil --dns 会打印系统实际使用的解析器配置,包括带作用域的条目。服务顺序影响哪个服务提供默认解析器,但针对名称的作用域仍然可能胜出。
这就是为什么 ping 一个地址能通、主机名却失败,或者恰好相反。在判定元凶之前,先读这两份输出。
修改配置文件,然后重新读取两份输出
当目的地策略需要改变时,所有者是 VPN 配置文件:包含的路由、排除的路由,以及厂商支持的分离隧道规则。改接口只是把争论挪个地方。在远程管理的 Mac 上,要先保存当前网络状态,因为在够不到的机器上丢掉隧道,那叫出差,不叫回滚。
复现故障,读路由,读解析器,只改一处,然后再读同样这两份输出。一次打乱多个服务和配置文件,留下的机器没人能解释,包括修好它的人。当两份输出都与你想做的改动一致时,测试才算结束。如果它们仍然对不上,说明配置文件与机器在描述两套不同的策略,而该改的是配置文件。