How to set up two default routes in linux
TL;DR
How to set up two default routes in linux (corresponding to two interfaces), such that incoming traffic from both interfaces is accepted.
Scenario
I have a host having two NICs eth0
and eth1
. Its connected to two networks, say:
Dev:
eth0
, IP:1.1.1.4
, Netmask:255.255.255.0
, Gateway:1.1.1.1
Dev:
eth1
, IP:2.2.2.4
, Netmask:255.255.255.0
, Gateway:2.2.2.1
(Both networks are connected to the internet.)
The routes are (ip route show
):
default via 1.1.1.1 dev eth0 metric 1
default via 2.2.2.1 dev eth1 metric 2
1.1.1.0/24 dev eth0 src 1.1.1.4
2.2.2.0/24 dev eth1 src 2.2.2.4
(Lower metric means higher priority.)
Now when someone pings 2.2.2.4
from some external host (say 4.4.4.4
), there is no reply.
The output of tcpdump -i eth1
on my host is:
22:41:27.431539 IP 4.4.4.4 > 2.2.2.4: ICMP echo request, id 8625, seq 4, length 64
22:41:28.439492 IP 4.4.4.4 > 2.2.2.4: ICMP echo request, id 8625, seq 5, length 64
22:41:29.447666 IP 4.4.4.4 > 2.2.2.4: ICMP echo request, id 8625, seq 6, length 64
22:41:30.455528 IP 4.4.4.4 > 2.2.2.4: ICMP echo request, id 8625, seq 7, length 64
After some research, it turns out that when linux network stack receives a packet from 4.4.4.4
, it checks its routing table to see what interface should have been used for 4.4.4.4
(which is eth0
in the routing table). Now, since the packet came from eth1
interface, linux simply discards it (This policy is probably to prevent IP spoofing).
What I want is is:
Outgoing traffic (locally originated) should use
eth0
interface by default.Incoming traffic should be accepted from both interfaces. (So
4.4.4.4
should be able to ping both1.1.1.4
and2.2.2.4
)
Solution 1:
Using iproute2 you can do something like this:
echo "1 admin" >> /etc/iproute2/rt_tables
echo "2 users" >> /etc/iproute2/rt_tables
ip rule add from 192.168.122.40/32 dev eth0 table admin
ip rule add from 192.168.123.41/32 dev eth1 table users
ip route add default via 192.168.122.1 dev eth0 table admin
ip route add default via 192.168.123.1 dev eth1 table users
Now you will have two routing table with two gateways.
Solution 2:
This phenomena is called unicast rpf (reverse path forwarding) as a standard but reverse path filter in Linux. You may disable this without any important negative consequences (unless you're an isp.. and a router).
echo 0 > /proc/sys/net/ipv4/conf/default/rp_filter
Then your example should work as you want it to.
Solution 3:
In case your application binds to 0.0.0.0
it is also required to add rules like:
ip rule add from 0.0.0.0/32 to 192.168.122.0/24 dev eth0 table admin
ip rule add from 0.0.0.0/32 to 192.168.123.0/24 dev eth1 table users