iptables équipe plus de 90 % des serveurs Linux en production selon les données consolidées de la communauté Netfilter. Pourtant, une mauvaise configuration suffit pour exposer un service critique, bloquer Docker ou verrouiller votre propre accès SSH. Ce tutoriel vous guide à travers 12 étapes concrètes pour configurer un pare-feu robuste sur Ubuntu 24.04 LTS ou Debian 12, de l’installation jusqu’à la persistance des règles en passant par la protection contre les attaques par force brute.
La version installée sur Ubuntu 24.04 LTS est iptables 1.8.10-3ubuntu2, accompagnée de nftables 1.1.0-2 et d’ufw 0.36.2-6. Sur Ubuntu 24.10, les paquets montent respectivement à iptables 1.8.11-2ubuntu1 et nftables 1.1.1-1build1. Ces versions coexistent dans le sous-système Netfilter du noyau Linux, ce qui crée des subtilités importantes avant de modifier vos règles.
Prérequis
- Système d’exploitation : Ubuntu 22.04 LTS, Ubuntu 24.04 LTS, Ubuntu 24.10 ou Debian 12 (Bookworm)
- Accès root ou sudo : toutes les commandes iptables nécessitent des privilèges élevés
- Connexion SSH active : si vous travaillez à distance, ne coupez jamais l’accès SSH avant d’avoir validé vos règles
- Versions logicielles confirmées : iptables 1.8.x, kernel Linux 5.15 ou supérieur
- Accès console ou IPMI : en cas de blocage accidentel, accès au serveur hors SSH indispensable
- Notions réseau de base : ports TCP/UDP, adresses IP, protocole ICMP
Ce tutoriel traite un serveur standard sans Docker dans un premier temps. La section dédiée à Docker et iptables couvre les interactions spécifiques à cette configuration.
Architecture d’iptables : tables, chaînes et cibles
iptables filtre les paquets réseau à travers une hiérarchie de tables, de chaînes et de règles. Comprendre cette architecture avant d’écrire la moindre règle évite la grande majorité des erreurs de configuration.
Les quatre tables principales
| Table | Rôle | Chaînes disponibles | Cas d’usage typique |
|---|---|---|---|
| filter | Filtrage des paquets (table par défaut) | INPUT, OUTPUT, FORWARD | Autoriser ou bloquer du trafic |
| nat | Traduction d’adresses réseau | PREROUTING, OUTPUT, POSTROUTING | Redirection de ports, masquage IP |
| mangle | Modification des en-têtes de paquets | Toutes les 5 chaînes | QoS, marquage de paquets |
| raw | Traitement avant le suivi de connexion | PREROUTING, OUTPUT | Contournement du conntrack |
Les cinq chaînes standard
Chaque paquet réseau traverse un chemin précis selon sa direction :
- INPUT : paquets destinés au serveur local (port 22, 80, 443…)
- OUTPUT : paquets émis par le serveur local
- FORWARD : paquets traversant le serveur (routeur, passerelle VPN)
- PREROUTING : paquets avant routage (redirection de destination)
- POSTROUTING : paquets après routage (masquage d’adresse source)
Pour un serveur standard (non routeur), vous utiliserez quasi exclusivement la table filter et les chaînes INPUT, OUTPUT et FORWARD. La chaîne FORWARD reste vide avec une politique DROP sauf si le serveur fait du routage ou du VPN.
Les cibles (targets) définissent l’action appliquée au paquet :
- ACCEPT : laisser passer le paquet
- DROP : rejeter le paquet silencieusement
- REJECT : rejeter et envoyer un message d’erreur à l’expéditeur
- LOG : journaliser le paquet sans l’arrêter, la règle suivante s’applique
- MASQUERADE : masquage d’IP pour le NAT dynamique
Étape 1 : Vérifier et installer iptables
Sur les distributions modernes, iptables est généralement préinstallé. Vérifiez d’abord sa présence et sa version :
# Vérifier la version d'iptables installée
sudo iptables --version
# Résultat attendu sur Ubuntu 24.04 LTS :
# iptables v1.8.10 (nf_tables)
# Vérifier le backend actif
sudo update-alternatives --display iptables
# Afficher toutes les règles actives avec compteurs
sudo iptables -L -v -n
# Exemple de sortie sur un serveur vierge :
# Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
# target prot opt source destination
#
# Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
# target prot opt source destination
#
# Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
# target prot opt source destination
La mention (nf_tables) indique qu’iptables utilise nftables comme backend. C’est le comportement par défaut depuis Ubuntu 20.04. Trois chaînes vides avec la politique ACCEPT signifient qu’aucune règle ne filtre le trafic : état le plus vulnérable.
Si iptables est absent (serveur minimal) :
# Installation sur Ubuntu/Debian
sudo apt update
sudo apt install -y iptables iptables-persistent
# Sur CentOS/RHEL/AlmaLinux 9
sudo dnf install -y iptables-services
sudo systemctl enable iptables
sudo systemctl start iptables
Étape 2 : Sauvegarder et créer un script de configuration
Travailler avec un script plutôt qu’en ligne de commande directe présente deux avantages : reproductibilité complète et possibilité d’inclure un iptables -F initial pour repartir d’un état propre.
# Sauvegarder la configuration actuelle avant toute modification
sudo mkdir -p /etc/iptables
sudo iptables-save > /etc/iptables/rules.v4.backup
# Créer le script de configuration
sudo nano /etc/iptables/setup-firewall.sh
Structure initiale du script (les règles seront ajoutées étape par étape) :
#!/bin/bash
# Pare-feu iptables - Configuration serveur Linux
# Mis à jour : juin 2026
# ---- REMISE À ZÉRO ----
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
# Politique temporairement en ACCEPT pendant la configuration
# (sera basculée en DROP à la fin du script)
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
echo "Remise à zéro effectuée"
# Rendre le script exécutable
sudo chmod +x /etc/iptables/setup-firewall.sh
Étape 3 : Autoriser le trafic loopback
L’interface loopback (lo, adresse 127.0.0.1) est utilisée par les processus locaux pour communiquer entre eux. Bloquer cette interface casse des services entiers : bases de données locales, sockets Unix, services systemd.
# Autoriser tout le trafic sur l'interface loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# Bloquer les paquets prétendant venir de 127.0.0.1 sur une interface externe
# Protection contre le spoofing de l'adresse loopback
iptables -A INPUT -s 127.0.0.0/8 ! -i lo -j DROP
La troisième règle protège contre une technique d’attaque rare : des paquets forgés avec l’adresse source 127.0.0.1 arrivant sur une interface externe. Sans cette protection, certains services locaux pourraient accepter ces paquets en croyant qu’ils viennent de la machine elle-même.
Étape 4 : Autoriser les connexions établies et liées
Le module conntrack (connection tracking) d’iptables suit l’état des connexions réseau. Cette règle est probablement la plus importante de toute la configuration car elle permet au serveur de recevoir les réponses aux connexions qu’il initie lui-même :
# Bloquer d'abord les paquets invalides (avant ESTABLISHED pour les éliminer tôt)
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
# Autoriser les connexions déjà établies et les connexions liées
# (réponses aux connexions sortantes initiées par le serveur)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Vérifier que le module conntrack est chargé
lsmod | grep conntrack
L’état ESTABLISHED couvre les paquets faisant partie d’une connexion bidirectionnelle active (mises à jour apt, requêtes DNS sortantes, etc.). L’état RELATED couvre les connexions auxiliaires, comme les canaux de données FTP passif. Sans cette règle, le serveur ne pourrait pas recevoir de réponses à ses propres requêtes sortantes.
Étape 5 : Protéger l’accès SSH
SSH sur le port 22 est la cible principale des scans automatisés. Les serveurs exposés reçoivent entre 1 000 et 5 000 tentatives de connexion par jour selon les données de Shodan (2025). Une règle d’autorisation simple ne suffit pas : il faut combiner autorisation et limitation de débit.
# Cas 1 : Port SSH standard (22), accès depuis n'importe quelle IP
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
# Cas 2 : Port SSH personnalisé (exemple : 2222)
# iptables -A INPUT -p tcp --dport 2222 -m conntrack --ctstate NEW -j ACCEPT
# Cas 3 : Restreindre SSH à une plage IP spécifique (recommandé en production)
# Remplacer 203.0.113.0/24 par votre plage d'IP réelle
# iptables -A INPUT -p tcp -s 203.0.113.0/24 --dport 22 -m conntrack --ctstate NEW -j ACCEPT
Étape 6 : Limiter les tentatives de connexion SSH (anti-brute force)
La limitation de débit (rate limiting) bloque les attaques par force brute avant qu’elles atteignent le service SSH. Cette technique fonctionne avec le module recent d’iptables et ne nécessite pas Fail2ban, bien que les deux puissent coexister :
# Protection SSH anti-brute force avec le module recent
# Enregistrer l'IP source dans la liste "ssh_brute"
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --set --name ssh_brute
# Bloquer les IP ayant plus de 4 tentatives en 60 secondes
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --update --seconds 60 --hitcount 5 --name ssh_brute \
-j DROP
# Variante avec journalisation avant blocage
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
-m recent --update --seconds 60 --hitcount 5 --name ssh_brute \
-j LOG --log-prefix "SSH_BRUTE_FORCE: " --log-level 7
Ces règles bloquent silencieusement les scanners automatisés tout en permettant à un utilisateur légitime qui ferait plusieurs tentatives échouées de se reconnecter après 60 secondes. Ajustez --hitcount et --seconds selon votre politique de sécurité. Pour une protection plus agressive, réduisez --hitcount à 3.
Étape 7 : Autoriser le trafic web (HTTP et HTTPS)
Si votre serveur héberge des applications web, ouvrez les ports 80 et 443. Si vous utilisez Let’s Encrypt pour les certificats TLS, le port 80 est également nécessaire pour la validation HTTP-01 :
# Autoriser HTTP (port 80)
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT
# Autoriser HTTPS (port 443) sur TCP
iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT
# Autoriser QUIC/HTTP3 sur UDP 443 (serveurs Nginx 1.25+ ou Caddy)
iptables -A INPUT -p udp --dport 443 -m conntrack --ctstate NEW -j ACCEPT
# Si serveur mail : SMTP (25), SMTPS (465), Submission (587), IMAP (993), POP3S (995)
# iptables -A INPUT -p tcp -m multiport --dports 25,465,587,993,995 \
# -m conntrack --ctstate NEW -j ACCEPT
La règle QUIC sur UDP 443 couvre HTTP/3. Nginx 1.25+ et Caddy le supportent nativement. Si votre stack n’utilise pas encore HTTP/3, omettez la ligne UDP pour réduire la surface d’attaque.
Étape 8 : Configurer les règles ICMP (ping)
Bloquer ICMP totalement est une mauvaise pratique souvent recommandée à tort dans des tutoriels dépassés. ICMP remplit des fonctions critiques pour le bon fonctionnement du réseau, notamment la découverte du MTU (path MTU discovery). Voici la configuration recommandée :
# Autoriser les messages ICMP essentiels en entrée
# echo-request (type 8) : permet le ping entrant, limité à 1/s
iptables -A INPUT -p icmp --icmp-type echo-request -m limit \
--limit 1/s --limit-burst 5 -j ACCEPT
# destination-unreachable (type 3) : nécessaire pour path MTU discovery
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
# time-exceeded (type 11) : nécessaire pour traceroute et diagnostics
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
# Bloquer tous les autres types ICMP (ping flood, etc.)
iptables -A INPUT -p icmp -j DROP
La limite de 1 ping par seconde avec un burst de 5 paquets permet le diagnostic réseau normal tout en bloquant les attaques par ping flood. Un attaquant envoyant des milliers de pings par seconde ne franchira pas cette limite.
Étape 9 : Journaliser les paquets rejetés
Avant d’appliquer la politique de rejet par défaut, ajoutez des règles de journalisation. Ces logs sont invaluables pour diagnostiquer les blocages légitimes et détecter les tentatives d’intrusion :
# Journaliser les paquets INPUT rejetés (limité à 5/min pour éviter le log flooding)
iptables -A INPUT -m limit --limit 5/min --limit-burst 10 \
-j LOG --log-prefix "IPT_INPUT_DROP: " --log-level 7
# Journaliser les paquets FORWARD rejetés
iptables -A FORWARD -m limit --limit 5/min --limit-burst 10 \
-j LOG --log-prefix "IPT_FORWARD_DROP: " --log-level 7
# Consulter les logs en temps réel
sudo journalctl -f | grep "IPT_INPUT_DROP"
# Ou dans /var/log/kern.log sur Debian/Ubuntu
sudo tail -f /var/log/kern.log | grep "IPT_"
Le niveau de log 7 (debug) envoie les messages vers le journal du noyau. La limite de 5 messages par minute empêche les attaques par déni de service par remplissage de logs. Sans cette limite, un attaquant pourrait saturer votre partition /var/log en quelques minutes.
Étape 10 : Appliquer la politique de refus par défaut (DROP)
Cette étape est la plus critique. Elle bascule la politique par défaut de ACCEPT vers DROP pour les chaînes INPUT et FORWARD. Après cette commande, tout trafic non explicitement autorisé sera rejeté :
# ATTENTION : vérifiez que les règles SSH sont bien en place avant cette commande
# En cas de doute : sudo iptables -L INPUT -n | grep "dpt:22"
# Politique DROP pour INPUT (trafic entrant vers le serveur)
iptables -P INPUT DROP
# Politique DROP pour FORWARD (trafic transitant par le serveur)
iptables -P FORWARD DROP
# Laisser OUTPUT en ACCEPT (le serveur peut initier des connexions sortantes)
iptables -P OUTPUT ACCEPT
# Vérification immédiate : votre session SSH doit rester active
echo "Règles appliquées. Session SSH maintenue."
# Afficher la configuration finale avec numéros de ligne
iptables -L -v -n --line-numbers
Si vous perdez votre accès SSH après cette commande, vos règles d’autorisation SSH (étape 5) n’ont pas été appliquées avant la politique DROP. Accédez au serveur via la console VNC ou IPMI et exécutez iptables -P INPUT ACCEPT pour retrouver l’accès, puis recommencez dans le bon ordre.
Astuce de sécurité : avant d’appliquer la politique DROP, planifiez une remise à zéro automatique avec la commande at :
# Planifier une remise à zéro dans 5 minutes en cas de blocage accidentel
echo "iptables -P INPUT ACCEPT; iptables -F" | sudo at now + 5 minutes
# Appliquer vos règles... puis annuler le job at si tout va bien
sudo atrm 1 # Remplacer 1 par le numéro de job affiché par at
Étape 11 : Persister les règles avec iptables-persistent
Par défaut, les règles iptables sont volatiles : elles disparaissent au redémarrage. Le paquet iptables-persistent les sauvegarde et les recharge automatiquement au boot :
# Installer iptables-persistent si pas encore fait
sudo apt install -y iptables-persistent
# Sauvegarder les règles IPv4 actuelles
sudo iptables-save > /etc/iptables/rules.v4
# Sauvegarder les règles IPv6 actuelles
sudo ip6tables-save > /etc/iptables/rules.v6
# Exemple de contenu de /etc/iptables/rules.v4 :
# # Generated by iptables-save v1.8.10
# *filter
# :INPUT DROP [0:0]
# :FORWARD DROP [0:0]
# :OUTPUT ACCEPT [0:0]
# -A INPUT -i lo -j ACCEPT
# -A INPUT -s 127.0.0.0/8 ! -i lo -j DROP
# -A INPUT -m conntrack --ctstate INVALID -j DROP
# -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# -A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
# -A INPUT -p tcp -m tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT
# -A INPUT -p tcp -m tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT
# COMMIT
Pour recharger les règles depuis le fichier sans redémarrer :
# Recharger les règles IPv4
sudo iptables-restore < /etc/iptables/rules.v4
# Activer le service de persistance au démarrage
sudo systemctl enable netfilter-persistent
sudo systemctl status netfilter-persistent
# Vérifier que les règles survivent après reboot (test sur VM recommandé)
sudo reboot
# Après redémarrage : sudo iptables -L -v -n
Étape 12 : Configurer IPv6 avec ip6tables
IPv6 est activé par défaut sur Ubuntu 22.04+ et Debian 12. Une configuration iptables sans ip6tables laisse le serveur totalement ouvert sur IPv6, contournant toutes vos règles IPv4 :
# Vérifier les règles IPv6 actuelles
sudo ip6tables -L -v -n
# Configuration minimale IPv6
# Loopback
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT
# Connexions établies
ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# ICMPv6 : OBLIGATOIRE pour le bon fonctionnement d'IPv6
# NDP (Neighbor Discovery Protocol) utilise ICMPv6
# Ne JAMAIS bloquer ICMPv6 totalement contrairement à IPv4
ip6tables -A INPUT -p ipv6-icmp -j ACCEPT
ip6tables -A OUTPUT -p ipv6-icmp -j ACCEPT
# SSH sur IPv6
ip6tables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
# HTTP/HTTPS sur IPv6
ip6tables -A INPUT -p tcp -m multiport --dports 80,443 \
-m conntrack --ctstate NEW -j ACCEPT
# Politique DROP
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
# Sauvegarder
sudo ip6tables-save > /etc/iptables/rules.v6
Contrairement à IPv4, ne jamais bloquer ICMPv6 totalement. IPv6 en dépend fondamentalement pour la résolution d'adresses (NDP remplace ARP), la détection de doublons d'adresse et la découverte des routeurs. Bloquer ICMPv6 rend le réseau IPv6 non fonctionnel même si les adresses sont correctement configurées.
iptables vs nftables vs UFW : comparatif 2026
Le choix entre iptables, nftables et UFW dépend de votre contexte. Voici un comparatif factuel basé sur les versions disponibles sur Ubuntu 24.04 LTS :
| Critère | iptables 1.8.10 | nftables 1.1.0 | UFW 0.36.2 |
|---|---|---|---|
| Syntaxe | Commandes séparées par table | Syntaxe unifiée, plus lisible | Simplicité maximale |
| Performance sur grandes règles | Bonne | Meilleure (évaluation par ensembles) | Dépend du backend |
| Gestion IPv4 + IPv6 | Deux commandes distinctes | Gestion unifiée en une commande | Unifiée via backend |
| Compatibilité Docker | Native, chaîne DOCKER intégrée | Partielle via iptables-compat | Problèmes documentés |
| Courbe d'apprentissage | Moyenne | Plus complexe initialement | Faible |
| Scripts automatisés | Excellent (historique abondant) | Bon, en progression | Limité |
| Documentation ANSSI | Abondante, française | En progression | Conseillé débutants |
| Package Ubuntu 24.04 | 1.8.10-3ubuntu2 | 1.1.0-2 | 0.36.2-6 |
Sur Ubuntu 24.04, iptables utilise nftables comme backend par défaut (visible avec iptables --version qui affiche nf_tables). Les deux outils coexistent dans Netfilter. La bonne approche en 2026 : utiliser iptables si vous avez une base existante de règles ou si Docker est dans votre stack, envisager la migration vers nftables natif pour les nouveaux déploiements sans Docker.
iptables et Docker : l'interaction à ne pas négliger
Docker modifie automatiquement les règles iptables pour gérer le réseau des conteneurs. Ce comportement crée des surprises, notamment des ports exposés non prévus qui contournent votre politique DROP.
Quand vous démarrez un conteneur avec -p 8080:80, Docker ajoute automatiquement des règles dans la chaîne DOCKER de la table nat et dans FORWARD. Ces règles ignorent votre politique DROP sur FORWARD car elles sont évaluées avant vos règles personnalisées :
# Voir les règles créées par Docker
sudo iptables -L DOCKER -v -n
sudo iptables -t nat -L DOCKER -v -n
# Solution 1 : Binder uniquement sur localhost (recommandée pour services internes)
# docker run -p 127.0.0.1:8080:80 mon-service
# Solution 2 : Utiliser la chaîne DOCKER-USER (recommandée pour restrictions)
# Docker consulte toujours DOCKER-USER avant ses propres règles
# Bloquer l'accès externe à un port Docker :
iptables -I DOCKER-USER -i eth0 -p tcp --dport 8080 -j DROP
# Autoriser uniquement une IP spécifique vers ce port
iptables -I DOCKER-USER -i eth0 -s 203.0.113.10 -p tcp --dport 8080 -j ACCEPT
iptables -A DOCKER-USER -i eth0 -p tcp --dport 8080 -j DROP
La chaîne DOCKER-USER est la solution officielle recommandée par Docker Inc. pour ajouter des règles persistantes que Docker ne supprime pas lors du redémarrage du service. Toutes vos restrictions sur les ports exposés doivent passer par cette chaîne.
Sur Ubuntu 24.04.3, un problème fréquent signalé dans les forums concerne les règles DNS cassées après activation d'iptables sur un serveur exécutant systemd-resolved et Docker simultanément. Solution : autoriser explicitement le port 53 en sortie.
# Autoriser les requêtes DNS sortantes (nécessaire avec OUTPUT en ACCEPT par défaut)
# Si vous avez restreint OUTPUT, ajoutez ces règles :
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
# DNS local de systemd-resolved
iptables -A OUTPUT -d 127.0.0.53 -j ACCEPT
Tableau de référence : règles iptables courantes
| Cas d'usage | Commande iptables | Notes |
|---|---|---|
| Autoriser MySQL depuis réseau interne | iptables -A INPUT -p tcp -s 10.0.0.0/8 --dport 3306 -j ACCEPT | N'exposez jamais MySQL publiquement |
| Bloquer une IP spécifique | iptables -I INPUT -s 198.51.100.1 -j DROP | -I insère en tête de chaîne |
| Redirection de port (NAT) | iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080 | Table nat, pas filter |
| Masquage IP (partage connexion) | iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE | Activer ip_forward également |
| Bloquer les scans SYN flood | iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT | Limite les attaques SYN |
| Bloquer les paquets invalides | iptables -A INPUT -m conntrack --ctstate INVALID -j DROP | À placer avant les règles ACCEPT |
| Bloquer scan Xmas (Nmap) | iptables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP | Détection de scans agressifs |
| Bloquer scan NULL (Nmap) | iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP | Combinaison de flags invalide |
| Lister règles avec numéros | iptables -L INPUT --line-numbers -n | Pour supprimer par numéro |
| Supprimer une règle par numéro | iptables -D INPUT 3 | Supprime la règle n°3 de INPUT |
Pièges courants et erreurs à éviter absolument
Piège 1 : Appliquer DROP avant d'autoriser SSH
L'ordre des commandes est critique. Si vous exécutez iptables -P INPUT DROP avant d'ajouter la règle SSH, vous perdez immédiatement votre accès distant. Vérifiez toujours avec iptables -L INPUT -n | grep "dpt:22" que la règle SSH est présente avant de basculer en DROP.
Piège 2 : Oublier ip6tables
iptables ne contrôle que IPv4. Sur tout serveur moderne avec une adresse IPv6 publique, le pare-feu IPv4 le plus strict du monde ne protège pas contre un scan IPv6 si ip6tables n'est pas configuré. Vérifiez votre exposition IPv6 avec curl -6 ifconfig.io.
Piège 3 : Confondre -I et -A
-A (append) ajoute une règle en fin de chaîne. -I (insert) l'ajoute en tête par défaut. iptables évalue les règles dans l'ordre séquentiel. Une règle DROP ajoutée avec -A après une règle ACCEPT pour le même trafic sera ignorée. Utilisez -I pour les blocages d'urgence et -A pour les règles normales dans le bon ordre logique.
Piège 4 : Ne pas persister les règles
Sans iptables-persistent, toutes vos règles disparaissent au redémarrage. Un serveur redémarré après une mise à jour de sécurité devient soudainement totalement ouvert. Vérifiez que les règles sont dans /etc/iptables/rules.v4 après chaque modification importante.
Piège 5 : Ignorer l'interaction avec Docker
Docker contourne les règles INPUT pour les ports mappés. Un docker run -p 0.0.0.0:8080:80 expose le port 8080 publiquement même avec iptables -P INPUT DROP. La seule solution correcte : utiliser la chaîne DOCKER-USER ou binder uniquement sur localhost (127.0.0.1:8080:80).
Piège 6 : Bloquer ICMPv6 sur IPv6
Beaucoup de tutoriels copiés depuis IPv4 bloquent tout ICMP par défaut. Sur IPv6, cette pratique casse complètement la connectivité car NDP (Neighbor Discovery Protocol) utilise ICMPv6. Autorisez toujours -p ipv6-icmp -j ACCEPT dans ip6tables.
Piège 7 : Bloquer les paquets RELATED sans le module nf_conntrack_ftp
FTP actif utilise des connexions de données sur des ports aléatoires. Pour que la règle ESTABLISHED,RELATED fonctionne avec FTP, le module nf_conntrack_ftp doit être chargé. Vérifiez avec lsmod | grep conntrack_ftp et chargez-le avec modprobe nf_conntrack_ftp, puis ajoutez-le à /etc/modules.
Piège 8 : Utiliser REJECT pour la politique par défaut
REJECT envoie un message d'erreur à l'expéditeur, confirmant que le port est filtré et que le serveur existe. DROP rejette silencieusement, ce qui ralentit les scans et ne révèle rien. Utilisez DROP pour la politique par défaut et REJECT seulement pour des règles spécifiques où informer l'expéditeur est pertinent (réseau interne, par exemple).
Dépannage iptables : 10 problèmes fréquents et leurs solutions
| Problème | Symptôme | Commande de diagnostic | Solution |
|---|---|---|---|
| Session SSH coupée | Connexion fermée après -P INPUT DROP | Console IPMI | iptables -P INPUT ACCEPT puis reconfigurer dans l'ordre |
| Port 80 inaccessible | Timeout navigateur | iptables -L INPUT -n | grep 80 | Ajouter règle --dport 80 -j ACCEPT |
| Docker port ignoré par les règles | Port exposé malgré INPUT DROP | iptables -L DOCKER -n | Utiliser la chaîne DOCKER-USER |
| Règles perdues au redémarrage | Serveur ouvert après reboot | ls -la /etc/iptables/rules.v4 | iptables-save > /etc/iptables/rules.v4 |
| DNS ne fonctionne plus | Résolution d'adresses échoue | dig @8.8.8.8 google.com | Autoriser OUTPUT UDP/TCP port 53 |
| apt update échoue | Timeout sur les dépôts | iptables -L OUTPUT -n | Politique OUTPUT doit être ACCEPT |
| Ping impossible | ICMP bloqué | iptables -L INPUT -n | grep icmp | Ajouter règle icmp echo-request ACCEPT |
| Conflit UFW/iptables | Règles dupliquées contradictoires | ufw status; iptables -L -n | Désactiver UFW ou utiliser iptables seul |
| Erreur "Unknown option" | Syntaxe incorrecte | Lire le message d'erreur précis | man iptables, vérifier guillemets et tirets |
| Module absent | "No such file or directory" | lsmod | grep [module] | modprobe [module], ajouter à /etc/modules |
Conseils avancés
Protection anti-DDoS de couche réseau
iptables seul ne peut pas arrêter un DDoS volumétrique (votre liaison est saturée avant que les paquets atteignent le serveur), mais peut filtrer des attaques syn-flood et UDP flood de faible intensité :
# Protection anti-SYN flood
iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP
# Bloquer les scans Nmap : Xmas scan, NULL scan, SYN/RST
iptables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
# Protection contre le spoofing RFC 1918 depuis l'extérieur (interface eth0)
iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DROP
iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j DROP
iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j DROP
# Limiter les connexions par IP (protection contre les connexions massives)
iptables -A INPUT -p tcp --syn -m recent --set --name conn_limit
iptables -A INPUT -p tcp --syn -m recent --update --seconds 1 \
--hitcount 20 --name conn_limit -j DROP
Chaînes personnalisées pour une meilleure organisation
Pour les configurations complexes avec plusieurs dizaines de règles, les chaînes personnalisées améliorent la lisibilité et les performances en évitant le re-parcours de règles non applicables :
# Créer une chaîne dédiée aux services web
iptables -N SERVICES_WEB
iptables -A INPUT -p tcp -j SERVICES_WEB
# Remplir la chaîne
iptables -A SERVICES_WEB --dport 80 -j ACCEPT
iptables -A SERVICES_WEB --dport 443 -j ACCEPT
iptables -A SERVICES_WEB --dport 8080 -j ACCEPT
# Créer une chaîne pour la blocklist d'IPs
iptables -N BLOCKLIST
iptables -A INPUT -j BLOCKLIST
iptables -A BLOCKLIST -s 198.51.100.0/24 -j DROP
# Lister toutes les chaînes existantes
iptables -L -n --line-numbers
Intégration avec Fail2ban
Fail2ban surveille les logs et ajoute dynamiquement des règles iptables pour bloquer les IPs malveillantes. Il crée sa propre chaîne f2b-sshd et l'insère dans INPUT. Vérifiez la compatibilité de backend :
# Dans /etc/fail2ban/jail.local, spécifier le backend iptables
# [sshd]
# banaction = iptables-multiport
# banaction_allports = iptables-allports
# Vérifier les chaînes Fail2ban actives
sudo iptables -L | grep f2b
# Lister les IPs actuellement bannies pour SSH
sudo fail2ban-client status sshd
# Débannir une IP manuellement
sudo fail2ban-client set sshd unbanip 203.0.113.50
Script de configuration complet et opérationnel
Ce script intègre toutes les étapes précédentes dans un fichier unique. Adaptez les variables en haut selon votre environnement :
#!/bin/bash
# /etc/iptables/setup-firewall.sh
# Pare-feu iptables complet - Serveur Linux 2026
# Testé sur Ubuntu 24.04 LTS (iptables 1.8.10-3ubuntu2) et Debian 12
# ---- VARIABLES À ADAPTER ----
SSH_PORT=22
SSH_ALLOWED_IP="" # Laisser vide pour tout autoriser, ex: "203.0.113.0/24"
WEB_SERVER=true # Mettre false si pas de serveur web
MAIL_SERVER=false # Mettre true si serveur mail
# ---- REMISE À ZÉRO ----
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
# ---- RÈGLES ESSENTIELLES ----
# Loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -s 127.0.0.0/8 ! -i lo -j DROP
# Paquets invalides (avant tout le reste)
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
# Connexions établies
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# ---- SSH ----
if [ -z "$SSH_ALLOWED_IP" ]; then
iptables -A INPUT -p tcp --dport $SSH_PORT -m conntrack --ctstate NEW -j ACCEPT
else
iptables -A INPUT -p tcp -s $SSH_ALLOWED_IP --dport $SSH_PORT \
-m conntrack --ctstate NEW -j ACCEPT
fi
# Anti-brute force SSH
iptables -A INPUT -p tcp --dport $SSH_PORT -m conntrack --ctstate NEW \
-m recent --set --name ssh_brute
iptables -A INPUT -p tcp --dport $SSH_PORT -m conntrack --ctstate NEW \
-m recent --update --seconds 60 --hitcount 5 --name ssh_brute -j DROP
# ---- DNS SORTANT ----
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
# ---- WEB ----
if [ "$WEB_SERVER" = true ]; then
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -p udp --dport 443 -m conntrack --ctstate NEW -j ACCEPT
fi
# ---- MAIL ----
if [ "$MAIL_SERVER" = true ]; then
iptables -A INPUT -p tcp -m multiport --dports 25,465,587,993,995 \
-m conntrack --ctstate NEW -j ACCEPT
fi
# ---- ICMP ----
iptables -A INPUT -p icmp --icmp-type echo-request \
-m limit --limit 1/s --limit-burst 5 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
iptables -A INPUT -p icmp -j DROP
# ---- JOURNALISATION ----
iptables -A INPUT -m limit --limit 5/min --limit-burst 10 \
-j LOG --log-prefix "IPT_INPUT_DROP: " --log-level 7
# ---- POLITIQUES PAR DÉFAUT ----
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
echo "=== Pare-feu configuré avec succès ==="
iptables -L -v -n
# ---- PERSISTANCE ----
iptables-save > /etc/iptables/rules.v4
echo "Règles sauvegardées dans /etc/iptables/rules.v4"
Conformité NIS2 et recommandations ANSSI pour le filtrage réseau
La directive NIS2, en vigueur dans l'Union Européenne depuis octobre 2024 et transposée progressivement en droit national, impose aux entités importantes et essentielles des mesures de sécurité réseau qui incluent le filtrage du trafic. Le Référentiel Cyber France (ReCyF), publié par l'ANSSI le 17 mars 2026, liste explicitement le cloisonnement réseau et le filtrage des flux parmi les 20 objectifs de sécurité à atteindre pour les organisations françaises.
Pour une conformité NIS2 via iptables, votre configuration doit couvrir au minimum ces points :
- Principe du moindre privilège : seuls les ports nécessaires au service sont ouverts, la politique par défaut est DROP
- Journalisation des rejets : tous les paquets rejetés sont loggués et conservés au minimum 12 mois selon le ReCyF
- Segmentation réseau : la chaîne FORWARD bloquée par défaut isole les segments de réseau
- Protection anti-brute force : rate limiting sur tous les services d'authentification (SSH, web, mail)
- Couverture IPv6 : ip6tables configuré en parallèle d'iptables pour éviter les contournements
Le CERT-FR publie régulièrement des alertes sur des vulnérabilités nécessitant des modifications urgentes des règles de filtrage réseau. Abonnez-vous à leurs flux d'alertes pour adapter vos règles iptables en réponse aux nouvelles menaces. Pour référence technique, la documentation de sécurité Ubuntu maintient à jour les versions des packages de filtrage et leurs interactions, et le Securing Debian Manual documente les bonnes pratiques de configuration sur Debian 12.
Couverture connexe
Articles liés
- Wireshark : analyser le trafic réseau en 12 étapes - Capturez et analysez le trafic bloqué par iptables pour valider votre configuration
- pfSense vs OPNsense : pare-feu réseau dédié - Comparatif des firewalls matériels si iptables ne suffit plus
- Let's Encrypt + Nginx : HTTPS en 12 étapes - Sécurisez le trafic web que votre iptables autorise
- TLS 1.3 vs TLS 1.2 : 40 % plus rapide, 5 CVE - Chiffrement de couche transport complémentaire au filtrage
- Clé SSH Linux : 12 Étapes, 30 Min - Sécurisez l'accès SSH que votre iptables protège
- Sécurité en ligne : protéger ses données et connexions - Vue d'ensemble de la sécurité serveur Linux
FAQ iptables Linux
iptables ou nftables en 2026 : que choisir ?
Sur Ubuntu 24.04 LTS, iptables utilise déjà nftables comme backend (version 1.8.10 avec mention "nf_tables"). Les deux coexistent. Choisissez iptables si vous avez des scripts existants ou si Docker est dans votre stack (iptables reste plus compatible nativement). Choisissez nftables pour les nouveaux déploiements sans Docker, car sa syntaxe unifiée IPv4/IPv6 simplifie la gestion à long terme.
Comment vider toutes les règles iptables d'urgence ?
Exécutez les 4 commandes dans cet ordre exact : iptables -P INPUT ACCEPT, iptables -P FORWARD ACCEPT, iptables -P OUTPUT ACCEPT, puis iptables -F. Cette séquence remet les politiques en ACCEPT avant de vider les règles. L'inverse (vider d'abord) peut couper votre accès si la politique est déjà DROP.
iptables bloque-t-il le trafic IPv6 ?
Non. iptables ne gère que IPv4. Pour IPv6, utilisez ip6tables avec les mêmes paramètres. Les fichiers de persistance sont distincts : /etc/iptables/rules.v4 pour IPv4 et /etc/iptables/rules.v6 pour IPv6. Vérifiez votre exposition IPv6 avec curl -6 ifconfig.io.
Pourquoi Docker ignore-t-il mes règles iptables ?
Docker ajoute ses propres règles dans les chaînes DOCKER et DOCKER-ISOLATION des tables nat et filter. Ces règles sont évaluées avant vos règles personnalisées dans INPUT pour les ports mappés. La solution officielle : utiliser la chaîne DOCKER-USER pour vos restrictions, ou binder les conteneurs sur 127.0.0.1 pour les services non destinés à l'extérieur.
Quelle est la différence entre DROP et REJECT ?
DROP rejette le paquet silencieusement. L'expéditeur ne reçoit aucune réponse et doit attendre le timeout. REJECT envoie un message d'erreur TCP RST ou ICMP "port unreachable", confirmant à un attaquant que le port est filtré et que le serveur existe. Pour la politique par défaut, utilisez DROP. Pour des services internes où vous voulez que les clients sachent qu'ils n'ont pas accès, REJECT peut être préférable.
Comment tester mes règles sans risquer de me bloquer ?
Utilisez la commande at pour programmer une remise à zéro automatique : avant d'appliquer vos règles restrictives, planifiez echo "iptables -P INPUT ACCEPT; iptables -F" | sudo at now + 5 minutes. Si votre configuration vous bloque, les règles seront automatiquement remises à zéro 5 minutes plus tard. Annulez le job avec atrm une fois vos règles validées.
iptables est-il compatible avec Kubernetes ?
Kubernetes utilise kube-proxy qui crée ses propres règles iptables (ou ipvs). Sur un noeud Kubernetes, ne gérez pas manuellement iptables : laissez kube-proxy gérer les règles des services. Vous pouvez ajouter des règles pour le trafic entrant vers le noeud lui-même, mais évitez de modifier les chaînes KUBE-* créées automatiquement.
Comment auditer les règles iptables d'un serveur en production ?
Exécutez iptables -L -v -n --line-numbers pour lister les règles avec compteurs de paquets. Les règles avec un compteur élevé sont celles qui traitent le plus de trafic. Exportez avec iptables-save et comparez avec votre configuration de référence. Pour un audit complet, vérifiez aussi ip6tables -L -v -n et iptables -t nat -L -v -n pour les règles NAT de Docker.
Références officielles : Netfilter.org (projet officiel iptables/nftables), Documentation Ubuntu Security, Securing Debian Manual.




