Consider we have a public website example.com
resolving to 1.1.1.1
. The actual web-server is behind a router/firewall and is listening on port 8080
.
Simple setup is OK for internet users, but not for other clients in 192.168.1.0
range. A client in 192.168.1.3
cannot connect to 1.1.1.1:80
. We have hairpinning NAT problem, (described also in mikrotik wiki).
Suppose, we solve issue not by configuring router, but with iptables
in web-server itself. This commands instruct all outgoing packets on port 8080 to be sent via router:
iptables -t mangle -A OUTPUT -p tcp -m tcp --sport 8080 -j MARK --set-xmark 1
ip rule add fwmark 1 table natreflect
ip route add default via 192.168.1.1 table natreflect
The above config solves all clients in 192.168
range, but not clients in 192.168.1.2
itself.
When a client 192.168.1.2
wants to connect to 1.1.1.1:80
, it sends a packet like 192.168.1.2:34567->1.1.1.1:80
to router. Router does NAT and sends a packet 192.168.1.2:34567->192.168.1.2:8080
to web server (e.g. on its eth0
interface). Web servers receives this packet. The packet traverses chains mangle.PREROUTING
and nat.PREROUTING
, but it doesn't reach to mangle.INPUT
(and connection does not establish).
What's the problem? (rp_filter
is set to 0 on all interfaces)
It appears to be difficult for the server
192.168.1.2
to accept an incoming packet coming from its own IP192.168.1.2
but from scope link, not scope host, so from its own IP but which it not itself. That seems a routing problem for which there might or might not be a solution. One can still just work around this situation so it never happens.To avoid this situation, before even having the initial packet leave the web server
192.168.1.2
and go on the wire, just add an iptables rule on it redirecting a connection from itself to1.1.1.1:80
directly to the right place: itself.An alternate and equivalent rule (at least on recent kernels, perhaps not on old kernels) would be:
By just adding this rule in addition to the other settings, connections coming from outside, from LAN and from the web server all behave the same: they work, they keep the source IP, and for all cases the destination IP is
192.168.1.2
. The only drawback is to have to know there is1.1.1.1
.