60

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?

2

5 Answers 5

79

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
7
  • 4
    No need for the first rule. The locally generated packets does not pass via the PREROUTING chain.
    – Khaled
    Dec 11, 2010 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, 2010 at 12:54
  • oh appologies I didn't see your answer when I replied.
    – Andy
    Dec 11, 2010 at 12:57
  • Hi Andy, I'm still getting Connecting to server.com|<ip>|:443... failed: Connection refused.
    – Chris
    Dec 11, 2010 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 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, 2010 at 12:49
15

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.

6
  • That would work too. I think doing it all in iptables is cleaner. Jun 16, 2017 at 2:52
  • Actually, the kernel setting is neded if the destination is on another machine, line a VM or remote machine.
    – user420606
    Jun 16, 2017 at 7:59
  • it is not if you have the two rules as Andy suggested above. Jun 16, 2017 at 8: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.
    – user420606
    Jun 16, 2017 at 8:25
  • Actually, it's' dependent on kernel version >= 3.6, apparently. Jun 16, 2017 at 8:35
3

How about this?

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

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.

2
  • 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, 2010 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 2, 2015 at 11:00
0

I also found this problem. It was still not working after try all these ways

  1. echo "1" > /proc/sys/net/ipv4/ip_forward
  2. use 'OUTPUT' in iptables for localhost redirect

Finally, I found the reason why it didn't work! Because REDIRECT in iptables always REDIRECT to localhost, instead of eth0 or other network device. So the request will be redirect to localhost, if your server is binding eth0, there is no way to receive it.

YOU SHOULD ALSO ADD THIS LINE:

iptables -t nat -A OUTPUT -p tcp -d 0.0.0.0 --dport 443 -j DNAT --to-destination 0.0.0.0:8080

You must log in to answer this question.

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