LAN 路由器加 VPN 客户端:两台设备,两张路由表
路由器的下一跳只把数据包送到客户端。补上客户端的隧道路由、转发和回程路径,再从 LAN 主机实测。
两台设备各转一次包,也各留一张表。LAN 路由器知道远端前缀属于 VPN 客户端,VPN 客户端知道怎么经自己的隧道到达那个前缀。只配好第一张表,包就会落到一台没有匹配路由的机器上,再由默认路由发出去。整个故障就是这个,而从 LAN 一侧看像路由环路,因为大体上它就是。
动路由之前先把两跳画出来
取一个示意布局:LAN 主机在192.168.50.0/24,普通路由器在192.168.50.1,一台专用客户端在192.168.50.15,远端 LAN 在10.60.0.0/24,只能经那台客户端持有的隧道到达。 两个私有网段互不重叠,而隧道有自己的地址规划。
两个私有网段都关键,因为它们决定哪台设备能应答。远端看到包从客户端的隧道地址进来,回程就必须找到回到192.168.50.0/24的路。只配去程,请求可能通,响应却消失了。
第 1 步:把路由器指向客户端,而不是指向隧道
在 LAN 路由器上添加一条目的路由,下一跳是客户端的 LAN 地址:
ip route add 10.60.0.0/24 via 192.168.50.15
ip route get 10.60.0.55这条记录只说“交给那台能走隧道的机器”。它没说隧道怎么建,也不能代替客户端自己的路由。在受管路由器上,对应物在设备的静态路由页;在 Linux 路由器上,它属于拥有 LAN 的接口配置,而不是你关掉就没了的外壳。
看第二条命令的输出。如果它把客户端报成 gateway、把 LAN 接口报成 device,第一跳就对了,剩下的活在另一台机器上。
第 2 步:给客户端补一条隧道侧的路由
客户端现在收到发往10.60.0.0/24的包,查自己的表。如果隧道配置已经装好该前缀的路由,包继续加密前进。如果没装,包就匹配普通默认路由,退回192.168.50.1,再由它送回客户端。
加东西之前先看:
ip route show table all | grep -E "10\.60\.0\.0/24|default"
sysctl net.ipv4.ip_forward所有表里都缺这条前缀路由,正是你要找的结论。通过隧道自身的配置加上它,下次重连才会重新安装;手敲的ip route add会随会话消失,让故障在最不方便的时候回来。下一跳是隧道接口,或 VPN 分配的对端地址,视客户端而定,对端地址应取自当前配置而不是旧笔记。
环路真发生时其实不是无限的:每过一跳 TTL 减一,包最终以超时报文死亡。所以反复 traceroute 像是绕圈,而根本不转发的客户端只是静默丢弃同一个包。
第 3 步:放行转发,并选定回程
接收和转发是两种权限。客户端上的net.ipv4.ip_forward=1在内核层允许中转,防火墙规则仍要在 LAN 接口与隧道之间放行。只放行客户端自己的管理页,不等于放行去远端 LAN 的中转;当同一台主机在本地应答 ping 时,这个区别很容易被忽略。
远端有镜像问题。它必须知道192.168.50.0/24经这台通过认证的客户端可达。用 OpenVPN 时,这通常意味着服务器配置下发的按客户端路由,或服务器上声明客户端背后 LAN 的客户端专属文件。没有它,远端要么丢弃回包,要么发往自己的默认网关,也就是互联网。
LAN 前缀无法通告时,源地址转换是替代方案。客户端上加一条限定范围的 masquerade 规则,把源改写成隧道地址,回包就自然回来了。它也隐藏了是哪台 LAN 主机发起的请求,而且本身并不允许远端向内发起连接。要有意识地选这个取舍,而不是先加一条全量 masquerade、事后再发现副作用。
第 4 步:把两个决定都持久化,再测真实路径
每条路由都有归属,归属就是开机或重连时会重新生成的那份配置。路由器上可能是静态路由条目;客户端上可能是 VPN 配置、NetworkManager 或 systemd-networkd。验证时要重连隧道并重启客户端,然后重新读表,而不是相信那次编辑。
承载隧道外层连接的默认路由要保持完整。为了“简化”而换掉它,会在任何内层流量用上之前就打断加密路径,症状是改完之后隧道再也建不起来。
从普通 LAN 主机测,而不是从客户端测,因为客户端上发起的请求永远走不到路由器的第一跳。取一个只存在于远端 LAN 的服务并确认响应正文,然后看客户端计数器或日志确认中转确实发生。内层 traceroute 显示私有跳只证明转发,不证明加密:外层路径是另一项观测,只有隧道自身接口的计数器才说明什么从它出去了。