The proper way to to this is to bind() to the interface you want to use for outgoing packets. Since You can then set up routes with the ip route
and ip rule
commands to control how packets are routed based on their outgoing interface. For my example, I will assume the following network:
- eth0:
- Address: 192.168.0.2/24
- Default Gateway: 192.168.0.1
- eth1:
- Address: 192.168.1.2/24
- Default Gateway: 192.168.1.1
I will create two routing tables, one for traffic outgoing for eth0 called alternate and one table for eth1 called main. Routing table main always exists and is the normal table that is used by the route
and ip route
commands. Most people never deal with any other tables. To create the table called alternate, we will add the following line to /etc/iproute2/rt_tables
:
10 alternate
The table main has a default priority of 254. The rules for which routing table is in effect is controlled by the ip rule
command. By default, that command will print out a list of existing rules which should look something like this:
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
This basically says it will look for a route in the table local
which is a special table maintained by the kernel for local routes such as my own IP address. It will then try table main and table default. Table default is normally blank so if there's no match in main, there's no route to host. First, lets fill table alternate with rules for eth0.
sudo ip route add table alternate 192.168.0.0/24 dev eth0
sudo ip route add table alternate 192.168.1.0/24 dev eth1
sudo ip route add table alternate default via 192.168.0.1
You will normally want the alternate
table to look similar to the main
table. The only differences are when routing should be different. You may want not want to include the second line above if you literally want all NFS, HTTP, etc. traffic to go via the default gateway on eth0 even if it's destined for the network on eth1. Next step is to add a rule for when to use this alternate routing table:
sudo ip rule add from 192.168.0.0/24 pref 10 table alternate
This rule says any traffic coming from an address on the 192.168.0 network will use the alternate
routing table instead of the normal main
table. The last step is to make sure all clients that must use eth0
bind to it. With wget
, for example, set --bind-address=192.168.0.2
, for NFS set the clientaddr=192.168.0.2
mount option. If using LibWWW with Perl, you can set the localaddr option in LWP::UserAgent to control the local interface it binds to. If you happen to have a client you can't control the binding and compiling source is not an option, you might be able to use an iptables rule to modify it's address, but this is more of a hack and may not work. You would need a SNAT rule set up in the PREROUTING chain of either the nat table or the mangle table. You will still need the modified routing tables given above for this to work.