Iptables : ouvrir un port local et rediriger le trafic sur un autre port local

Pour transférer le trafic d'un port à un autre on utilise en général une règle de ce type :

$ sudo iptables -t nat -A PREROUTING -p tcp --dport <nouveau port> -j REDIRECT --to-ports <port vers lequel rediriger le trafic>

exemple :

$ sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3118

Ça fonctionne bien pour les machines se connectant au nouveau port ainsi créé (80 ici).

Par contre si on essaye de se connecter au port 80 depuis la machine où la règle iptables a été ajoutée, ça ne fonctionne pas (symptome : Connection refused).

La raison est que cette règle, placée sur la chaine POSTROUTING, n'est pas utilisée lorsque l'on accède à un port via l'interface de loopback (lo).

Il faut donc ajouter une règle sur la chaine OUTPUT de l'interface de loopback :

$ sudo iptables -t nat -A OUTPUT -o lo -p tcp --dport <nouveau port> -j REDIRECT --to-port <port vers lequel rediriger le trafic>

Use case pratico-pratique : je forward via ssh du trafic HTTP sur un port ne nécessitant pas d'accès privilégié (numéro de port supérieur à 1024) mais mon navigateur reçoit une redirection vers localhost sur un autre port que celui forwardé (par exemple port 80 ; http://localhost/).

Dans ce cas on pourrait utiliser la règle suivante pour rediriger le trafic arrivant sur le port 80 vers le port 3118 (qui écoute déja localement, grâce au tunnel SSH) :

$ sudo iptables -t nat -A OUTPUT -o lo -p tcp --dport 80 -j REDIRECT --to-port 3118

Dans tous les cas nous penserons bien sûr à activer l'ip forwarding :

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