Aller au contenu
Sécurité medium

NAT et redirection de port sur une passerelle Linux avec nftables

10 min de lecture

Une passerelle Linux fait deux choses avec le NAT : elle laisse un réseau interne sortir vers Internet derrière une seule adresse (MASQUERADE), et elle expose un service interne sur un port public (DNAT). Ce guide configure ces deux sens sur un routeur Linux avec nftables, le pare-feu moderne du noyau. Vous activez le routage, écrivez les règles MASQUERADE et DNAT, puis vérifiez chaque traduction avec conntrack. Toutes les commandes et sorties viennent d'un lab réel : une passerelle Linux et un hôte interne (10.0.0.2) derrière elle. Public visé : administrateurs qui montent un routeur, un homelab ou une DMZ.

Si les termes SNAT, DNAT ou PAT sont neufs, posez d'abord les concepts avec comprendre le NAT. Ce guide est la mise en pratique.

  • Activer le routage IP sur la passerelle.
  • Partager la connexion sortante d'un réseau interne avec MASQUERADE.
  • Rediriger un port public vers un service interne avec DNAT.
  • Vérifier les traductions avec conntrack.
  • Rendre les règles persistantes au redémarrage.
  • Une passerelle Linux avec deux « côtés » : une interface vers Internet (le WAN, ici eth0) et un accès au réseau interne (le LAN, ici 10.0.0.0/24).
  • Un hôte interne à joindre (ici 10.0.0.2, avec un service web sur le port 80).
  • nftables installé (sudo apt install nftables ou sudo dnf install nftables).
  • Les droits sudo.

Le NAT réécrit les adresses des paquets qui traversent la passerelle, et nftables le fait dans deux chaînes distinctes :

  • postrouting (sortie) : juste avant d'émettre, on réécrit l'adresse source. C'est le SNAT ; sa forme automatique est MASQUERADE, qui prend l'IP de l'interface de sortie.
  • prerouting (entrée) : dès l'arrivée, on réécrit l'adresse destination. C'est le DNAT, utilisé pour la redirection de port.

Retenez la règle : MASQUERADE pour sortir, DNAT pour entrer.

Par défaut, Linux ne route pas les paquets d'une interface à l'autre. Il faut l'autoriser :

Fenêtre de terminal
sudo sysctl -w net.ipv4.ip_forward=1

Pour que ce soit permanent, écrivez-le dans un fichier dédié :

Fenêtre de terminal
echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-routeur.conf

Sans cette étape, aucune règle NAT ne fonctionnera : les paquets seraient jetés au lieu d'être routés.

Objectif : les machines du réseau interne (10.0.0.0/24) doivent atteindre Internet derrière l'adresse de la passerelle. On crée une table NAT et une règle MASQUERADE dans la chaîne postrouting.

Fenêtre de terminal
sudo nft add table ip nat
sudo nft add chain ip nat postrouting '{ type nat hook postrouting priority 100 ; }'
sudo nft add rule ip nat postrouting ip saddr 10.0.0.0/24 oifname "eth0" masquerade

La règle se lit : « pour tout paquet venant de 10.0.0.0/24 et sortant par eth0, remplace l'adresse source par celle d'eth0 ». Vérifions que l'hôte interne sort bien :

Fenêtre de terminal
# Exécuté depuis l'hôte interne 10.0.0.2
curl -sS -o /dev/null -w "HTTP %{http_code}\n" http://1.1.1.1
HTTP 301

L'hôte interne, qui n'a aucune route directe vers Internet, a bien atteint 1.1.1.1 à travers la passerelle.

Objectif inverse : exposer le service web interne (10.0.0.2:80) sur le port public 8080 de la passerelle. On ajoute une chaîne prerouting et une règle DNAT.

Fenêtre de terminal
sudo nft add chain ip nat prerouting '{ type nat hook prerouting priority -100 ; }'
sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 8080 dnat to 10.0.0.2:80

La règle se lit : « tout paquet arrivant sur eth0 à destination du port 8080 est redirigé vers 10.0.0.2:80 ». Testons depuis une machine externe :

Fenêtre de terminal
# Depuis un client sur le réseau public
curl http://<ip-passerelle>:8080/
BONJOUR-DEPUIS-HOTE-INTERNE

