假设我的服务器上有两个公共网络地址:一个通过 ISP 的 NAT(192.168.99.0/24),另一个通过另一个 ISP 的 VPN(192.168.1.0/24),并且已经通过我的 ISP 配置了到 VPN 服务器的每个主机路由。
这是我的初始路由表。我目前通过 ISP 在子网 192.168.99.0/24 上进行路由。
$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.99.1 0.0.0.0 UG 0 0 0 eth1
55.66.77.88 192.168.99.1 255.255.255.255 UGH 0 0 0 eth1
192.168.99.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 tap0
现在,我想要新的 TCP 连接切换到我的 192.168.1.0/24,因此我输入以下内容:
$ route add -net 0.0.0.0 gw 192.168.1.1 dev tap0
当我这样做时,会导致一些长期存在的 TCP 连接挂起。有没有办法可以安全地更改新连接的默认接口,同时允许现有 TCP 连接使用旧路由(即我需要启用某种有状态的路由表)?
我可以接受只适用于已建立 TCP 连接的解决方案,我不在乎它有多老套。例如,如果有办法为现有连接添加临时 iptables 规则以强制它们通过旧路由。但必须有一些方法来做到这一点。
编辑:关于现有连接的简单“route add -host ...”的说明:如果我愿意在旧接口上保留一部分 IP,此解决方案将有效。但是,在我的应用程序中,这实际上并不能解决我的问题,因为我想允许新连接进入新接口,即使它们具有相同的源 IP。我现在正在考虑使用“ip route”命令来设置基于源的路由规则。
答案1
以下命令将检查打开的 TCP 连接,并列出本地网络之外的目的地:
$ netstat -4ntu | tail -n +3 | cut -c45-65 | cut -d: -f1 | grep -v '192.168.99' | grep -v '192.168.1'
214.236.220.101
63.171.235.16
174.63.61.132
159.47.216.178
62.59.197.29
139.47.218.150
56.4.17.22
204.63.49.5
155.9.79.196
144.31.207.66
因此,我们只需要遍历此列表,并在更改默认路由之前将特定路由放置到主路由器:
for i in $(netstat -4nt | tail -n +3 | cut -c45-65 | cut -d: -f1 |grep -v '192\.168\.99' | grep -v '192\.168\.1') ; do echo route add -host $i gw 192.168.1.99; done
(我把“echo”命令保留在那里,以便您可以看到它的作用,当您真正想要执行它时,可以将其删除。
然后更改您的默认路线:
$ route add -net 0.0.0.0 gw 192.168.1.1 dev tap0
由于添加的路由更具体,因此将优先采用这些路由而不是默认路由。显然,您可以将其放入脚本中以使其更简单。