Change the default route without affecting existing TCP connections

3

2

Let's say I have two public network addresses on my server: one NAT through an ISP (192.168.99.0/24), and a VPN through a different ISP (192.168.1.0/24), already configured with a per-host route to the VPN server through my ISP.

Here is my initial routing table. I am currently routing through my ISP on subnet 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

Now, I want new TCP connections to switch to my 192.168.1.0/24 so I type the following:

$ route add -net 0.0.0.0 gw 192.168.1.1 dev tap0

When I do this, it causes some long-standing TCP connections to hang. Is there a way to I safely change the default interface for new connections, while allowing existing TCP connections to use the old route (i.e. do I need enable some sort of stateful routing table)?

I am okay with a solution that only works with established TCP connections, and I don't care how hacky it is. For example, if there is a way to add temporary iptables rules for existing connections to force them over the old route. But there has to be some way to do this.

EDIT: Just a note about a simple "route add -host ... " for existing connections: this solution would work if I am fine with leaving a subset of IPs on the old interface. However, in my application, this actually doesn't solve my problem because I want to allow new connections to come on the new interface even if they have the same source IP. I'm now looking at using the "ip route" command to set source-based routing rules.

Patrick Horn

Posted 2012-11-26T08:31:22.370

Reputation: 41

You should really fix it correctly forever and use source-based (policy) routing. – David Schwartz – 2012-11-26T09:42:09.863

@DavidSchwartz Cool! This is exactly the sort of answer I was looking for. I honestly didn't even know that such a concept existed: Indeed I should have been looking at "ip route" rather than plain old "route"--I forgot about this completely.

If you respond formally to the question with a way to enable source-based routing or more specifics on the types of ip commands that could create simple source-based routing tables, I'd be happy to accept the answer. – Patrick Horn – 2012-11-27T07:59:01.390

Answers

1

The following command will examine open tcp connections, and list the destinations outside of the local network:

$ 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

So we just need to iterate through this list, and put specific routes toward the main router before changing the default route:

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

(I have left the "echo" command in there so you can see what it does, you can remove this when you want to actually do it.

Then change your default route:

$ route add -net 0.0.0.0 gw 192.168.1.1 dev tap0

Because the routes added are more specific, they will be taken in preference to the default route. Obviously you can put this in a script to make it easier.

Paul

Posted 2012-11-26T08:31:22.370

Reputation: 52 173

The routing table solution would work if I am fine with leaving a subset of IPs on the old interface. However, in my application, this actually doesn't solve my problem because I want to allow new connections to come on the new interface even if they have the same source IP.Also, I asked this question partially because I was hoping for the possibility of a less crude approach. – Patrick Horn – 2012-11-27T07:51:50.860

@PatrickHorn It is worth editing your question to clarify this, as that other people looking to help may not find this comment – Paul – 2012-11-27T09:52:05.040