Search code examples
iptablesnat

HTTP iptable PREROUTING rule is not working


I'm trying to understand iptables and can't seem to redirect traffic at all. The target is to redirect traffic form port 4567 to 8443 and have a (local) program listen on the latter.

I've written a short script to make sure I flush and restart the iptables each time I change the rule:

#!/bin/bash

iptables -t nat -F

iptables -t nat -A PREROUTING -p tcp --dport 4567 -j REDIRECT --to-ports 8443
sudo /sbin/iptables-save                                                   

I've also setup the ip_forwarding (although I'm not entirely sure whether I need that):

sudo echo "1" > /proc/sys/net/ipv4/ip_forward

I'm running this simple python script to test the routing. The site is made as to allow http requests on any port.

import requests
r = requests.get("http://portquiz.net:4567")
print(r.status_code)

As well as checking if any packets / bytes pass through the prerouting by looking at the output of iptables -t nat --list -v

Chain PREROUTING (policy ACCEPT 4 packets, 560 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REDIRECT   tcp  --  any    any     anywhere             anywhere             tcp dpt:4567 redir ports 8443

Both the iptables and the python script are on the same machine (my laptop). The python request seems to be going through without problems, and does not seem to be intercepted by the prerouting policy.

I'm running on the latest ubuntu 20.02

This is the output of the iptables-save, in case it's useful:

# Generated by iptables-save v1.8.4 on Tue Nov 10 13:20:02 2020
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -p tcp -m tcp --dport 4567 -j REDIRECT --to-ports 8443
COMMIT
# Completed on Tue Nov 10 13:20:02 2020
# Generated by iptables-save v1.8.4 on Tue Nov 10 13:20:02 2020
*filter
:INPUT ACCEPT [16727:8538288]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [16979:3211690]
COMMIT
# Completed on Tue Nov 10 13:20:02 2020

Solution

  • One needs to pay close attention between local packets, and network packets, when using iptables. Local packets are packets created on the local machine, whereas network packets are packets received. PREROUTING works on network packets, for instance what you would get on a router device. Since in this case it's all local, then one must use OUTPUT instead of PREROUTING to redirect the packets. The necessary rule is therefore.

    iptables -t nat -A OUTPUT     -p tcp --dport 4567 -j REDIRECT --to 8443
    

    I have found this picture to be very useful:

    enter image description here

    Which comes from this article: https://danielmiessler.com/study/iptables/