FortiClient 全隧道:只路由办公子网
VPN 装上默认路由后本地网络就消失了。先读路由表,恢复 LAN 默认路由,再加入办公网段前缀,最后修 DNS。
隧道起来了,图标变绿,本地网络却消失了:打印机、NAS 和办公室路由器全都不再响应。FortiClient 只是按配置文件办事。网关下发了默认路由,客户端把它装上,于是每个数据包都有了一条通往隧道的路径。修复办法是改路由表,随后再改 DNS,而这两步的先后顺序决定了这台机器最后是变好还是变坏。
客户端装了什么,以及 LAN 为何消失
先读路由表,而不是看客户端界面。macOS 上netstat -rn会打印整张路由表,route -n get default会指出当前胜出的接口和度量值;Linux 上对应的是ip route show和ip route get 8.8.8.8。两者都回答同一个问题:一个不与任何更具体条目匹配的数据包,会由哪条路由来承载。
隧道设备的名字并不固定。macOS 上的 IKEv2 配置通常显示带编号的utun,SSL VPN客户端显示ppp0,OpenVPN 则显示tun0。两条默认路由也可能同时存在、度量值不同,而客户端那条记录也许要等到重新连接之后才接管,而不是在它出现的那一刻。这就是为什么相隔五分钟抓的两份路由表会讲出不同的故事。
为什么隧道默认路由必须先删
内核选择最长匹配前缀,当多条路由同样具体时,选度量值最小的那条。因此装了度量值更优的0.0.0.0/0的客户端会赢下所有目的地,却不删除原来的默认路由,这就是物理路由仍然留在表里、也仍然能解释故障的原因。先删掉隧道的默认路由,才能恢复原来的行为。只有在这之后,经由隧道的前缀路由才会按作者的本意生效。
在这一步之前就加前缀,正是制造半好机器的错误。新前缀的流量走隧道,而所有未列出的流量同样走隧道的默认路由,于是在有人打开一个谁都没加过的服务之前,什么都不像坏了。先删、再恢复、然后才添加,中间状态才保持可预期。
macOS 与 Linux 上的操作顺序
在 macOS 上,这个顺序是删掉隧道默认路由、恢复物理默认路由,再把一个办公前缀送回隧道。请把这里的示例接口名换成你自己表里的名字。
sudo route delete -net default -interface utun4
sudo route add -net 0.0.0.0 -interface en0
sudo route add -net 10.20.0.0 -netmask 255.255.0.0 -interface utun4在 Linux 上,同样的顺序换一套工具:默认路由用 LAN 网关,办公前缀用隧道设备。旧的route命令仍然接受老语法,但ip route才是与当前文档一致的形式。
sudo ip route del default dev tun0
sudo ip route add default via 192.168.50.1
sudo ip route add 10.20.0.0/16 dev tun0当路由需要的是下一跳而不是设备时,从客户端输出里取 peer。猜错会得到两种错误之一,含义并不相同:网关错会立刻给出 network unreachable,隧道目标错则给出超时。再改命令之前,先读清楚你拿到的是哪一种。
前缀、解析器,以及始终不通的 DMZ
一个前缀很少能覆盖全部工作。应用服务器、管理网、DMZ 以及 DNS 服务器本身可能各在不同的网段,所以动手前先把能叫出名字的网段全列出来,并在每次 ping 旁边测一次解析。测试途中才发现的地址,恰恰是最容易在变更记录里被忘掉的那个。能按地址通、按名字不通的路由,通常是解析器问题披着路由的外衣。
解析器是另一个独立决定。当配置下发的是内部 DNS 服务器时,去掉默认路由可能让这些地址对公网域名不可达,或者只能经隧道访问,两种状态都会给出令人困惑的部分结果。把解析器地址经由隧道路由,或者按域名分别配置解析,让公网查询走本地解析器。
Linux 的 SSL 客户端有一种值得了解的字段级故障:隧道连上了,办公 LAN 也通,但某个 DMZ 网段始终不通。缺的是把这个网段指向隧道网关的路由,而网关在不同机器上并不相同,所以硬编码地址正是下一台笔记本出事的方式。从客户端状态里推导出它,并让命令自带说明:
PEER=$(ip -4 addr show dev ppp0 | awk '/peer/ {print $4}' | cut -d/ -f1)
sudo ip route add 192.168.30.0/24 via "$PEER"运行之前先读这两个值。peer是点对点隧道的远端,DMZ 路由需要的正是这个地址;在路由型隧道里,等价物是客户端报告的接口或网关。如果两者都没出现,说明客户端并不在你以为的模式里。
下一次连接之后,以及何时不该在本地继续这么做
FortiClient 在休眠或网络变化后会重新连接,并把配置里规定的东西再装一遍。所以手工路由只能撑到下一次连接,而这恰恰是一次成功测试看起来像修复的那段时间。隔夜就消失的路由是预期行为,不是新故障。
有两种长期解法。每次连接后重跑修正脚本是一种可能比作者活得更久的绕行方案;而由网关管理员下发的拆分隧道配置才是真正的修复,因为那样客户端只安装工作需要的网段。去申请后者,前者只在等待期间使用。在本地拆分全隧道之前,也要检查你已同意的策略,因为远端网络可能依赖看到你的全部流量。
清单很短:读路由表,删掉隧道默认路由,恢复 LAN 默认路由,加上每个前缀,单独修好解析,并且预期重连后路由会回来。