System: Accessing Public IP address from behind NAT
This article describes a simple solution we came up with to for what must be a common problem for anyone hosting a website on a local network or at a hosting centre with a 1:1 NAT (Network Address Translation) or similar firewall.
What is a Private Network?
As well as the public IP addresses that we use every day (yours is 188.8.131.52 and ours 184.108.40.206) the RFC1918 specification cleverly allows for a number of private networks of various sizes:
|IP address range
|number of addresses
|10.0.0.0 – 10.255.255.255
|172.16.0.0 – 172.31.255.255
|192.168.0.0 – 192.168.255.255
Many home users will be familiar with the 16-bit block range as a means for accessing the router control panel or talking to other devices in the local network.
While everyone inside the local network can use these addresses they are not visible to the outside world. When someone else opens 192.168.0.1 they will see their router and not yours. The outside world can only see the public IP address that has been assigned to your Internet connection.
Description of the problem
From inside the private network each server or device is known only by it's private IP address and is always referenced using that address. Internal IP addresses are either assigned manually, or dynamically by the router using DHCP (Dynamic Host Configuration Protocol).
With a 1:1 NAT firewall setup, requests from outside the network are translated into requests for a local address. For example, a public IP address 204.8.XXX.6 might be converted to a local address 10.30.XXX.6, 204.8.XXX.7 mapped to 10.30.XXX.7 and so on.
A consequence of this is that from a server inside the network it's no longer possible to access the public IP address. So any HTTP requests for locally hosted websites will fail because a DNS lookup will return the public address which is unreachable.
If you are hosting only a small number of domains then you can set up a local DNS server (BIND) mapping those domains to local IP addresses. You could also achieve this by editing /etc/hosts.
For a large number of domains, however, this is not really an option as it means twice as much work every time the DNS is updated.
Using NAT tables to get around a NAT firewall
Sure enough there's a simpler solution using iptables. We know that a request from the server itself (telnet, web browser or web spider for example) can't reach the external IP address, but that the same request using the internal address will get through.
Using the right routing rules we can translate those requests and it should all just work. After some experimentation what we came up with was the following rules and added them to the firewall script which runs on startup:
$IPTABLES -t nat -A OUTPUT -d 204.8.XXX.6 -s 10.30.XXX.0/XX -j DNAT --to-destination 10.30.XXX.6
$IPTABLES -t nat -A OUTPUT -d 204.8.XXX.7 -s 10.30.XXX.0/XX -j DNAT --to-destination 10.30.XXX.7
(to see what was going we used the LOG option in iptables to monitor requests from the server ip address in each of the NAT chains. In this case requests appeared only in the OUTPUT chain and not in PREROUTING or POSTROUTING as they would for a router)
The above rules intercept any requests from our server (subnet 10.30.XXX.0/XX) directed at our public IP addresses, which would normally drop out or fail, and translates them into requests for the appropriate local IP address.
So an HTTP/1.1 request for www.the-art-of-web.com (204.8.XXX.6) is translated into a request for www.the-art-of-web.com (10.30.XXX.6) meaning that the server can handle it itself. You will need a separate rule for each external/internal address pair.
Essentially what we're doing is replicating the actions taken by the NAT firewall for external requests, only we're doing it for internal requests.
These rules are to allow a server behind a NAT firewall to make requests to itself using the public IP addresses. For router configuration you need to use a combination of DNAT, SNAT and Masquerading and there are loads of examples online.