My goal is to redirect connections from the local host to a remote server, and be able to change the remote address on the fly, without any client config changes. I can do this now using a nat on the external interface like so:


iptables -t nat -A OUTPUT -p tcp -d $LOCAL_IP --dport $LOCAL_PORT -j DNAT --to-destination $REMOTE_IP:$REMOTE_PORT
iptables -t nat -A POSTROUTING -p tcp -d $REMOTE_IP --dport $REMOTE_PORT -j SNAT --to-source $LOCAL_IP

This works fine, but still couples the client's config to the hosts IP address. What would be really nice, is to be able to NAT traffic going to, to This seems like something that should be possible using a DNAT/SNAT|MASQUERADE combination, but I haven't come up with a working configuration yet. Any configurations I try seem to silently drop the packets (possibly caught by the martian rules? I do have ip_forward enabled).

  • 1
    So you want a client application to open a socket to and have iptables redirect that to – bahamat Nov 2 '12 at 19:53
  • @bahamat - yes, exactly. – JimB Nov 2 '12 at 20:01

The problem is that Linux treats anything within as being local, and will even answer (try pinging

What this means is that the packet is originally transmitted on the OUTPUT as the packet is "leaving" lo. When it "comes in" it goes to the INPUT chain (I traced it to be sure). This is where your situation breaks down.

PRE/POST routing chains aside, on Linux packets destined for the system will traverse only INPUT chain. Packets originating from the system will traverse only the OUTPUT chain. Packets that are neither sourced from nor destined to the local system will traverse only the FORWARD chain.

So what you have is that Linux is selecting the INPUT chain when you want it to be selecting the FORWARD chain.

I tried a few different options and I wasn't able to get it working either, but I do know definitively why it's not working. I'll try looking at this later when I have more time.

P.S. At first I thought you simply had a router issue (and deep down I still feel that routing is involved). Translating the IPs on lo outside of will cause a routing violation which can silently drop packets. In order to disable this you need to set rp_filter=0. You'll still need to do this before you can get it working but that's not the root of the problem. The root issue is that Linux is using INPUT when you want OUTPUT.

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.