58

I want to redirect all traffic from port 443 to the internal port 8080. I'm using this config for iptables:

iptables -t nat -I PREROUTING --source 0/0 --destination 0/0 -p tcp \
         --dport 443 -j REDIRECT --to-ports 8080

This works for all external clients. But if I'm trying to access the port 443 from the same maschine I'll get a connection refused error.

wget https://localhost

How can I extend the iptables rule to redirect local traffic too?

Linostar
  • 157
  • 7
Chris
  • 581
  • 1
  • 5
  • 3

4 Answers4

77

PREROUTING isn't used by the loopback interface, you need to also add an OUTPUT rule:

iptables -t nat -I PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 8080
iptables -t nat -I OUTPUT -p tcp -o lo --dport 443 -j REDIRECT --to-ports 8080
Andy
  • 3,705
  • 1
  • 19
  • 9
  • 3
    No need for the first rule. The locally generated packets does not pass via the PREROUTING chain. – Khaled Dec 11 '10 at 12:43
  • 9
    I added the initial rule for compeletion's sake, as he wants external traffic to redirect as well. The rule doesn't need source/destination if they only say to accept all IPs – Andy Dec 11 '10 at 12:54
  • oh appologies I didn't see your answer when I replied. – Andy Dec 11 '10 at 12:57
  • Hi Andy, I'm still getting Connecting to server.com||:443... failed: Connection refused. – Chris Dec 11 '10 at 13:24
  • Hi Chris, is that the Connecting to localhost|127.0.0.1|443 or is that the domain? If the latter and you're running it from your server, you might have a internal routing problem. You could double check by trying wget https://server.com:8080/ (although I assume the reason you're port forwarding is because its blocked externally?). My own VPC has that problem, however you could possibly put a workaround by defining the domain as 127.0.0.1 in your /etc/hosts file. – Andy Dec 12 '10 at 12:49
  • Does the edit I made above help? (added -d 127.0.0.1) – Andy Dec 12 '10 at 13:13
  • Can anyone explain why `PREROUTING` does not work on localhost? – Ciro Santilli OurBigBook.com Dec 18 '14 at 11:48
13

To redirect packets from localhost to another machine the rule:

 iptables -t nat -A OUTPUT -o lo -d 127.0.0.1 -p tcp --dport 443 -j DNAT  --to-destination 10.x.y.z:port

will work, BUT you also need to enable this option in the kernel:

sysctl -w net.ipv4.conf.all.route_localnet=1

Without that kernel setting it wont work.

  • That would work too. I think doing it all in iptables is cleaner. – quadruplebucky Jun 16 '17 at 02:52
  • Actually, the kernel setting is neded if the destination is on another machine, line a VM or remote machine. –  Jun 16 '17 at 07:59
  • it is *not* if you have the two rules as Andy suggested above. – quadruplebucky Jun 16 '17 at 08:03
  • Sorry, I was talking about the case of forwarding to a different machine where DNAT doesn't work. I was looking at this answer for a solution to a problem when I was trying to forward something that thought it was connecting to localhost to a containter on the same machine. eg running the nameserver in a container for local queries. –  Jun 16 '17 at 08:25
  • Actually, it's' dependent on kernel version >= 3.6, apparently. – quadruplebucky Jun 16 '17 at 08:35
  • Thanks for mentioning the kernel option. I could not figure out why my OUTPUT rules were not being triggered until I read your post! – Semafoor Mar 09 '18 at 10:46
3

How about this?

iptables -t nat -A OUTPUT -d 127.0.0.1 -p tcp --dport 443 -j REDIRECT --to-port 8080

Athanasios
  • 355
  • 1
  • 2
  • 7
2

You said you are getting connection refused error. This means that there is no local process listening on the port you are trying to connect to! To check the listening processes, use the command:

$ sudo netstat -lnp | grep 8080

After applying the rule, you should have a process listening on the port 8080 to get connected.

It seems that you should have the following rule instead:

$ iptables -t nat -I OUTPUT --source 0/0 --destination 0/0 -p tcp
                                       --dport 443 -j REDIRECT --to-ports 8080

Remember that you are sending from the localhost. So, you need to redirect the output packet.

Khaled
  • 35,688
  • 8
  • 69
  • 98
  • 1
    Thanks for yor answer. The process is listening on port 8080. Therefor I want to redirect all traffic to that port. – Chris Dec 11 '10 at 11:53
  • Are you sure the process is listening on the loop interface as well? It may only be listening on your physical interface. Typically, your webserver will need to listen to 0.0.0.0 rather than, say, 192.168.10.0 – MrMajestyk Feb 02 '15 at 11:00