给正在运行的站点间隧道添加第二个子网,在一种设计里只要五分钟,在另一种里几乎要耗掉整个下午。当隧道为你指定的前缀安装路由时,你加一条路由,流量就跟着走。当它只协商一对固定选择器时,新前缀会一直不受保护,直到两端就一对匹配的选择器达成一致。三件事决定你的处境:每一端的配置到底描述了什么、协商出的流量是否被收窄到最小的匹配对,以及新网段的回程路由归谁管。

看内核,不看状态标签

显示已连接的隧道至少装好了一个子级关联,但未必是你以为的那个。在 Linux 上内核会显示实际生效的内容:ip xfrm policy 列出选择器对,swanctl --list-sas(或更旧的 ipsec statusall)显示两端协商的结果,包括每个方向的流量选择器。如果新前缀在两处都不出现,那么无论配置文件怎么写,它都没有受到保护。

把它和路由表对照一下。在基于路由的设计里,隧道设备就是受保护前缀的下一跳。基于策略的设计往往没有针对远端子网的专门路由,只有默认路由,因为选流量的是策略而不是路由表。

基于策略:两端都必须列出新前缀

用 strongSwan 的说法,选择器位于子级配置的 local_ts 和 remote_ts 中,它们是 leftsubnet 和 rightsubnet 的后继。新前缀必须在两端镜像出现:站点 A 称作本地的,站点 B 称作远端的。不匹配很少给出干净的报错。两端会收窄到交集,旧前缀继续工作,只有新的那个静默失败。

swanctl --load-conns
swanctl --initiate --child <child-name>
swanctl --list-sas
ip xfrm policy

在 pfSense 或 OPNsense 上,这意味着新增第二条 Phase 2 条目,把新的本地子网和新的远端子网配对,然后再应用。保留旧条目;替换它会把原来的子网搬走而不是新增。如果已有的 Phase 2 已经覆盖了像 0.0.0.0/0 这样的超网或汇总网段,就不要在旁边再加更窄的条目:重叠的选择器会装上互相竞争的策略,评估顺序决定谁胜出。

IKEv1 把每对子网都做成自己的一条 Phase 2,而每次交换只接受一对的一端会丢掉其余部分。IKEv2 可以在一个子级里携带多个选择器对,但前提是两端的实现都接受。swanctl --list-sas 给出的列表才是事实;你输入的内容只是一个请求。

基于路由:路由本身就是策略

XFRM 接口或 VTI 设备按路由表转发流量。你在两个站点把新前缀指向该设备,绑定到接口变换的状态就会生效。这里没有需要同步的选择器对,所以随着子网增多,这种设计扩展性更好。strongSwan 的转发指南详细讲了内核侧。

ip route add 192.168.60.0/24 dev xfrm0
ip route get 192.168.60.10

WireGuard 把这一思路推得更远。AllowedIPs 既是加密白名单,也通过 wg-quick 成为路由表条目。只在一端加前缀,你会得到握手、出向数据包和沉默,因为远端会丢弃源地址不在其白名单里的包。wg set 这种写法会替换整个列表,所以要把原本能用的前缀重新写一遍,否则就会把它们切断:

wg set wg0 peer <PUBKEY> allowed-ips 192.168.10.0/24,192.168.60.0/24
ip route add 192.168.60.0/24 dev wg0

当你用 wg set 而不是 wg-quick 时,第二条命令不是可选项。内核会立即接受新白名单,但没有任何东西为它添加路由,因此本地产生的流量仍然从默认网关出去。这就是新的 WireGuard 子网从隧道主机能用、从笔记本不能用的最常见原因。

回程路由比隧道更容易出问题

新远端子网里的主机必须通过 VPN 网关回包。当这个网关不是它们的默认路由器时,回包会送到 LAN 路由器,后者要么丢弃,要么带着私有源地址转发到互联网。要从远端主机而不是从网关测试:Linux 上的 ip route get 10.30.20.15 或 PowerShell 里的 Find-NetRoute -RemoteIPAddress 10.30.20.15 会显示主机真正使用的下一跳。如果答案不是隧道的端点,就在那里为新前缀加一条静态路由。

在缺少回程路由的一侧做源 NAT 是正当的替代方案,也是许多 hub-and-spoke 部署避免逐台服务器改动的方式。在目的侧网关上也要对新前缀应用它:

iptables -t nat -A POSTROUTING -s 10.30.20.0/24 -d 192.168.60.0/24 -j MASQUERADE

代价是真实存在的。远端日志不再显示单独的源地址,而针对原子网的防火墙规则会合并成针对网关的一条规则。要有意选择它,而不是因为缺了一条路由。

防火墙是回程路由的另一半。基于区域的设备不会自动把现有隧道接口的区域扩展到新子网,而针对旧前缀写的规则也不会匹配。在指责 IPsec 之前,先把新子网加入区域或双向规则对。

用三个问题定夺,再用流量验证

简版:端配置是点名前缀(基于策略),还是把流量路由进某个接口(基于路由)?两端都列出了新前缀吗?从新子网回到原始源网段有路可走吗?

Tunnel styleWhere the prefix goesWhat breaks if you skip it
Policy-based IPsecSelector pair on both peersOld subnets work, the new one fails with no clear error
Route-based XFRM or VTIRoute into the device on both sitesPackets routed but not transformed, or the state never matches
WireGuardAllowedIPs on both peers plus a routeHandshake succeeds, replies are dropped
Overlapping supernetAdjust the existing entry insteadA shadowed policy wins or loses by evaluation order

验证正是大多数改动被过早收尾的地方。从网关 ping 证明力很弱,因为网关从自身发出,往往匹配的是与主机不同的策略。从新子网里的主机 ping,然后运行促使你改动的那套应用,并且看计数器而不是状态图标。

tcpdump -ni any host 192.168.60.10 and (esp or udp port 4500)
ip xfrm state
wg show

在基于策略的隧道上,ip xfrm state 的计数器应该双向增长;计数不动说明包被路由了但没被选中。在 WireGuard 上,wg show 会报告每一端的传输量,收到零字节的握手则指向远端的白名单或其回程路由。

最后把前缀、该端的选择器或路由、回程路由的决定以及防火墙条目,连同隧道清单的其余部分记录下来。然后重启一台网关再测一次:手工加的路由会消失,下一个人不该再重新发现这件事。

相关文章