The Situation:
Your workstation/server has both a network connection to the local network with internet access, and a public IP address (or a second, different LAN/WAN/DMZ) on a separate interface. You’d like to run some services, perhaps the Apache web server, and serve them via the public IP address you have directly on your NIC, but still use the LAN connection for everything else. Or maybe you just want to be able to ssh directly to your workstation from home, without forwarding a port on the main firewall. Whatever you want to serve on the public IP address, this is how you can do it.
Warning: If you have a public IP address on your workstation, be sure to apply the proper firewall and security measures! Your workstation will be directly accessible from the Internet! If your workstation is compromised, an attacker will have a vector to your internal LAN though it.
The Solution:
We use the iproute2 extensions built into Ubuntu (And Debian. Other distros use it as well. YMMV) in order to set up a separate routing table for the second interface. This makes sure that requests hitting the IP address of the interface are replied to via that address, rather then through the default route (aka: the LAN). If you don’t do this, incoming connections are never answered.
We do this via the /etc/network/interfaces file. It’s possible to set up multiple interfaces exactly the same, but that is left as an exercise for the reader.
TL;DR:
Here is an example interfaces file:
auto eth1 iface eth1 inet static address 123.123.123.123 netmask 255.255.255.224 rtgateway 123.123.123.97 rttable 1 post-up ip route add $IF_NETMASK dev $IFACE src $IF_ADDRESS table $IF_RTTABLE post-up ip route add default via $IF_RTGATEWAY table $IF_RTTABLE post-up ip route add $IF_NETMASK dev $IFACE src $IF_ADDRESS post-up ip rule add from $IF_ADDRESS table $IF_RTTABLE post-down ip route flush table $IF_RTTABLE
This example makes use of variables set in the file itself to make it easier to change and improve readability. The ‘rttable’ variable must be incremented for each publicly routed interface you set up. If you want to make the ‘rttable’ variable more readable, you can define them in the /etc/iproute2/rt_tables file like this:
# # reserved values # 255 local 254 main 253 default 0 unspec # # local # Define your new/custom routing tables here: 1 ispA 2 ispB 3 ispC
Then you can set the ‘rttable’ variable in /etc/network/interfaces to ‘ispA’ instead of ‘1’. However, this is not necessary. It works just fine with numbers, and you can always put a comment in the interfaces file to document which interface is which, if you want to.
After you’ve set this up, and rebooted (or brought the interface up manually, this is Linux after all), you can view the new routing table and rule for the interface by running:
$ ip route show table 1 default via 123.123.123.97 dev eth1 255.255.255.224 dev eth1 scope link src 123.123.123.123 $ ip rule show 0: from all lookup local 32765: from 123.123.123.123 lookup 1 32766: from all lookup main 32767: from all lookup default
Here we see the routing table for eth1, as well as the rule that tells the system to use it for incoming connections to eth1’s IP address.