I'm trying to understand the limitations of using iptables DNAT with loopback addresses. Consider we have an application which can connect only to; the obvious solution to make server and client work on different nodes is to use NAT as following:

Make sure all outgoing packets have the main client host's ip address:

iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source <CLIENT_IP>

Now let's try to fool the client and DNAT a connection to the outside world:

iptables -t nat -A OUTPUT -d -p tcp -m tcp --dport <SERVICE_PORT> -j DNAT --to-destination <SERVER_IP>

Unfortunately, that just doesn't work, when trying to connect to<SERVICE_PORT> program just hangs on connect syscall. The interesing thing is that I cannot see any SYN packets on any interfaces (tcpdump -qn -i any port <SERVICE_PORT>), however I can see the packet counters increase while looking at iptables statistics (iptables -nvL -t nat).

Googling for solution I've found a kernel build option CONFIG_IP_NF_NAT_LOCAL, which was used in kernels 2.6.0-2.6.10 to solve the problem of using NAT with locally originated connections. Unfortunately, current git kernel tree holds information for versions 2.6.11 and later, so I hit dead end here.

Looking further I've run into this thread, concerning fixes of some DNAT on loopback issues in 2.6.11; one of the patches removes CONFIG_IP_NF_NAT_LOCAL build option and enables the code unconditionally (here's the actual diff).

However, the current state of this problem is quite unclear to me. I'd like to find some explanations or references proving this is a kernel bug or some not-so-well-documented feature. I know that network routing is handled by the kernel in a special way, but from the iptables documentation it is clear that nat table OUTPUT chain is the only place which makes sense for that kind of rules and states no exceptions or any kind of notes regarding 127/8 network.

Please refrain from advising some workarounds with third-party tools, I've already have some, I just want to have some explanation why this exact configuration does not work and why it should not work. Any examples of how this DNAT can be done with any other iptables rules are welcome.

The above configuration was tested on Debian squeeze and wheezy, with kernels 2.6.32, 3.1.0, 3.2.0.


Digging a little deeper reveals some confirmation that aforementioned behavior is totally correct.

According to RFC 5735, network should not be routed outside host itself: - This block is assigned for use as the Internet host loopback address. A datagram sent by a higher-level protocol to an address anywhere within this block loops back inside the host. This is ordinarily implemented using only for loopback. As described in [RFC1122], Section, addresses within the entire block do not legitimately appear on any network anywhere.

RFC 1700, page 5 also states that these addresses «Should never appear outside a host».

RFC 1812, Section 5.3.7 Martian Address Filtering declares that «router SHOULD NOT forward, except over a loopback interface, any packet that has a source address on network 127», which is exactly my case.

Concerning these references, I presume the case from the first post indeed is a feature, and the opposite behavior would be a standards violation.

| improve this answer | |
  • 1
    Cm'on, if you explicitly tell the OS you want to redirect packets from to, this isn't violation of the standard, you told it to do that. – Elazar Leibovich Jan 12 '15 at 20:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.