Using multiple ADSL IPs with Linux and iptables

Please note: This document assumes more than basic networking knowledge, although not too much more. If you don't understand some of the terms or concepts used, please make a good effort to find out yourself before emailing with questions, or be prepared for a beating.

When we moved to a sensible ISP for ADSL, we were offered the chance to have multiple real IP addresses. This is handy, since it gives us chance to have machines other than our internet gateway directly addressable from outside. Normally, using linux and iptables to do the address routing, you'd end up with 4 usable internal IP addresses from a block of 8.

Lets assume you normally use 192.168.0.0/24 internally, with the router assigned the IP address 192.168.0.1 internally, masquerading all outgoing traffic. We keep this working as normal, and assign the the external addresses to hosts in addition to the internal ones.

Lets also assume you've been allocated the address range 1.2.3.16/29 by your ISP - this gives you the addresses 1.2.3.16 to 1.2.3.23, which would normally be used like this:

This becomes a problem when you have 5 internal hosts that you want to assign external IP addresses, not including the machine acting as router. Fortunately, there's a nice convenient way around this.

ARP Proxying

ARP proxying is a convenient way of bridging 2 networks together - where you have 2 sides of a network (such as the internal public part of your network, and the external gateway), and you want packets to be transferred between them. Effectively, this means we can give the same IP to both sides of the router, freeing up another IP (.18 in this case) for internal use. It's also trivially easy to apply normal firewall rules with iptables using ARP proxying, which means the internal network is still protected by a firewall.

Got Firewall?

Firstly, and for the sake of sanity, you'll want a firewall. This is also a fairly convenient place to put the ARP proxying config. You can get a tidied up version of my current firewall script here. It's the same as we're currently using, only with the accounting stuff removed, and IP addresses changed to protect the innocent.

Secondly, you'll need iproute2 - under debian this is apt-get'able as 'iproute'. You'll also need appropriate kernel support.

To use this script, change the internal and external network ranges to whatever you're using (the script currently assumes 192.168.0.0/24 internally and 1.2.3.16/29 externally), and edit the section where allowed ports through to public addresses are defined.

Under debian, the best way to run this script is to have it called when the eth0 (or whatever your internal interface is called) device is brought up. Once you've edited the rc.firewall, save it as /etc/rc.firewall. Edit /etc/network/interfaces and add the following to the end of the eth0 section:

up /bin/sh /etc/rc.firewall

The edited section should look something like this:

auto eth0
iface eth0 inet static
    address 192.168.0.1
    netmask 255.255.255.0
    network 192.168.0.0
    broadcast 192.168.0.255
    up /bin/sh /etc/rc.firewall

I'm not sure of the best way to do this under other distros, but their online documentation, or google should be able to help you out.

Restart the ADSL and eth0 interfaces, and all should be well and good. Your public internal hosts can use 1.2.3.17 as their default gateway, once their external IP addresses have been assigned, and private internal hosts can continue to use 192.168.0.1.

If you already have a working firewall in place that you don't want to change much, the important bits for ARP proxying are:

echo 1 >/proc/sys/net/ipv4/conf/eth0/proxy_arp
/bin/ip addr add 1.2.3.17/29 dev eth0

Obviously, the firewall rules you'll want to apply to this range should be added to your existing firewall script.

Comments, questions, and corrections to ben@spod.cx.


Contact: site@spod.cx