18

I'm trying to locally redirect ports on my Ubuntu machine using iptables. Similar to transparent proxying. I want to catch anything trying to leave my system on port 80 and redirect it to a remote host and port.

Can I achieve this using the NAT and pre-routing functions of iptables?

28

Try this iptables rule:

$ sudo iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination IP:80

The above says to:

  • Add the following rule to the NAT table (-t nat).
  • This rule will be appended (-A) to the outbound traffic (OUTPUT).
  • We're only interested in TCP traffic (-p tcp).
  • We're only interested in traffic who's destination port is 80 (--dport 80).
  • When we have a match, jump to DNAT (-j DNAT).
  • Route this traffic to some other server's IP @ port 80 (--to-destination IP:80).

What's DNAT?

DNAT
    This target is only valid in the nat table, in the PREROUTING and OUTPUT 
    chains, and user-defined chains which are only called from those chains.
    It specifies that the destination address of the packet should be modified 
    (and all future packets in  this  connection will also be mangled), and
     rules should cease being examined.

References

  • thanks for that but it does not seem to work. I have however since found this that does work. – pjf Aug 8 '13 at 6:20
  • sudo iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination xx.xx.xx.xx:3128 – pjf Aug 8 '13 at 6:21
  • Is that because this is locally and not through a gateway? your SNAT would work through a gateway? – pjf Aug 8 '13 at 6:22
  • @pjf - I believe so. I've updated my answer. – slm Aug 8 '13 at 6:25
  • @pjf - I found both rules and was in the process of updating my answer with both. I wasn't sure which situation you were in though. – slm Aug 8 '13 at 6:30
5

This can be made more specific to operate only on traffic to a particular destination host. For instance when postfix made mistake and mails in queue want to be sent to an old ip address.

iptables -t nat -A OUTPUT -p tcp -d {ONLY_TO_THIS_DESTINATION} --dport 25 -j DNAT --to-destination {NEW_IP}:25
4

This can allow you to translate ports to all IP addresses. The main difference here is the absense of an IP address in the --to-destination field.

iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination :80
  • Very useful tip; exactly what I needed. Is there a way to increment the port number? Say I have a range of 100 ports and want to raise them all by a specific amount. – Zdenek May 7 '17 at 14:00
  • Not sure what you mean. Could you write a for-loop in Bash? – Felipe Alvarez May 8 '17 at 1:18
  • A loop adding 100 iptables rules would work, but it would slow it down. I'd prefer to be able to tell it to increment many successive ports in a single rule. – Zdenek May 8 '17 at 16:42
  • @Zdenek I do not know if that is possible with iptables. Have you looked at firewalld? – Felipe Alvarez May 9 '17 at 23:51

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.