Learned something new today: hairpin nat (with iptables on linux)


So I was trying to set up a service that should be accessible from the internet and locally (under the same Domain name and in a different subnet as the internal hosts for security reasons).

the variables (from my script I use for testing) are self explainatory I think (IP Addresses and interface name)

iptables -t nat -A PREROUTING -p tcp -d ${EXTIP} --dport 80 -j DNAT --to ${WEB}
iptables -A INPUT -p tcp -m state --state NEW --dport 80 -i ${IFACE_WAN} -j ACCEPT

Trying to just use my usual DNAT rules did work from outside, but not from the inside.. luckily I found help in #Netfilter on irc.freenode.net ..  duclicsic pointed out to me that i needed SNAT or MASQUERADE too so the router rewrites the local packets too. And also told me that this whole thing was called Hairpin NAT. Thanks to that I now have my iptables rules in place:

iptables -t nat -A POSTROUTING -s ${INTERNALNET} -d ${WEB} -p tcp --dport 80 -j MASQUERADE

INTERNALNET is just the internal network in CIDR notation.

He also pointed out to me that a packet forwared this way would not hit the INPUT chain, but FORWARD instead on the host (since the LAN interface on my router does not block port 80 i did not have an issue with this).

An alternative to this would be split horizon DNS, where the internal DNS server returns the internal IP for internal hosts instead of the public IP.

Current rating: 3


There are currently no comments

New Comment


required (not published)