Le client externe croit parler à la passerelle sur 8080 ; il reçoit en réalité la réponse du serveur interne sur son port 80. C'est le port forwarding.

Vos deux règles vivent dans une seule table ip nat. La visualiser confirme l'ensemble :

Fenêtre de terminal
sudo nft list table ip nat
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 10.0.0.0/24 oifname "eth0" masquerade
}
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
iifname "eth0" tcp dport 8080 dnat to 10.0.0.2:80
}
}

Le NAT n'est pas magique : le noyau suit chaque connexion dans une table (conntrack) pour réécrire le trafic retour au vol. C'est l'outil de diagnostic numéro un du NAT. Pour la connexion sortante (MASQUERADE) :

Fenêtre de terminal
sudo conntrack -L | grep 10.0.0.2
tcp 6 ... src=10.0.0.2 dst=1.1.1.1 sport=60184 dport=80 src=1.1.1.1 dst=192.168.10.79 sport=80 dport=60184 [ASSURED]

Lisez les deux tuples : la connexion d'origine (src=10.0.0.2) et sa réécriture pour le retour (dst=192.168.10.79, l'IP de la passerelle). La source a bien été masquée.

Pour la redirection entrante (DNAT) :

Fenêtre de terminal
sudo conntrack -L | grep dport=8080
tcp 6 ... src=192.168.10.11 dst=192.168.10.79 sport=49334 dport=8080 src=10.0.0.2 dst=192.168.10.11 sport=80 dport=49334 [ASSURED]

Ici, la destination est réécrite : le client visait 192.168.10.79:8080, le retour vient de 10.0.0.2:80. La traduction est prouvée dans les deux sens.

Les règles ajoutées à la volée disparaissent au redémarrage. Pour les conserver, écrivez le ruleset dans le fichier chargé par le service nftables, puis activez-le :

Fenêtre de terminal
sudo nft list ruleset | sudo tee /etc/nftables.conf
sudo systemctl enable --now nftables

Au prochain démarrage, nftables.service rejoue /etc/nftables.conf, et le fichier sysctl.d réactive le routage. La passerelle est reconstruite à l'identique.

Une passerelle qui route et redirige est une cible : quelques réflexes s'imposent.

  • Ne routez que ce qui doit l'être. Ajoutez une chaîne forward en filter qui n'accepte que les flux légitimes (du LAN vers le WAN, et le retour établi), plutôt qu'une politique accept globale.
  • Restreignez le DNAT à la source si possible : iifname "eth0" ip saddr <réseau-de-confiance> tcp dport 8080 dnat ... limite qui peut atteindre le service interne.
  • Le service exposé reste responsable de sa propre sécurité : le DNAT ne fait que router, il ne durcit rien. Placez les services exposés en DMZ.
  • Journalisez les paquets jetés pour repérer les tentatives : une règle log prefix "DROP " avant la politique par défaut.
SymptômeCause probableSolution
L'hôte interne n'atteint pas InternetRoutage désactivésysctl net.ipv4.ip_forward doit valoir 1
MASQUERADE sans effetMauvaise interface oifnameVérifier avec ip route show default
Le DNAT ne répond pasL'hôte interne ne route pas par la passerelleMettre la passerelle en route par défaut de l'hôte
Ça marche puis se coupeRègle forward qui bloque le retourAutoriser l'état established,related
Les règles disparaissent au rebootRuleset non persisténft list ruleset > /etc/nftables.conf + systemctl enable nftables
Doute sur la traductionDiagnosticconntrack -L montre les deux tuples

Monter soi-même la passerelle reste le meilleur moyen d'ancrer les deux sens du NAT : ce lab vous fait activer le routage IP, écrire les règles MASQUERADE et DNAT avec nftables, puis rendre le ruleset persistant au redémarrage.

  • MASQUERADE dans postrouting partage une connexion sortante derrière l'IP de la passerelle.
  • DNAT dans prerouting redirige un port entrant vers un hôte interne.
  • net.ipv4.ip_forward=1 est le préalable absolu : sans routage, aucune règle ne s'applique.
  • conntrack -L est l'outil de diagnostic : ses deux tuples montrent la traduction dans les deux sens.
  • L'hôte interne doit avoir la passerelle comme route par défaut, sinon le retour casse le NAT.
  • Persistez avec /etc/nftables.conf et le service nftables, sinon tout part au redémarrage.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn