TP sur le filtrage avec iptables
Objectifs Mettre en oeuvre un ensemble de règles de filtrage sous iptables Comprendre la syntaxe iptables Organiser l’ordre des règles
Réalisation du script Mettre la politique de filtrage à DROP pour toute la table filter iptables -t filter -P INPUT DROP -t filter -P INPUT DROP iptables -t filter -P OUTPUT DROP Ici, on ne crée pas une simple règle, mais on ajoute une “politique” par défaut pour la chaîne INPUT (INPUT= le trafic à destination du firewall) En réalité, cela revient à ajouter une règle qui DROP tous les paquets après toutes les autres règles. iptables -t filter -P FORWARD DROP On indique que la règle sera ajoutée dans la table filter, mais on peut l'omettre étant donné que la table filter est choisie par défaut Et on fait pareil pour les chaines OUTPUT et FORWARD
Réalisation du script (2) Autoriser tous les flux en sortie de votre machine Deux façons de faire: 1- iptables -t filter -P OUTPUT ACCEPT = On change la politique par défaut pour OUTPUT Ou 2- iptables -A OUTPUT -j ACCEPT = On laisse tous les flux sortir en OUTPUT Exercice: Y a-t-il une différence entre les deux ? et si oui laquelle ?
MAIS !!!!! Il faut aussi accepter les paquets de réponse à nos requêtes, sinon les connexions ne pourront pas être établies -m state --state ESTABLISHED,RELATED iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT On accepte en INPUT les paquets appartenant à une connexion établie (ceux qui ont été autorisés en OUTPUT)
Réalisation du script (3) Autoriser les flux web et DNS vers votre machine iptables -A INPUT -m state --state NEW -p tcp -- dport 80 iptables -A INPUT -m state --state NEW -p tcp --dport 80 --syn -j ACCEPT --syn iptables -A INPUT -m state --state NEW -p udp -- dport 53 -j ACCEPT On fait pareil pour le DNS, sans le --syn étant donné qu’il n’y a pas de flags en UDP On vérifie aussi que seul le flag SYN est positionné (pour éviter les scans bizarres) On autorise les flux entrants pour les nouvelles connexions tcp sur le port 80
Réalisation du script (4) Créer une chaine qui log et qui drop les paquets iptables -N log_n_drop iptables -A log_n_drop -j LOG --log-prefix '[paquet rejeté] : ' iptables -A log_n_drop -j DROP On créé la chaîne log_n_drop Et on y créé deux règles, une pour logger et une pour filtrer
ATTENTION !!! Cette nouvelle chaîne créée ne sert a rien tant qu’elle n’est pas appelée depuis une autre règle avec l’action “-j log_n_drop” Pour l’instant la chaîne est créée mais pas utilisée. Comme si vous créiez une fonction en C mais que vous ne l’appeliez jamais.
Réalisation du script (5) Au lieu de droper dans le script, appelez la chaîne log_n_drop Nous n’avons aucune règle de DROP pour l’instant vu que nous dropons avec la politique par défaut. Si nous avions des règles finissant par “-j DROP” nous pourrions les remplacer par “-j log_n_drop”
Réalisation du script (6) Créer une chaîne qui interdit l’usage des adresses RFC 1918 et qui log iptables -N RFC iptables -A RFC -s 10.0.0.0/8 -j log_n_drop iptables -A RFC -s 192.168.0.0/16 -j log_n_drop iptables -A RFC -s 172.16.0.0/12 -j log_n_drop On créé la chaîne Et les règles pour chaque plage d’adresse
ATTENTION !!! Comme pour log_n_drop, cette nouvelle chaîne créée ne sert a rien tant qu’elle n’est pas appelée depuis une autre règle avec l’action “-j RFC” Pour l’instant la chaîne est créée mais pas utilisée.
Réalisation du script (6) Créer une règle qui redirige dans la chaine RFC si le paquet vient sur l’interface externe. iptables -A INPUT -i eth0 -j RFC Ainsi tout paquet venant de l’extérieur (interface eth0) avec une adresse anormale pour Internet (RFC1918) se verra rejeté.
Réalisation du script (7) Faire une règle qui nat toutes les requêtes venant de l’interne -j MASQUERADE iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE -t nat -A POSTROUTING On spécifie que l’on veut écrire dans la table nat, et non plus filter On veut nater sur l’interface externe, donc après le routage. On met en place de la nat dynamique avec la cible MASQUERADE qui transforme automatiquement l’adresse source du paquet en l’adresse de l’interface externe eth0.
Script complet #!/bin/bash iptables -X iptables -F iptables -N log_n_drop iptables -A log_n_drop -j LOG --log-prefix '[paquet rejeté] : ' iptables -A log_n_drop -j DROP iptables -N RFC iptables -A RFC -s 10.0.0.0/8 -j log_n_drop iptables -A RFC -s 192.168.0.0/16 -j log_n_drop iptables -A RFC -s 172.16.0.0/12 -j log_n_drop iptables -t filter -P INPUT DROP iptables -t filter -P OUTPUT ACCEPT iptables -t filter -P FORWARD DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -i eth0 -j RFC iptables -A INPUT -m state --state NEW -p tcp --dport 80 --syn -j ACCEPT iptables -A INPUT -m state --state NEW -p udp --dport 53 -j ACCEPT iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
L’ordre des règles ? L’ordre des règles est-il important ? Oui, extrêmement. Pour deux raisons: 1- Etant donné que les règles sont parcourues une à une dans l’ordre d’écriture, il est important de vérifier qu’une règle ne “surpasse” pas une autre, par exemple 2- Vu que les règles sont passées en revue une à une dans l’ordre et qu’on s’arrête dès qu’une règle correspond, il est important de mettre en premier les règles les plus utilisées, comme ESTABLISHED et RELATED qui concerneront la majorité des paquets. iptables -A INPUT -p tcp -j ACCEPT iptables -A INPUT -p tcp --dport 80 -j DROP Ici la seconde règle ne sera jamais utilisée car la première correspondra à tout le traffic TCP et donc notamment au port 80 TCP.