Linux流量路由问题:Server B无法通过Server A的IPsec VPN访问10.10.18.0/24网段
这种IPsec+路由转发的问题确实容易卡壳,我来帮你一步步排查:
首先,先明确你观察到的现象:Server B的ping包能通过Server A的VPN出去,目标主机也回复了,但Server A就是不把回复包转发给Server B。这里有几个核心点需要检查:
1. 确认IPsec策略是否允许转发整个网段的流量
很多时候IPsec配置默认只允许本地主机(Server A的10.10.19.1)和对端网段通信,而不是整个10.10.19.0/24。比如如果你用的是StrongSwan,得检查ipsec.conf里的leftsubnet参数是不是设成了10.10.19.0/24,而不是仅10.10.19.1/32。如果leftsubnet只包含Server A自己的IP,内核的IPsec策略会直接拒绝转发来自Server B的流量——哪怕你开了IP转发也没用。
2. 检查反向路径过滤(rp_filter)是否干扰了转发
Linux的反向路径过滤机制(rp_filter)会验证数据包的来源是否符合路由逻辑,如果开启了严格模式(值为1),可能会把从VPN接口收到的、目标是Server B的回复包判定为“非法”而丢弃。你可以先临时关闭试试:
sysctl -w net.ipv4.conf.all.rp_filter=0
之后再从Server B ping测试,如果能通了,就说明是这个问题。后续可以根据需要调整具体网卡的rp_filter值,而不是全局关闭。
3. 修正MASQUERADE规则的匹配范围
你加的MASQUERADE规则是针对所有源为10.10.19.0/24的流量,但可能没限定出口接口,导致规则没匹配到VPN出去的流量。建议修改成仅对VPN接口的出口流量做伪装:
iptables -t nat -D POSTROUTING -s 10.10.19.0/24 -j MASQUERADE # 先删掉旧规则 iptables -t nat -A POSTROUTING -s 10.10.19.0/24 -o <你的VPN接口名> -j MASQUERADE
替换掉<你的VPN接口名>(比如可能是ipsec0或者tun0,可以用ip link show查看)。然后用iptables -t nat -L POSTROUTING -v查看规则的数据包匹配数,如果有增长,说明规则生效了。
4. 确保FORWARD链允许流量转发
有时候iptables的FORWARD链默认会DROP流量,你需要明确允许Server B和VPN网段之间的双向转发:
# 允许从Server B所在网段到VPN的出站流量 iptables -A FORWARD -i ens8 -o <VPN接口名> -s 10.10.19.0/24 -j ACCEPT # 允许从VPN到Server B所在网段的回复流量 iptables -A FORWARD -i <VPN接口名> -o ens8 -d 10.10.19.0/24 -j ACCEPT
执行后再测试ping,看看是否能通。
5. 最后确认Server A的直连路由
虽然Server A和B在同一网段,但还是要确认路由表中存在10.10.19.0/24的直连路由:
ip route show | grep 10.10.19.0/24
如果输出类似10.10.19.0/24 dev ens8 proto kernel scope link src 10.10.19.1,就没问题;如果没有,得手动添加直连路由。
按照这个顺序排查,应该能找到问题所在。我遇到过好几次类似的情况,大多是IPsec策略没放开整个网段或者rp_filter的锅。
备注:内容来源于stack exchange,提问作者DBCL

