{{tag>pare-feu sécurité réseau}}
{{ :icons:ufw.png?100|Icône iptables}}
====== iptables ======
FIXME: Depuis une Ubuntu 23.10, le package [[apt>iptables]] semble être maintenu, voir : https://changelogs.ubuntu.com/changelogs/pool/main/i/iptables/iptables_1.8.9-2ubuntu2/changelog -- [[utilisateurs:BeAvEr]], en date du : ✨✨ **////__(14/09/2023)__** ✨✨
----
**[[wpfr>iptables]]** est une interface en ligne de commande permettant de configurer Netfilter. En plus de **iptables**, depuis la version 8.04, Ubuntu est installé avec la surcouche [[:UFW]] qui permet de contrôler simplement [[wpfr>Netfilter]], [[:UFW]] est toutefois moins complet que **iptables**.
Cette documentation est une introduction à **iptables**, elle est destinée à ceux qui souhaitent mettre en place un [[:pare-feu]] et/ou un partage de connexion, sur une machine Linux, sans passer par une interface graphique. Seule la table par défaut (//Filte//r) d'iptables est présentée ici et seules les chaînes utilisées par //Filter// (//Input//, //Forward// et //Output//) y sont exposées.
Les lecteurs désirant approfondir leur recherche et aborder l'utilisation des autres tables (Nat, Mangle, Row et Security) ainsi que des chaînes non utilisables par Filter (Prerouting et Postrouting) se tourneront vers les nombreuses documentations disponibles sur l'Internet. Ceux désirant configurer un [[:pare-feu]] par l'intermédiaire d'une interface graphique se tourneront vers Gufw ou encore vers Shorewall pour une utilisation sur serveur.
**iptables** existe aussi pour l'IPv6, pour cela il suffit d'utiliser la commande ''ip6tables'' au lieu de ''iptables''.
Pour une bonne compréhension d'**iptables** (et des pare-feux en général) il est conseillé d'avoir des notions en réseaux informatiques, au minima connaître le principe de fonctionnement des protocoles [[wpfr>Transmission_Control_Protocol|TCP]] et [[wpfr>User_Datagram_Protocol|UDP]].
===== Configuration du pare-feu =====
Nous allons configurer notre [[:pare-feu]] de la manière suivante :
* On bloque tout le trafic entrant par défaut.
* On autorise au cas par cas : le trafic appartenant ou lié à des connexions déjà établies et le trafic à destination des serveurs (web, ssh, etc.) que nous souhaitons mettre à disposition.
Afin de ne pas avoir de problème au moment où on crée ces règles, nous allons d'abord créer les autorisations, puis nous enverrons le reste en enfer.
En tapant « ''sudo iptables -L'' », une liste de vos règles actuelles est affichée. Si vous (ou un logiciel) n'avez encore jamais touché à **iptables**, les chaînes sont vides, et vous devriez voir :
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Pour l'instant, tout passe dans toutes les directions (//policy ACCEPT//).
Pour cette configuration basique, seul le trafic entrant (chaine //input//) nous intéresse.
Par défaut, « ''sudo iptables -L'' » n'affiche que la table "filter". Pour consulter les autres tables, vous devez ajouter l'option -t suivie de "nat", "mangle" ou "raw". Pour la configuration d'un [[:pare-feu]] la table "filter" est toutefois la seule nécessaire.
ATTENTION, si vous avez modifié la règle par défaut pour le blocage (''iptables -P INPUT DROP'' voir plus bas) et que vous entrez ''iptables -F'' vous bloquerez tous les accès... y compris celui en cours. Ceci est particulièrement problématique sur une machine sur laquelle vous accédez à distance (serveur etc.).
Si vous avez déjà modifié la configuration et que vous voulez la réinitialiser, tapez :
sudo iptables -F
sudo iptables -X
=== Autoriser le trafic entrant d'une connexion déjà établie ===
Pour permettre à une connexion déjà ouverte de recevoir du trafic :
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
Cette commande ajoute une règle (''-A'') à la chaîne contrôlant le trafic entrant //INPUT//, pour autoriser le trafic (''-j ACCEPT''), aprés vérification que l'état de la connexion est établie (''-m conntrack --ctstate ESTABLISHED'').
Une ancienne configuration avec l'état "--state RELATED" est toujours sur internet, or cette option peut permettre l'ouverture de port non désirée sur votre machine par un attaquant. L'option "RELATED" est à utiliser avec prudence. Pour plus d'information :
https://gist.github.com/azlux/6a70bd38bb7c525ab26efe7e3a7ea8ac
=== Permettre le trafic entrant sur un port spécifique ===
Pour permettre le trafic entrant sur le port 22 (traditionnellement utilisé par [[:SSH]], vous devrez indiquer à **iptables** tout le trafic TCP sur le port 22 de votre adaptateur réseau.
sudo iptables -A INPUT -p tcp -i eth0 --dport ssh -j ACCEPT
Cette commande ajoute une règle (''-A'') à la chaîne contrôlant le trafic entrant //INPUT//, pour autoriser le trafic (''-j ACCEPT''), vers l'interface (''-i'') //eth0// et à destination du port (''--dport'') //SSH// (on aurait pu mettre 22).
Maintenant vous pouvez vérifier vos règles iptables :
sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere ctstate ESTABLISHED
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
Maintenant, acceptons tout le trafic web (''www'') entrant :
sudo iptables -A INPUT -p tcp -i eth0 --dport 80 -j ACCEPT
En regardant nos règles, nous avons :
sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere ctstate ESTABLISHED
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
ACCEPT tcp -- anywhere anywhere tcp dpt:www
Nous avons exceptionnellement autorisé le trafic tcp pour ssh et les ports web, mais comme nous n'avons rien bloqué, tout le trafic passe quand même.
=== Bloquer le trafic ===
Maintenant que nous avons fini avec les autorisations, il faut maintenant bloquer le reste.
Nous allons en fait modifier la « politique par défaut » (//policy//) de la chaîne //INPUT// : cette décision (//DROP//) s'applique lorsque aucune règle n'a été appliquée à un paquet. Donc, si la tentative de connexion n'est permise par aucune des règles précédentes, elle sera rejetée.
warning : a ne pas utiliser sur un serveur distant !
sudo iptables -P INPUT DROP #warning : a ne pas utiliser sur un serveur distant !
sudo iptables -L
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- anywhere anywhere ctstate ESTABLISHED
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
ACCEPT tcp -- anywhere anywhere tcp dpt:www
== Autre méthode, par exemple pour les server ==
**Un autre moyen de procéder** est l'ajout en fin de chaîne d'une règle supprimant les paquets (les paquets autorisés par les règles précédentes n'atteindraient pas celle-ci), //via// ''iptables -A INPUT -j DROP'', mais il faudrait alors faire attention à la position des futures règles.
=== Autoriser le trafic local ===
Un petit problème de notre configuration est que même l'interface locale //(loopback)// est bloquée.
Nous pourrions avoir écrit les règles de rejet seulement pour //eth0// en spécifiant ''-i eth0'', mais nous pouvons aussi ajouter une règle pour //loopback//. Par exemple, nous pourrions l'insérer en 2e position :
sudo iptables -I INPUT 2 -i lo -j ACCEPT
Pour lister les règles plus en détail.
sudo iptables -L -v -n
=== Autoriser les requêtes ICMP (ping) ===
Il peut-être utile de valider les réponses aux requêtes "ping", ne serait-ce que pour s'assurer que le poste est toujours en activité.
# On autorise le PC a faire des pings sur des IP externes et à répondre aux requêtes "ping"
sudo iptables -A OUTPUT -p icmp -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
# Si vous utilisez une ancienne version de iptables la commande ci-dessus peut ne pas fonctionner, dans ce cas entrez la commande suivante :
sudo iptables -A OUTPUT -p icmp -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
# On autorise les pings
sudo iptables -A INPUT -p icmp -j ACCEPT
=== Supprimer une règle ===
Si vous vous êtes trompé dans la création d'une règle et que cela vous bloque une connexion, vous pouvez supprimer une seule entrée plutôt que de tout réinitialiser.
Tout d'abord vous listez l'ensemble de vos règles avec l'affichage des lignes :
sudo iptables -L --line-numbers
Ce qui personnellement me retourne :
Chain INPUT (policy DROP)
num target prot opt source destination
1 DROP icmp -- anywhere anywhere
2 ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
3 ACCEPT tcp -- anywhere anywhere tcp dpt:www
4 ACCEPT tcp -- anywhere anywhere tcp dpt:webmin
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT tcp -- anywhere anywhere tcp spt:www
2 ACCEPT tcp -- anywhere anywhere tcp spt:12345
Je souhaite supprimer la ligne 2 de la chaîne OUTPUT
Syntaxe : iptables -D chaîne numéro_de_ligne
sudo iptables -D OUTPUT 2
=== Sauvegarder vos règles ===
Passer en mode superutilisateur
sudo -s iptables-save -c
===== Appliquer les règles au démarrage =====
==== Via iptables-persistent ====
Vous avez testé vos règles, ça marche au poil, alors il reste à les appliquer au démarrage.
iptables-persistent propose de sauvegarder les règles dans le répertoire ''/etc/iptables'', fichier ''rules.v4'' pour les règles IPv4 et ''rules.v6'' pour les règles IPv6. Le script peut s’appeler via :
sudo iptables-save
Il prend les arguments : ''save'' pour sauvegarder les règles, ''flush'' pour vider toutes les règles et ''reload'' pour les recharger depuis les fichiers précités.
==== Via un fichier ====
Depuis l'utilisation du daemon **systemd-networkd**, il n'est plus possible de lancer votre script iptables via l'emplacement ''/etc/network/if-pre-up.d/'' de votre Ubuntu. Pour vérifier si vous êtes concerné par cette note, veuillez ouvrir un [[:terminal]], avec pour contenu **pidof systemd-networkd**, si vous avez un retour, merci de vous référer au chapitre **3.2.1**.
Commencez par éditer un fichier en root, que vous enregistrerez sous ''/etc/network/if-pre-up.d/''.
La première ligne de ce fichier doit être :
#!/bin/bash
Cette ligne indique que le fichier doit être interprété par l'exécutable /bin/bash (c'est donc un [[:tutoriel:script_shell|script bash]]).
Ajoutez ensuite à votre script ceci :
iptables-restore < /etc/iptables.test.rules
Le reste du fichier doit contenir les commandes **iptables** que vous avez générées.
Déplacez le script iptables dans /etc/network/if-pre-up.d/ :
sudo mv /emplacement/du/script/iptables /etc/network/if-pre-up.d/
Rendez ce script exécutable :
sudo chmod +x /etc/network/if-pre-up.d/iptables
Cela devrait être bon. Au prochain redémarrage, vous pouvez vérifier que vos règles sont bien utilisées, en effectuant :
sudo iptables -L
=== Lancer votre script iptables au démarrage via Systemd ===
Pour lancer votre script iptables au démarrage de votre Ubuntu, merci d'ouvrir un [[:terminal]], avec pour contenu :
sudo touch /lib/systemd/system/firewall.service
Veuillez éditer ensuite le fichier se trouvant dans **/lib/systemd/system/firewall.service**, avec votre [[:éditeur de texte]] favoris, et y coller :
[Unit]
Description=Firewall
Requires=network-online.target
After=network-online.target
[Service]
User=root
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/iptables.sh start
ExecStop=/usr/local/sbin/iptables.sh stop
[Install]
WantedBy=multi-user.target
Il ne vous reste plus qu'à activer le service **firewall.service**, au démarrage de votre Ubuntu, via la commande :
sudo systemctl enable firewall.service
Au prochain redémarrage de votre Ubuntu, votre service **firewall.service** chargera votre script iptables se trouvant dans **/etc/init.d/**.
Pour vérifier le statut de votre service **firewall.service**, veuillez saisir dans un [[:terminal]] :
systemctl status firewall
===== Script iptables =====
Ce script est un exemple, il est à adapter à vos besoins. Il peut toutefois être utilisé pour une utilisation courante, il offre une plutôt bonne "protection" pour un usage desktop.
#!/bin/bash
## Script iptables by BeAvEr.
## Règles iptables.
## On flush iptables.
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
## On drop tout le trafic entrant.
iptables -P INPUT DROP
## On drop tout le trafic sortant.
iptables -P OUTPUT DROP
## On drop le forward.
iptables -P FORWARD DROP
## On drop les requêtes ICMP.
## Votre machine ne répondra plus aux requêtes ping sur votre réseau local.
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
# Autorise les messages ICMP "Destination Unreachable" (type 3)
# Nécessaire pour recevoir les erreurs liées à nos propres connexions
# sortantes (ex: PMTUD - découverte du MTU du chemin), sans quoi les
# connexions TCP/UDP peuvent se bloquer silencieusement (ex: HTTPS/QUIC).
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
# Autorise les messages ICMP "Time Exceeded" (type 11)
# Utilisé notamment par traceroute et signalé quand un paquet expire
# en transit (TTL=0) ; utile pour le diagnostic réseau et pour éviter
# que des erreurs de routage légitimes soient bloquées.
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
## On accepte le Multicast (mDNS/Bonjour, découverte imprimante, Chromecast...).
iptables -A INPUT -m pkttype --pkt-type multicast -j ACCEPT
## DHCP client : indispensable pour obtenir/renouveler une IP en DHCP.
## sudo ss -tulnpa |grep :68
## -> udp ESTAB 0 0 192.168.1.37%wlp3s0:68
## -> 192.168.1.254:67 users:(("NetworkManager",pid=904,fd=26)).
iptables -A INPUT -p udp --sport 67 --dport 68 -j ACCEPT
## Rejette les paquets dans un état de connexion invalide (INVALID).
# Il s'agit généralement de paquets malformés, incohérents, hors contexte
# ou ne correspondant à aucune connexion suivie par conntrack. Cette règle
# permet d'écarter rapidement une partie du trafic anormal ou suspect.
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
## Dropper silencieusement tous les paquets broadcastés.
iptables -A INPUT -m pkttype --pkt-type broadcast -j DROP
## Permettre à une connexion ouverte de recevoir du trafic en entrée.
iptables -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
## Permettre à une connexion ouverte de recevoir du trafic en sortie.
iptables -A OUTPUT -m conntrack ! --ctstate INVALID -j ACCEPT
## On accepte la boucle locale en entrée.
iptables -I INPUT -i lo -j ACCEPT
## On log les paquets en entrée.
iptables -A INPUT -j LOG
## On log les paquets forward.
iptables -A FORWARD -j LOG
exit 0
===== Voir aussi =====
==== Documentations supplémentaires ====
En anglais :
* [[https://www.netfilter.org/documentation/HOWTO/packet-filtering-HOWTO.html| How To Iptables]]
* [[https://www.netfilter.org/documentation/|Documentation Multilingue de Netfilter et Iptables]]
* [[https://people.netfilter.org/rusty/unreliable-guides/| Rusty's Remarkably Unreliable Guides]]
En Français :
* [[http://olivieraj.free.fr/fr/linux/information/firewall/ |Bible française pour apprendre les bases de la sécurité et d'Iptables sous Linux]]
* [[http://irp.nain-t.net/doku.php |Bible française d'introduction aux réseaux et à Internet]] ou [[ http://stielec.ac-aix-marseille.fr/electron/cours.htm |ici]] (même auteur et contenu trés proche)
* [[https://memoire-grise-liberee.fr.eu.org|"Mémoire Grise Libérée" : IpTables HowTo]]
* [[http://www.inetdoc.net/guides/iptables-tutorial/|iptables-tutorial de Oskar Andreasson traducteur Marc Blanc et publié par Philippe Latu]]
* [[https://www.it-connect.fr/supprimer-une-regle-precise-dans-iptables/|Supprimer une règle précise sous Iptables]] sur IT-Connect.fr
* [[https://wiki.visionduweb.fr/index.php?title=Configurer_le_pare-feu_Iptables|Quelques notes avec des exemples ainsi que des liens valides vers des tutoriels pour utiliser Iptables]] depuis le wiki de Visionduweb.
==== Sources ====
* Basé sur [[https://wiki.ubuntu.com/IptablesHowTo]]
* Merci à Rusty Russell et son //How-To//, il est la base de cette page.
* Et merci surtout pour son travail au sein de l'équipe de développement de Netfilter. :-)
----
//[[:Contributeurs]] : [[:utilisateurs:Kmeleon]], [[:utilisateurs:eks]], [[:utilisateurs:BeAvEr]] (création du script iptables et modification majeure de la documentation), [[:utilisateurs:maverick62]], [[:utilisateurs:mydjey]] (mise à jour et refonte).//