Encore une fois, il n'est pas question de reprendre toute la documentation d'IPtables. Nous allons simplement examiner quelques règles simples d'un usage courant. Pour étudier la syntaxe, consultez:
Les pages de man, bien que pas toujours très agréables à lire, sont essentielles, pour la simple raison que Netfilter/IPtables sont des outils en pleine évolution et que d'une version à l'autre, de nouvelles fonctionnalités peuvent apparaître.
Pour ce qui suit, nous allons faire de la pratique. Debian Etch montée en passerelle, tel que décrit dans le chapitre « Partage de connexion ».
Rappelons-le, il s'agit de masquer tous les clients d'un réseau privé (par exemple 192.168.0.0) derrière l'unique adresse officielle attribuée par le fournisseur d'accès, et d'assurer un minimum de sécurité sur la totalité de l'installation.
Pour commencer, nous allons tout fermer au niveau de la passerelle dans la table filter
.
Nous vidons les chaînes :
iptables -F
Nous supprimons d'éventuelles chaînes personnelles :
iptables -X
Nous les faisons pointer par défaut sur DROP
iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP
Nous faisons de même avec toutes les autres tables, à savoir nat
et mangle
, mais en les faisant pointer par défaut sur ACCEPT. Ca ne pose pas de problèmes puisque tout est bloqué au niveau filter
:
iptables -t nat -F iptables -t nat -X iptables -t nat -P PREROUTING ACCEPT iptables -t nat -P POSTROUTING ACCEPT iptables -t nat -P OUTPUT ACCEPT iptables -t mangle -F iptables -t mangle -X iptables -t mangle -P PREROUTING ACCEPT iptables -t mangle -P INPUT ACCEPT iptables -t mangle -P OUTPUT ACCEPT iptables -t mangle -P FORWARD ACCEPT iptables -t mangle -P POSTROUTING ACCEPT
Notez que dans tout ça, on n'a pas changé grand chose par rapport à l'état de ces tables tel qu'on le trouve après un boot de la machine, sans modifications particulières des scripts de démarrage, hormis la cible par défaut des règles de la table filter
que l'on a passé à DROP. Tout de même, cette manipulation préliminaire a eu pour conséquences :
Normalement, plus rien ne doit passer nulle part. Essayez des pings dans tous les sens, entre la passerelle et votre réseau privé ou vers le Net, entre un poste de votre réseau privé et la passerelle, rien ne devrait passer.
Nous considérons que la machine elle même est sûre et que les processus locaux peuvent communiquer entre eux via l'interface locale :
iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT
Nous considérons que notre réseau local est également sûr (ce qui n'est pas forcément vrai, d'ailleurs).
iptables -A INPUT -i eth0 -j ACCEPT iptables -A OUTPUT -o eth0 -j ACCEPT
A ce stade, nous avons la situation suivante :
Mais…
Translation d'adresses pour tout ce qui traverse la passerelle en sortant par ppp0
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
Nous pourrions ici restreindre le NAT à une plage d'IPs du réseau local :
iptables -t nat -A POSTROUTING -s 192.168.0.0/255.255.255.0 -o ppp0 -j MASQUERADE
Ou même à une liste d'IP bien définies :
iptables -t nat -A POSTROUTING -s 192.168.0.10 -o ppp0 -j MASQUERADE iptables -t nat -A POSTROUTING -s 192.168.0.11 -o ppp0 -j MASQUERADE
Ceci peut être utile, surtout en sachant que vous pouvez détruire une règle et une seule :
iptables -t nat -D POSTROUTING -s 192.168.0.11 -o ppp0 -j MASQUERADE
Ainsi, si vous avez, par exemple, des enfants qui usent de votre connexion permanente de façon un peu trop permanente, vous pourrez aisément, avec l'aide du démon cron
n'accorder l'accès au Net que pour certaines plages horaires.
Mais ça ne suffit pas encore pour fonctionner, les pings depuis le réseau local vers le Net ne passent toujours pas. Normal, FORWARD fait toujours DROP sur tout ce qui passe. Nous devons accorder des autorisations de passage sur FORWARD.
Le suivi de connexion est intéressant, bien qu'il consomme un peu plus de ressources sur votre passerelle. Nous l'avons vu, son avantage est qu'il permet d'obtenir des informations sur toute connexion en cours. Ces informations sont principalement :
En français, nous allons faire :
En langage iptables : Toutes les connexions qui sortent du LAN vers le Net sont acceptées
iptables -A FORWARD -i eth0 -o ppp0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
Nous aurions aussi bien pu écrire :
iptables -A FORWARD -i eth0 -o ppp0 -m state ! --state INVALID -j ACCEPT
Seules les connexions déjà établies ou en relation avec des connexions établies sont acceptées venant du Net vers le LAN
iptables -A FORWARD -i ppp0 -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
irp.nain-t.net
(par exemple) se met à fonctionner.
Maintenant que nous avons mis conntrack en œuvre, nous aimerions bien voir un peu comment il opère… Il se trouve qu'il est possible d'observer la table de suivi de connexions qui se présente sous la forme d'un fichier virtuel en /proc/net/ip_conntrack.
Pour interpréter plus facilement ce qu'il suit, il faut savoir plusieurs choses :
tcp 6 14 CLOSE_WAIT src=192.168.0.10 dst=213.186.35.33 sport=1102 dport=80 src=213.186.35.33 dst=80.8.130.97 sport=80 dport=1102 [ASSURED] use=1 tcp 6 431991 ESTABLISHED src=192.168.0.10 dst=213.186.35.33 sport=1103 dport=80 src=213.186.35.33 dst=80.8.130.97 sport=80 dport=1103 [ASSURED] use=1 tcp 6 73 TIME_WAIT src=192.168.0.10 dst=213.186.35.33 sport=1104 dport=80 src=213.186.35.33 dst=80.8.130.97 sport=80 dport=1104 [ASSURED] use=1 tcp 6 82 SYN_SENT src=192.168.0.10 dst=213.186.35.33 sport=1105 dport=80 [UNREPLIED] src=213.186.35.33 dst=80.8.130.97 sport=80 dport=1105 use=1 tcp 6 51 CLOSE_WAIT src=192.168.0.10 dst=213.186.35.33 sport=1106 dport=80 src=213.186.35.33 dst=80.8.130.97 sport=80 dport=1106 [ASSURED] use=1
Le troisième champ est un « timer », l'entrée est effacée de la table lorsque le timer tombe à zéro. Bien entendu, cette table est en mémoire, ce n'est pas un vrai fichier, son contenu évolue donc perpétuellement au cours du temps.
tail
;Si vous installez sur votre passerelle un serveur DNS, il faudra qu'il puisse envoyer ses requêtes sur le Net, ce qui n'est actuellement pas possible. Il faut ouvrir une voie en UDP conforme aux besoins d'une requête DNS :
En langage IPtables :
Autorisation des requêtes DNS locales
iptables -A OUTPUT -o ppp0 -p udp --sport 1024: --dport 53 -m state --state ! INVALID -j ACCEPT iptables -A INPUT -i ppp0 -p udp --sport 53 --dport 1024: -m state --state RELATED,ESTABLISHED -j ACCEPT
Voilà des syntaxes qui commencent à être sympathiques…
Lorsque l'on veut définir, non pas un port mais une plage de ports, les écritures suivantes sont autorisées :
–dport 1024:1999
autorisera la plage de ports [1024,1999] en destination (ça marche aussi avec –sport
) ;–dport 1024:
veut dire que tous les ports supérieurs où égaux à 1024 seront acceptés en destination.Vous pouvez désirer implanter un SMTP sur votre passerelle, pour envoyer votre courrier depuis le LAN sans vous préoccuper des disponibilités ou des lenteurs du SMTP de votre FAI. Voir le chapitre SMTP à ce sujet.
Deux options sont possibles :
La première option est la plus rapide. Malheureusement, à cause de nombreux débordements, la tendance actuelle consiste à refuser les messages provenant de serveurs SMTP non officiels, ce fut un temps par exemple le cas entre Wanadoo et AOL. AOL refusait tout message en provenance de wanadoo.fr autre que ceux qui lui arrivent des SMTP officiels de wanadoo. Comme il est clair que cette tendance n'ira qu'en s'accentuant, il demeure plus sage d'utiliser la seconde méthode. Vous serez tributaire du bon fonctionnement du SMTP de votre FAI, mais ça ne se verra pas au niveau de vos clients du LAN. Ce sera votre SMTP local qui assurera les éventuelles attentes.
Sachant qu'un serveur SMTP écoute sur le port 25 et utilise tcp :
Autorisation des envois SMTP locaux
iptables -A OUTPUT -o ppp0 -p tcp --sport 1024: --dport 25 -m state --state ! INVALID -j ACCEPT iptables -A INPUT -i ppp0 -p tcp --sport 25 --dport 1024: -m state --state RELATED,ESTABLISHED -j ACCEPT
Et vous pouvez même restreindre encore d'avantage, si vous avez adopté la seconde stratégie d'envoi :
Autorisation des envois SMTP locaux vers le SMTP du FAI
iptables -A OUTPUT -o ppp0 -p tcp --sport 1024: -d smtp.wanadoo.fr --dport 25 -m state --state ! INVALID -j ACCEPT iptables -A INPUT -i ppp0 -p tcp -s smtp.wanadoo.fr --sport 25 --dport 1024: -m state --state RELATED,ESTABLISHED -j ACCEPT
Si, si, ça fonctionne, à condition bien entendu que votre passerelle soit en mesure de résoudre les noms au moment où vous écrivez la règle. Attention donc, si vous faites tout ça lors de l'initialisation de la machine, il faudra que :
Vous pouvez, plus simplement, indiquer non pas le nom du serveur mais son IP.
Vous pouvez souhaiter pouvoir accéder à votre passerelle depuis le Net, pour peu que vous ayez un moyen de connaître à tout moment son adresse IP. Sachant que ssh utilise tcp sur le port 22 :
iptables -A INPUT -p tcp --dport ssh -i ppp0 -j ACCEPT iptables -A OUTPUT -p tcp --sport ssh -o ppp0 -j ACCEPT
Nous pouvons effectivement définir un port par le service qui lui est normalement associé (ici ssh).
Si vous devez accéder à votre passerelle depuis une IP fixe sur le Net, vous pouvez largement restreindre cette règle en n'acceptant les connexions ssh que depuis et vers cette IP.
Le protocole ICMP, même s'il présente quelques dangers, rend tout de même quelques services appréciables, dans le cas d'erreurs de transmission et aussi dans la découverte du MTU. Pour plus de détails, voyez le chapitre « TCP/IP(v4) ».
Il se trouve que, pour les messages d'erreur ICMP, l'en-tête du paquet qui a généré l'erreur est reproduite dans le message. Le suivi de connexion ICMP s'en sert pour déclarer ce paquet RELATED
.
En ce qui concerne les clients du LAN, avec les règles que nous avons écrites, il ne devrait pas y avoir de problèmes, puis qu'on laisse passer tout paquet RELATED
sans distinction de protocole.
En revanche, pour la passerelle elle-même, si l'on a activé SMTP et DNS, il peut s'avérer intéressant d'ajouter la ligne :
iptables -A INPUT -p icmp -m state --state RELATED -j ACCEPT
De cette manière, une erreur ICMP passera, mais votre passerelle ne répondra pas aux pings, ni à aucune autre interrogation ICMP.
Vous pouvez faire quelque chose de très simple, mais qui reste tout de même moins sûr. Nous sommes dans la table Filter
(table par défaut).
Vidage des chaînes
iptables -F
Destruction des éventuelles chaînes personnelles :
iptables -X
Changement de stratégie par défaut: Nous n'acceptons plus rien
Mais nous acceptons tout ce qui sort (localement) de la passerelle :
iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT
Initialisation des tables NAT
et MANGLE
:
iptables -t nat -F iptables -t nat -X iptables -t nat -P PREROUTING ACCEPT iptables -t nat -P POSTROUTING ACCEPT iptables -t nat -P OUTPUT ACCEPT iptables -t mangle -F iptables -t mangle -X iptables -t mangle -P PREROUTING ACCEPT iptables -t mangle -P OUTPUT ACCEPT
Mise en place du NAT :
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o ppp0 -j MASQUERADE
Maintenant, nous allons créer une chaîne particulière, que nous allons appeler SuiviConnexions
et qui va gérer ce suivi :
iptables -N SuiviConnexions
Filtrage de suivi dans cette chaîne : Seules les nouvelles connexions qui ne viennent pas du Net sont acceptées :
iptables -A SuiviConnexions -m state --state NEW -i ! ppp0 -j ACCEPT
Ceci veut dire plus clairement que toutes les connexions qui n'entrent pas par ppp0 c'est à dire dans notre cas, qui entrent par eth0, mais aussi par l'interface locale (lo).
Toutes les connexions établies et relatives sont acceptées :
iptables -A SuiviConnexions -m state --state ESTABLISHED,RELATED -j ACCEPT
Cette chaîne va maintenant servir de cible commune pour les deux chaînes standard INPUT et FORWARD, les deux chaînes INPUT et FORWARD vont pointer sur SuiviConnexions :
iptables -A INPUT -j SuiviConnexions iptables -A FORWARD -j SuiviConnexions
Et le tour est joué, puisque OUTPUT accepte tout. Il faut faire beaucoup confiance au bon fonctionnement de conntrack et ne pas trop se poser de questions sur les coups tordus qui peuvent arriver à passer quand même là dedans, mais au premier coup d'oeil, votre machine paraîtra invisible sur le Net.
Enfin, pour ssh :
iptables -A INPUT -p tcp --dport ssh -j ACCEPT
Très souvent, les clients du LAN derrière un routeur NAT ne peuvent accéder à des serveurs FTP sur le Net qu'en mode passif. Sans précautions particulières, ce sera également le cas ici.
Cependant, Netfilter permet de s'affranchir de cette limitation, en exploitant les modules spécialisés, nf_nat_ftp
et nf_conntrack_ftp
. Ceci nous amène à dire quelques mots du chargement de ces modules, à propos desquels nous ne nous sommes pas beaucoup posé de questions.
Netfilter est capable de charger dynamiquement la plupart des modules qui lui sont nécessaires, en fonction des règles écrites. Faites un lsmod
et voyez les modules impliqués dans Netfilter (ils sont tous dans /lib/modules/<version du kernel utilisé>/kernel/net/ipv4/netfilter
et dans /lib/modules/<version du kernel utilisé>/kernel/net/netfilter
).
Cependant, les modules nécessaires au FTP actif ne se chargent pas automatiquement. Vous pourrez les monter avec modprobe pour faire les tests. Si vous voulez les rendre automatiquement disponibles à chaque démarrage, référencez-les par exemple dans le fichier /etc/modules.
C'est le moment d'utiliser un outil fourni avec iptables : le script iptables-save. Ce script envoie sur le flux de sortie par défaut, normalement l'écran, le contenu des chaînes de toutes les tables, dans un format relativement lisible pour l'être humain :
# iptables-save # Generated by iptables-save v1.2.6a on Mon Dec 2 18:22:31 2002 *mangle :PREROUTING ACCEPT [4110:906437] :INPUT ACCEPT [113562:22595477] :FORWARD ACCEPT [2160:709057] :OUTPUT ACCEPT [2308:208513] :POSTROUTING ACCEPT [68746:14733820] COMMIT # Completed on Mon Dec 2 18:22:31 2002 # Generated by iptables-save v1.2.6a on Mon Dec 2 18:22:31 2002 *filter :INPUT DROP [392:38736] :FORWARD DROP [20:944] :OUTPUT DROP [616:25100] -A INPUT -i lo -j ACCEPT -A INPUT -i eth0 -j ACCEPT -A FORWARD -i eth0 -o ppp0 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT -A FORWARD -i ppp0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT -A OUTPUT -o lo -j ACCEPT -A OUTPUT -o eth0 -j ACCEPT COMMIT # Completed on Mon Dec 2 18:22:31 2002 # Generated by iptables-save v1.2.6a on Mon Dec 2 18:22:31 2002 *nat :PREROUTING ACCEPT [781:63004] :POSTROUTING ACCEPT [331:18116] :OUTPUT ACCEPT [1028:49802] -A POSTROUTING -o ppp0 -j MASQUERADE COMMIT # Completed on Mon Dec 2 18:22:31 2002
Nous retrouvons bien là dedans tout ce que nous avons défini plus haut. Mais cette commande a un autre avantage. En dirigeant sa sortie vers un fichier, vous obtenez un fichier de configuration qui sera exploitable par un autre script : iptables-restore
En d'autres termes, si vous faites :
iptables-save > /root/maconfig.iptables
vous pourrez refaire ensuite :
iptables-restore < /root/maconfig.iptables
Pour restaurer intégralement votre configuration.
Sur Debian, il est possible d'invoquer des commandes lors de l'activation et de la désactivation d'une interface réseau, dans le fichier /etc/network/interfaces
. Voyez le chapitre « Partage de connexion » et plus particulièrement la page « Passerelle simple » pour plus de détails.
Beaucoup de choses n'ont pas été dites, Netfilter nécessiterait un livre entier. Parmi ce dont nous n'avons pas parlé et qui peut s'avérer utile, même pour un réseau domestique :
Je ne suis pas un expert en sécurité. Ne comptez pas sur moi pour vous donner toutes les ficelles de sécurisation de votre installation. D'ailleurs, rien n'est définitif dans ce domaine.
Reprenons quelques liens qui vous en apprendront d'avantage :
Et probablement beaucoup d'autres que je ne connais même pas.