S03 - Pare-feu sous Linux : iptables, nftables, ufw
Objectif
Filtrer le trafic d’un serveur Linux, et transformer une VM Linux en routeur NAT (comme la VM routeur du projet transversal).
1. Qui fait quoi ?
Le filtrage est fait dans le noyau par Netfilter. On le pilote avec un outil :
| Outil | Statut en 2026 | Usage |
|---|---|---|
iptables | Toujours très utilisé (en réalité souvent iptables-nft, qui traduit vers nftables) | Cours, TP, scripts existants |
nftables (nft) | Remplaçant officiel (défaut Debian 10+) | Nouvelles installations |
ufw | Surcouche simple (Ubuntu, Pop!_OS) | Poste de travail |
firewalld | Surcouche à zones (Fedora, RHEL) | Serveurs RHEL |
2. Le parcours d’un paquet dans iptables
flowchart LR IN(("Paquet entrant")) --> PRE["PREROUTING<br/>(table nat : DNAT)"] PRE --> D{"Pour moi ?"} D -- oui --> INPUT["INPUT<br/>(filter)"] --> APP["Programme local<br/>(sshd, apache…)"] D -- non --> FWD["FORWARD<br/>(filter) — routeur"] --> POST APP --> OUT["OUTPUT"] --> POST["POSTROUTING<br/>(table nat : SNAT / MASQUERADE)"] POST --> SORTIE(("Paquet sortant"))
| Chaîne | Trafic concerné |
|---|---|
| INPUT | Destiné à la machine elle-même |
| OUTPUT | Émis par la machine |
| FORWARD | Qui traverse la machine (routeur) |
| PREROUTING / POSTROUTING | Avant / après la décision de routage (NAT) |
Actions (targets) : ACCEPT (laisser passer), DROP (jeter sans répondre), REJECT (refuser en prévenant), LOG (journaliser), MASQUERADE / SNAT / DNAT (NAT).
3. iptables : les commandes essentielles
sudo iptables -L -n -v --line-numbers # lister les règles (filter)
sudo iptables -t nat -L -n -v # lister les règles NAT
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT # -A = ajouter à la fin
sudo iptables -I INPUT 1 -s 10.0.0.5 -j DROP # -I = insérer en position 1
sudo iptables -D INPUT 3 # supprimer la règle n°3
sudo iptables -P INPUT DROP # politique par défaut
sudo iptables -F # tout vider (attention !)En SSH sur une machine distante : autorise le port 22 AVANT de passer
INPUTenDROP, sinon tu te coupes toi-même.
Pare-feu minimal d’un serveur web
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
sudo iptables -P INPUT DROPRendre les règles permanentes (Debian/Ubuntu)
sudo apt install iptables-persistent # propose de sauvegarder les règles actuelles
sudo netfilter-persistent save # après chaque modification
# fichiers : /etc/iptables/rules.v4 et rules.v64. Routeur NAT Linux (projet transversal)
flowchart LR VMweb["VM Web<br/>172.30.16.2"] --> R["VM Routeur<br/>eth1 172.30.16.1 | eth0 172.16.118.6"] VMbdd["VM BDD<br/>172.30.16.5"] --> R R -->|"MASQUERADE :<br/>source réécrite en 172.16.118.6"| LABO(("Réseau labo / Internet"))
# 1) Autoriser le transit des paquets
sudo sysctl -w net.ipv4.ip_forward=1 # immédiat
echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-routeur.conf # permanent
# 2) NAT
sudo iptables -t nat -A POSTROUTING -s 172.30.16.0/24 -o eth0 -j MASQUERADE
# 3) Autoriser le transit
sudo iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A FORWARD -s 172.30.16.0/24 -j ACCEPTLes VM internes doivent avoir le routeur comme passerelle (172.30.16.1).
Publier un service interne (DNAT / port forwarding)
# Tout ce qui arrive sur le port 8080 du routeur part vers le serveur web interne
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination 172.30.16.2:80
sudo iptables -A FORWARD -p tcp -d 172.30.16.2 --dport 80 -j ACCEPTAu projet, c’est HAProxy qui jouait ce rôle (reverse proxy) → SV03 - HAProxy (reverse proxy et répartition de charge).
Script complet
Fichier : scripts/securite/routeur_nat.sh - usage : sudo ./routeur_nat.sh eth0 eth1 172.30.16.0/24
#!/usr/bin/env bash
set -euo pipefail
interface_externe="$1"; interface_interne="$2"; reseau_interne="$3"
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-routeur.conf
sysctl --system > /dev/null
iptables -F; iptables -t nat -F; iptables -X
iptables -P INPUT DROP; iptables -P FORWARD DROP; iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i "$interface_interne" -o "$interface_externe" -s "$reseau_interne" -j ACCEPT
iptables -t nat -A POSTROUTING -s "$reseau_interne" -o "$interface_externe" -j MASQUERADE
netfilter-persistent saveEt scripts/securite/pare_feu_serveur.sh : ouvre automatiquement 80/443 si Apache tourne et 3306 si MariaDB tourne (fonction firewall du TP Linux B2).
5. La même chose en nftables (syntaxe moderne)
Fichier /etc/nftables.conf :
#!/usr/sbin/nft -f
flush ruleset
table inet filtre {
chain entree {
type filter hook input priority 0; policy drop;
iif "lo" accept
ct state established,related accept
ip protocol icmp accept
tcp dport { 22, 80, 443 } accept
}
chain transit {
type filter hook forward priority 0; policy drop;
ct state established,related accept
ip saddr 172.30.16.0/24 oifname "eth0" accept
}
}
table ip nat {
chain sortie {
type nat hook postrouting priority 100;
ip saddr 172.30.16.0/24 oifname "eth0" masquerade
}
}sudo nft -c -f /etc/nftables.conf # vérifier la syntaxe sans appliquer
sudo systemctl enable --now nftables # appliquer et garder au démarrage
sudo nft list ruleset # afficher6. ufw : le plus simple (Pop!_OS, Ubuntu)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh # = 22/tcp
sudo ufw allow from 192.168.1.0/24 to any port 3306 proto tcp
sudo ufw enable
sudo ufw status numbered
sudo ufw delete 2Sur Arch : sudo pacman -S ufw && sudo systemctl enable --now ufw.