I would like to have multiple NICs (eth0 and wlan0) in the same subnet and to serve as a backup for the applications on the host if one of the NICs fail. For this reason I have created an additional routing table. This is how /etc/network/interfaces
looks:
iface eth0 inet static
address 192.168.178.2
netmask 255.255.255.0
dns-nameserver 8.8.8.8 8.8.4.4
post-up ip route add 192.168.178.0/24 dev eth0 src 192.168.178.2
post-up ip route add default via 192.168.178.1 dev eth0
post-up ip rule add from 192.168.178.2/32
post-up ip rule add to 192.168.178.2/32
iface wlan0 inet static
wpa-conf /etc/wpa_supplicant.conf
wireless-essid xyz
address 192.168.178.3
netmask 255.255.255.0
dns-nameserver 8.8.8.8 8.8.4.4
post-up ip route add 192.168.178.0/24 dev wlan0 src 192.168.178.3 table rt2
post-up ip route add default via 192.168.178.1 dev wlan0 table rt2
post-up ip rule add from 192.168.178.3/32 table rt2
post-up ip rule add to 192.168.178.3/32 table rt2
That works for connecting to the host: I can still SSH into it if one of the interfaces fails. However, the applications on the host cannot initialize a connection to the outside world if eth0
is down. That is my problem.
I have researched that topic and found the following interesting information:
When a program initiates an outbound connection it is normal for it to
use the wildcard source address (0.0.0.0), indicating no preference as
to which interface is used provided that the relevant destination
address is reachable. This is not replaced by a specific source
address until after the routing decision has been made. Traffic
associated with such connections will not therefore match either of
the above policy rules, and will not be directed to either of the
newly-added routing tables. Assuming an otherwise normal
configuration, it will instead fall through to the main routing table.
http://www.microhowto.info/howto/ensure_symmetric_routing_on_a_server_with_multiple_default_gateways.html
What I want is for the main route table to have more than one default gateway (one on eth0
and one on wlan0
) and to go to the default gateway via eth0
by default and via wlan0
if eth0
is down.
Is that possible? What do I need to do to achieve such a functionality?
Best Answer
Solved it myself. There seems to be very little information about the networking stuff that you can do with Linux, so I have decided to document and explain my solution in detail. This is my final setup:
First step: Create a new route table for every interface in
/etc/iproute2/rt_tables
. Let's call them rt1, rt2 and rt3Second step: Network configuration in
/etc/network/interfaces
. This is the main part and I'll try to explain as much as I can:If you type
ip rule show
you should see the following:This tells us that traffic incoming or outgoing from the IP address "192.168.178.99" will use the rt1 route table. So far so good. But traffic that is locally generated (for example you want to ping or ssh from the machine to somewhere else) needs special treatment (see the big quote in the question).
The first four post-up lines in
/etc/network/interfaces
are straightforward and explanations can be found on the internet, the fifth and last post-up line is the one that makes magic happen:Note how we haven't specified a route-table for this post-up line. If you don't specify a route table, the information will be saved in the
main
route table that we saw inip rule show
. This post-up line puts a default route in the "main" route table that is used for locally generated traffic that is not a response to incoming traffic. (For example an MTA on your server trying to send an e-mail.)The three interfaces all put a default route in the main route table, albeit with different metrics. Let's take a look a the
main
route table withip route show
:We can see that the main route table has three default routes, albeit with different metrics. The highest priority is eth0, then wlan1 and then wlan0 because lower metric numbers indicate a higher priority. Since
eth0
has the lowest metric this is the default route that is going to be used for as long aseth0
is up. Ifeth0
goes down, outgoing traffic will switch towlan1
.With this setup we can type
ping 8.8.8.8
in one terminal andifdown eth0
in another.ping
should still work because becauseifdown eth0
will remove the default route related toeth0
, outgoing traffic will switch towlan1
.The post-down lines make sure that the related route tables get deleted from the routing policy database (
ip rule show
) when the interface goes down, in order to keep everything tidy.The problem that is left is that when you pull the plug from
eth0
the default route foreth0
is still there and outgoing traffic fails. We need something to monitor our interfaces and to executeifdown eth0
if there's a problem with the interface (i.e. NIC failure or someone pulling the plug).Last step: enter
ifplugd
. That's a daemon that watches interfaces and executesifup/ifdown
if you pull the plug or if there's problem with the wifi connection/etc/default/ifplugd
:You can now pull the plug on
eth0
, outgoing traffic will switch towlan1
and if you put the plug back in, outgoing traffic will switch back toeth0
. Your server will stay online as long as any of the three interfaces work. For connecting to your server you can use the ip address of eth0 and if that fails, the ip address of wlan1 or wlan0.