Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have two Systems A and B. A is a TCP Client and sends a message to TCP Server on B.

------------------                --------------------------

  System A                        System B wlan0      wlan0   lo         lo
  TCP Client    <------------>    TCP Server on
------------------                ----------------------------

The TCP Client sends message to

This should be redirected to the local interface of B as the TCP Server is running on at Port 8000 of System B.

Therefore, I wrote the following ip table rules, however my Server at B doesn't receive any messages. Oh btw these two systems are Ubuntu linux systems.

Here is what I did on System B:

#Enable IP Forwarding for NAT
echo "1" > /proc/sys/net/ipv4/ip_forward

#Flush all iptable chains and start afresh
sudo iptables -F

#Forward incoming packets on at wlan0 interface to
sudo iptables -t nat -A PREROUTING -p tcp -i wlan0 -d --dport 8000 -j DNAT --to

#Explicitly allow incoming connections on port 8000 
sudo iptables -A INPUT -i wlan0 -p tcp --dport 8000 -m state --state NEW,ESTABLISHED -j ACCEPT

#Explicitly allow outgoing messages from port 8000
sudo iptables -A OUTPUT -o wlan0 -p tcp --sport 8000 -m state --state ESTABLISHED -j ACCEPT

Then I start the Server on B and send a message from TCP Client on A. I can see the packets on wireshark from on wlan0 but they never get forwarded :(

Please help.


After inputs from experts here, I have made a more realistic "NAT" scenario for applying the forwarding rules but I have still issues: I have explained this in my newer post: Iptables: Forwarding packets doesn't work

share|improve this question
There is a simple bug in your code. I believe it should be echo "1" > /proc/sys/net/ipv4/ip_forward Additionally I'm not sure why you'd like to use NAT anyway. It doesn't make sense. NAT is something where you hide a network behind the NATting host and act in place of the origin host. – Jens Bradler Apr 26 '12 at 8:56
Oops that was really a typo error! Let me edit it! – user907810 Apr 26 '12 at 13:17

Here is a total non-answer answer.
as Jens Bradler said in his comment, the simplest thing to do here is to bind the service to the public IP address on port 8000, rather than NAT the connection. You can secure access to the single Server A by iptables rules like so;

 -A INPUT -s -p tcp -m tcp --dport 8000 -j ACCEPT
 -A INPUT -p tcp -m tcp --dport 8000 -j REJECT
share|improve this answer

Tom H's non-answer answer is better, but if you don't like it, here is a direct answer:

Sorry, my iptables skills are best when I can tinker, test, check, logs, repeat... and I don't have your system to play with, but here is my advice anyway. You proabably will need to debug using the logs.

Change the direction of your redirect, as stated by Jens Bradler:

echo "1" > /proc/sys/net/ipv4/ip_forward

Prove it is right

cat /proc/sys/net/ipv4/ip_forward

Output from cat:


Add a rule to ACCEPT using the FORWARD table also.

sudo iptables -A FORWARD -i wlan0 -p tcp --dport 8000 -j ACCEPT

Remove the "-m state" stuff from the incoming rule (optional... unnecessary I think):

sudo iptables -A INPUT -i wlan0 -p tcp --dport 8000 -j ACCEPT

Probably anywhere that you added "ESTABLISHED", you should also have "RELATED" (Not sure but I think a return packet that starts a connection is related, but not established).

sudo iptables -A OUTPUT -o wlan0 -p tcp --sport 8000 -m state --state RELATED,ESTABLISHED -j ACCEPT

The FORWARD rule to go with the above accept, reverse of the other FORWARD. sudo iptables -A FORWARD -o wlan0 -p tcp -s --sport 8000 -m state --state RELATED,ESTABLISHED -j ACCEPT

Instead of using wireshark, use -j LOG.

First check to see that there aren't already LOG rules (the default ones are better than the following... but you used flush; mine will spam your server hard):

sudo iptables --list --line-numbers -v
sudo iptables -t nat --list --line-numbers -v

If not, then add them:

sudo iptables -A INPUT -j LOG
sudo iptables -A OUTPUT -j LOG
sudo iptables -A FORWARD -j LOG
sudo iptables -t nat -A PREROUTING -j LOG

Watch the logs

tail -F /var/log/firewall

# or if that file doesn't exist:
tail -F /var/log/messages
share|improve this answer
BTW I've done similar to the above a bunch, but I have never used "-j DNAT" – Peter Apr 26 '12 at 13:11
Thanks Peter. I am going to try this now and let you know :) – user907810 Apr 26 '12 at 13:21
Oh I guess even the first FORWARD rule should omit -m state, am I right? – user907810 Apr 26 '12 at 13:28
Hi Peter, I tried exactly what you said, however when the client on System A sends a packet to Server on B, the log message only shows the SYN requeston System B at but that is all. The server doesnt receive the message as it doesnt get forwarded I guess :( – user907810 Apr 26 '12 at 13:50
Yes, the "-m state"| on its own is just a mistake. (I'll remove it now) – Peter Apr 27 '12 at 13:54

You can't ever perform -j DNAT --to is a super-duper-special address; it would only accept connections from

@Tom H's answer is the way you should set up your server.

share|improve this answer
Shouldn't a NAT (the t being for "translation") translate the source address to the so the listening process will think it is accepting something from there? – Peter May 2 '12 at 19:56

Your Answer


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.