To share a public IP address between two or more servers using iptables.
Suppose that you have three machines, a mail server, a web server and a DNS server, but only one public IP address. You have chosen to give the public address, which is 203.0.113.1, to the DNS server. All three machines are connected via a local area network on which the DNS server is 192.168.0.1, the mail server is 192.168.0.2 and the web server is 192.168.0.3/24.
These instructions assume that:
Inbound connections to the mail server will appear on port 25 (SMTP) of the external interface of the DNS server. You must change the destination IP address of this traffic from 203.0.113.1 to 192.168.0.2. Similarly, traffic to port 80 (HTTP) must have its destination address changed to 192.168.0.3. This must be done prior to routing, otherwise the traffic will be delivered locally instead of being forwarded.
The desired effect can be achieved by means of the DNAT target of iptables. The rules need to isolate the relevant traffic and should be placed in the PREROUTING chain of the nat table:
iptables -t nat -A PREROUTING -p tcp -d 203.0.113.1 --dport 25 -j DNAT --to 192.168.0.2 iptables -t nat -A PREROUTING -p tcp -d 203.0.113.1 --dport 80 -j DNAT --to 192.168.0.3
Only the first packet of a connection traverses the PREROUTING table: subsequent packets are automatically redirected. For this reason it is not necessary to provide rules for the return path.
Testing must be done from a machine on the far side of the router, which in this example is the public Internet. The most obvious methods are to use a second Internet connection or a remotely hosted server, but there are alternatives if these are not readily available:
Most TCP-based services can be tested using a generic proxy service such as Tor, provided that they do not require secondary connections (as FTP does when in active mode) and have not been blocked as a matter of policy by the proxy service (as SMTP ought to be).
Use tcpdump or a similar tool to answer the following questions, stopping at the first one for which the answer is no:
A failure at step 1, 4, 5, 6 or 7 indicates an issue that is unconnected with iptables or NAT, and which will need to be addressed before you can test further.
A failure at step 2 could indicate that:
A failure at step 3 could indicate that:
A failure at step 8 could indicate that:
Finally, a failure at step 9 could indicate that:
Further information about how to investigate these issues can be found in the troubleshooting guides for iptables and routing.
DNAT rules can be used alongside filtering rules. In this case the traffic is being forwarded, therefore the appropriate place to filter it is the FORWARD chain. This is traversed after the PREROUTING chain, therefore the filter will see the NATted IP address of the server (192.168.0.2 or 192.168.0.3), not the external address.
For example, to block access to the mail server from 198.51.100.0/24 a suitable rule would be:
iptables -t filter -A FORWARD -p tcp -s 198.51.100.0/24 -d 192.168.0.2 --dport 25 -j DROP