24

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?

3 Answers 3

35

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

8
  • thanks for that but it does not seem to work. I have however since found this that does work.
    – pjf
    Commented Aug 8, 2013 at 6:20
  • sudo iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination xx.xx.xx.xx:3128
    – pjf
    Commented Aug 8, 2013 at 6:21
  • Is that because this is locally and not through a gateway? your SNAT would work through a gateway?
    – pjf
    Commented Aug 8, 2013 at 6:22
  • @pjf - I believe so. I've updated my answer.
    – slm
    Commented Aug 8, 2013 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
    Commented Aug 8, 2013 at 6:30
7

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
4
  • 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
    Commented May 7, 2017 at 14:00
  • Not sure what you mean. Could you write a for-loop in Bash? Commented May 8, 2017 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
    Commented May 8, 2017 at 16:42
  • @Zdenek I do not know if that is possible with iptables. Have you looked at firewalld? Commented May 9, 2017 at 23:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .