2

I'm trying to understand the limitations of using iptables DNAT with loopback addresses. Consider we have an application which can connect only to 127.0.0.1; 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 127.0.0.1/32 -p tcp -m tcp --dport <SERVICE_PORT> -j DNAT --to-destination <SERVER_IP>

Unfortunately, that just doesn't work, when trying to connect to 127.0.0.1:<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 127.0.0.0/8 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.

1

1 Answer 1

1

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

According to RFC 5735, network 127.0.0.0/8 should not be routed outside host itself:

127.0.0.0/8 - 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 127.0.0.1/32 for loopback. As described in [RFC1122], Section 3.2.1.3, addresses within the entire 127.0.0.0/8 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.

1
  • 1
    Cm'on, if you explicitly tell the OS you want to redirect packets from 127.0.0.1 to 10.0.0.1, this isn't violation of the standard, you told it to do that. Jan 12, 2015 at 20:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .