Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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:

LOCAL_IP=10.1.1.10
LOCAL_PORT=8888
REMOTE_IP=10.1.1.11
REMOTE_PORT=9999

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 127.0.0.1:8888, to 10.1.1.11:9999. 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).

share|improve this question
1  
So you want a client application to open a socket to 127.0.0.1:8888 and have iptables redirect that to 10.1.1.11:9999? –  bahamat Nov 2 '12 at 19:53
    
@bahamat - yes, exactly. –  JimB Nov 2 '12 at 20:01
add comment

1 Answer

The problem is that Linux treats anything within 127.0.0.0/8 as being local, and will even answer (try pinging 127.99.88.77).

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 127.0.0.1 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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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