客户机 VPN 与宿主机 VPN:究竟哪条路由真正生效
两个客户端、两条默认路由和一个令人困惑的症状。先记录客户机的接入方式,再追踪它向外走的端点,然后每次只改一个变量。
两个客户端同时运行,各自都认定自己拥有默认路由,症状却呈现出奇怪的样子:客户机上的一个应用正常,另一个却解析到了错误的位置。客户机内的 VPN 与宿主机上的 VPN 可以共存,但前提是外层路径与内层策略对“谁承载什么”达成一致。同时启动两者本身并不会形成链路。先记录接入方式,再每次只改一处。
先记录客户机的接入方式
客户机通过虚拟化平台分配给它的路径访问自己的 VPN 服务器:宿主机身后的 NAT、桥接到物理网段,或者在其上叠加了路由的仅主机网络。每种接入方式都会改变客户机能看到什么,以及宿主机能对它的流量做什么。在 NAT 之下,客户机的数据包看起来来自宿主机,因此宿主机自己的隧道可能在客户机毫不知情的情况下承载它们。在桥接模式下,客户机在网段上有自己的存在和自己的默认网关。
在触碰任何配置之前,先把接入方式写下来,并写清楚哪个客户端应当承载哪个应用。这句话能解决其中大多数工单,因为两个客户端通常建立在不同的假设之上。一个被期望使用宿主机隧道的客户机,不应同时拥有自己的竞争性默认路由。
追踪客户机向外走的端点
客户机 VPN 需要一条可用的、通往自己服务器的路径,其他任何事情才可能成立。当宿主机隧道处于开启状态而客户机位于 NAT 之后时,客户机的握手会经宿主机隧道发出,这要么是设计本意,要么是没人记录过的意外。当宿主机隧道断开而客户机依赖于它时,客户机一侧没有任何改动就会失去连接。向外追踪端点,就能判断你实际属于这两种情况中的哪一种。
任一环境下的一条宽路由都会捕获另一个客户端所期望的流量。客户机内的 0.0.0.0/0 路由与全隧道宿主机客户端都主张接管一切,最后生效的那条获胜。客户机虚拟网络、本地 LAN 与远端网络之间的重叠,对私有前缀会产生同样的效果,其故障表现与认证问题相似;地址转换的行为与 容器网络 中描述的相同。
对比变更前后的记录
在宿主机隧道关闭、或你的策略所允许的任何受控状态下取一个基线,并记录客户机的路由与解析器。然后应用组合配置并对比两份记录,同时保持隐私要求不受破坏。如果直接取基线并不合适,就把这一限制写进记录,而不是跳过对比。
ip route get 10.20.30.41
ip rule show
resolvectl status --no-pager | head -12
路由查询会指出承载某个特定目的地的接口与源地址,这是本次排查中最有用的一行。规则列表显示策略路由是否把某些目的地送往第二张表。解析器的输出显示 DNS 是跟随了客户机隧道,还是留在宿主机的路径上。在变更前后各跑一遍同样的三条命令,差异就会指出元凶。
在多次重启之间保持归属清晰
宿主机客户端的本地访问限制可能会阻断通往虚拟 NAT 或桥接的流量,而这一限制经常被误认为客户机的凭据问题。应当阅读客户端有文档记录的行为,而不是为了让测试通过就关闭该限制。在做受支持的修正之后,重新测试客户机应用和你所需的失败策略。宿主机成功重连,并不能证明客户机的路由或解析器没有问题。
决定默认路由归哪一侧所有,并把它写进运行手册。客户机重启或宿主机切换网络若在无声中反转了归属,就会产生一份针对从未出错的 VPN 的缺陷报告。这套安排应当能在无人记得它为何有效的情况下经受住一次重启。