IPTables Trickery

IPTables Trickery

I've had a bit of a strange situation on my network - Googling never did come up with anything for me.

I have a private network. All my servers sit behind the firewall on the private LAN. A few of those servers provide services to the Internet on specific ports.

Sharing those ports to the outside using iptables is trivial. The problem arises when you are trying to access the internal server using the external DNS / IP from inside the network. What would happen is that iptables would redirect your packets to the correct server, but the return address would be your local internal IP, so the packets return to you as if coming from the private address instead of the public address, and your local computer won't know what to do with them.

There's actually a very simple solution, assuming you have static IP's on the Internet and on the internal server. Using a combination of source and destination masquerading, you can rewrite those IP addresses to match. The downside is you double the traffic on your internal network, but it enables you to provide services that are harder to NAT such as SIP traffic.

Read more for an example fix:

Here's an example:

INT_SUBNET = // replace with your internal subnet
EXT_IP_OF_SERVER = # replace with your own external IP
INT_IP_OF_SERVER = # replace with your own internal IP

iptables -t nat -A PREROUTING  -i eth0 -p tcp --dport 80 -s $INT_SUBNET -d $EXT_IP_OF_SERVER 
-j DNAT --to-destination $INT_IP_OF_SERVER
iptables -t nat -A POSTROUTING -o eth0 -p tcp --dport 80 -s $INT_SUBNET -d $INT_IP_OF_SERVER 
-j SNAT --to-source $EXT_IP_OF_SERVER

So, there's me and a web server on the same private subnet, but I want to access it using the external IP that my firewall routes to it. I browse to $EXT_IP_OF_SERVER and my firewall/nat box gets the packets. The first line above says "Hey, here's a packet from our internal network, and it wants to go to a server we host on the outside IP. Let's make sure we redirect that traffic to the server on the internal network." That's why my traffic gets to the server. The second step is how the traffic finds it's way back to me - it's again processing on the way to the server, but AFTER I've already redirected the traffic to the internal IP. It says "Here's a packet destined for the ineternal server. It's from our local subnet, but let's pretend it's really from the external IP address that the server uses." You could use any external address or even a different subnet entirely if you wanted. The point is to make sure that the return address on the packets is NOT on the local subnet. That will force those packets on the return trip to go back through the firewall and be handled by the NAT tables.

I specified the interface to keep people outside my lan from trying to spoof a request as if it's coming from inside. Filtering solely based on IP address is a bad idea from a security standpoint. In the example above, eth0 is my internal network interface on the firewall / NAT box.

So there you have it, a simple solution to a problem that's plagued me for over a year.

Posted by Tony on Aug 22, 2009 | Servers, Network Security, Networking