连上 VPN,打印机就消失了,NAS 共享打不开,连到旁边那台机器的远程桌面会话也会超时。没有任何东西坏掉。客户端加了一条默认路由,于是笔记本能叫出名字的每个目的地都归它管,包括三米之外的那台。这就是全部机制,把它叫作 VPN 故障,正是把一行修复变成工单的原因。

先读路由表

在改动任何东西之前,先用 route print -4 抓一份 IPv4 路由表并保存输出。连接后重新抓一次,比较 0.0.0.0 这几行:生效的默认路由指向某个接口,如果那个接口就是隧道,本地打印和浏览就先被送去办公室了。

第二列的接口编号是持久路由以后必须引用的值,所以趁隧道还连着就记下来。它也是适配器重建时会改变的值,正因为如此,固定在该接口上的路由会悄悄失效。

清掉默认路由,有三种办法

在 Windows 内置配置文件上,控件是一个复选框。打开连接的属性,进入 IPv4,再点高级,取消勾选Use default gateway on remote network;较新的“设置”应用把同一个对话框藏得更深一层。在提升权限的命令提示符里,同样的改动是一条 cmdlet:

Set-VpnConnection -Name "Corp" -SplitTunneling $true

一个 OpenVPN 配置文件的工作方式不同,所以它的行为会让期待复选框的人困惑。它的 redirect-gateway def1 指令根本不替换默认路由;它安装两条半区路由,0.0.0.0/1 和 128.0.0.0/1,这两条合起来胜过默认路由,却没把它删掉。由于原来的默认路由还在,加一条指向 net_gateway 的前缀,只会把那一条前缀送回本地路由器。这个细节解释了为什么 def1 配置的修复办法是前缀路由,而不是一个谁也找不到的复选框。

只把属于工作的部分加回来

默认路由没了,隧道就什么都不承载,所以必须明确写出工作网段。把前缀绑定到连接上的 cmdlet 比持久路由更安全,因为它只在该连接处于连接状态时安装,也不依赖接口编号:

Add-VpnConnectionRoute -ConnectionName "Corp" -DestinationPrefix 172.20.0.0/16

较老的做法仍然有效,也仍然出现在每份清单里:route -p add 172.20.0.0 mask 255.255.0.0 172.20.0.1 if 14,并带上隧道自己的接口索引和网关地址。它能跨重启保留,这既是目的也是风险,因为下一次启动时那个索引可能已经属于别的东西。

其余由跃点数决定。如果物理网卡和隧道网卡都声称拥有同一网段的路由,跃点数更低的一方获胜,而调高隧道的跃点数是合理的客户端侧控制,不是取巧。

当服务器替你做决定

无视你那个复选框的客户端,通常是在服从一条策略。Cisco 配置文件带有Allow Local LAN Access 设置,而头端可以下发 tunnel-all 策略,覆盖客户端的任何偏好;在强制隧道部署里,本地根本没有开关可翻。与其反复检查同一个对话框,不如去读客户端日志里下发的路由和策略行。

接着看名称解析,它是与路由分开的另一个开关。分离隧道仍可能拿到内部解析器和搜索后缀,所以本地设备用地址能通、用名字却找不到,直到 DNS 侧也修好为止。

重叠是另一个问题

如果家里的 LAN 和办公室的 LAN 共用 192.168.0.0/24 这样的网段,没有任何路由能把它们区分开。该范围的每个数据包只有一个查表结果,解决办法是给一侧重新编号,或者通过地址池转换后的地址访问办公室。加更具体的路由,只会移动网络哪一半出故障。

最后用一次验证收尾,而不是五次:连上,然后tracert 对内部主机和公网主机各跑一次。第一跳应当不同;如果相同,不论客户端报告什么,分流都没有生效。然后重连一次再重复,因为下发的路由每次会话都会回来。

相关文章