Suppose that TCP packets are sent to destination ip (dest_ip) and can be dropped by the following command:

iptables -A INPUT -d dest_ip -p tcp -j DROP

But when I try to redirect the packet using iptables NAT to a different ip (diff_ip), the packet still arrives at the old destination (dest_ip):

iptables -t nat -A PREROUTING -d dest_ip -p tcp -j DNAT --to-destination diff_ip

There is something about iptables that I don't quite understand here, as I am expecting the packet to no longer reach the dest_ip. Can someone please explain why this is so? Thanks.

Additional info that may be relevant:
/proc/sys/net/ipv4/ip_forward is already set to 1
ifconfig shows two interfaces: eth0 and lo; dest_ip is on eth0 and diff_ip is a remote ip

UPDATE 1: further tests using telnet

A listener using socat is established on 12800 to receive telnet message:

socat -u TCP-LISTEN:12800,reuseaddr,keepalive,reuseaddr OPEN:/tmp/output.txt,creat,append

Telnet connection is made with random messages:

telnet 12800

1) test using:

iptables -A INPUT -p tcp --dport 12800 -j DROP

result: all messages from telnet are dropped as confirmed by the counter:

iptables -L INPUT -v -n

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    2   120 DROP       tcp  --  *      *              tcp dpt:12800

2) test using:

iptables -t nat -A PREROUTING -p tcp --dport 12800 -j DNAT --to-destination remote_ip

result: all message arrives at port 12800 without being redirected, which is confirmed by the counter:

iptables -L PREROUTING -t nat -v -n

Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DNAT       tcp  --  *      *              tcp dpt:12800 to:remote_ip

UPDATE 2: further test using telnet (see above) but with iptables rules on the OUTPUT chain:

iptables -t nat -A OUTPUT -p tcp --dport 12800 -j DNAT --to-destination remote_ip

result: all messages are successfully redirected as confirmed by the counter:

iptables -L OUTPUT -t nat -v -n

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    3   180 DNAT       tcp  --  *      *              tcp dpt:12800 to:remote_ip

This is starting to make sense since telnet is a local process and its output should directly go into the OUTPUT chain. However, this raises another question: according to update 1, telnet messages can also be dropped in the INPUT chain, so how exactly are the packets travelling? OUTPUT -> INPUT?

  • Any previous rules in PREROUTING which match these packets? – Hauke Laging Apr 26 '13 at 5:05
  • No, there are no other rules. Those are the only two. – tonytz Apr 26 '13 at 5:32
  • 1
    Do you test this with new connections (TCP SYN packets)? You may check with tcpdump. Existing connections are not affected by PREROUTING. – Hauke Laging Apr 26 '13 at 5:40
  • This is what I am doing: I use Firefox to visit a specific site and I monitor where the returning packets are going to (ie. dest_ip). Then I try to re-direct the returning packets using DNAT as shown above. This apparently doesn't work as Firefox still displayed the page successfully. Based on what you said, perhaps, it is because this is an existing connection since Firefox already established a connection before receiving the returning packets? – tonytz Apr 26 '13 at 5:47
  • 1
    try iptables -t nat -L PREROUTING -v -n to see weather your rule is beeing used (check the counter) when you try. Also you could check that your traffic don't get stuck in any other rule eg OUTPUT or FORWARD. I seem to recollect having had similar trouble just because I dropped the package in another chain... – Petter H Apr 26 '13 at 6:12

All your tests have pointed out something that you should have figured out. When dealing with Netfilter/iptables, you cannot successfully build your rules without having the packet flow in mind.

As you can see, a local process never go though the PREROUTING chain but only OUTPUT and POSTROUTING. This is why your telnet process is redirected when you place your rule in OUTPUT but not when you put it in PREROTUING. However, this rule is right for an external packet traversing your machine.

  • Thank you for responding. Although telnet is a local process and its packets can be manipulated in the OUTPUT chain, this still doesn't explain the initial question that an external packet coming into the machine can be dropped in the INPUT chain but cannot be re-directed in the PREROUTING chain. – tonytz Apr 28 '13 at 17:28

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.