自定义路由表中VPN网关失效问题的排查与解决
自定义路由表中VPN网关失效问题的排查与解决
问题背景
我最近在折腾把一个容器配置成路由器,目标是通过多个VPN连接实现负载均衡。思路是用概率标记初始数据包,让不同的数据包对应到不同的自定义路由表,从而分流到不同的VPN隧道。
我的配置步骤
1. 用iptables做数据包概率标记
通过mangle表的规则实现数据包的概率标记,同时确保同一连接的后续数据包复用之前的标记:
iptables -I PREROUTING -t mangle -j CONNMARK --restore-mark iptables -A PREROUTING -t mangle -m statistic --mode random --probability .50 -j MARK --set-mark 200 -m mark --mark 0 iptables -A PREROUTING -t mangle -j MARK --set-mark 201 -m mark --mark 0 iptables -A POSTROUTING -t mangle -j CONNMARK --save-mark
2. 创建并关联自定义路由表
给两个VPN隧道tun0和tun1分别创建专属路由表,然后添加规则让标记后的数据包使用对应表:
echo "200 tun0" >> /etc/iproute2/rt_tables echo "201 tun1" >> /etc/iproute2/rt_tables ip rule add fwmark 200 table tun0 ip rule add fwmark 201 table tun1
3. 给自定义路由表设置默认网关
为两个自定义路由表指定VPN网关:
ip route add default 10.7.7.1 dev tun0 table tun0 ip route add default 10.7.7.1 dev tun1 table tun1
4. 已配置的系统参数与NAT规则
为了确保路由转发正常,我已经设置了以下必要参数和NAT规则:
# 关闭反向路径过滤 echo 0 > /proc/sys/net/ipv4/conf/**/rp_filter echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter # 开启fwmark反射和IP转发 sysctl -w net.ipv4.fwmark_reflect=1 sysctl -w net.ipv4.ip_forward=1 # 给所有出口网卡配置NAT iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE iptables -t nat -A POSTROUTING -o tun1 -j MASQUERADE
遇到的奇怪问题
我确认路由表的选择逻辑是正常的——比如把主路由表的默认网关直接设为VPN网关10.7.7.1时,流量能正常通过VPN;但如果是通过自定义路由表tun0/tun1来选择VPN网关,tcpdump明明能看到流量发出去,却完全没有返回数据包,所有网络命令都失败。反而如果自定义路由表用非VPN网关10.10.10.1,流量就完全正常。
最终解决方案
在@A.B的提示下终于找到了问题根源:我的自定义路由表中缺少返回本地网络的路由规则,导致返程的数据包被错误地从VPN隧道发出去,根本回不到本地网络。
只需要给tun0和tun1的路由表分别添加本地网段的路由,问题就解决了:
ip r a 10.10.10.0/24 via 10.10.10.1 table tun0 ip r a 10.10.10.0/24 via 10.10.10.1 table tun1
这样一来,标记后的流量去程走VPN网关,返程的本地流量会通过正确的网关回到本地网络,整个链路就通了。
备注:内容来源于stack exchange,提问作者simonw
相关产品推荐
相关产品推荐

