Guide Pratique du Filtrage de Paquets sous Linux 2.4 Rusty Russell Titre original : `Linux 2.4 Packet Filtering HOWTO' Traduction initiale : Emmanuel Roger Dernière adaptation : Guillaume Audiracguillaume POINT audirac CHEZ netpratique POINT fr Relecture : Thomas Nemethtnemeth CHEZ free POINT fr v1.26.fr.1.0, le 17 Avril 2004, traduction/adaptation Ce document décrit comment utiliser Iptables pour filtrer les paquets indésirables, pour les noyaux Linux 2.4. ______________________________________________________________________ Table des matières 1. Introduction 2. Où se Trouvent les Sites Web Officiels ? Existe-t'il une Liste de Diffusion ? 3. Alors Qu'est-ce Qu'un Filtre à Paquets ? 3.1 Pourquoi Souhaiterais-je Filtrer des Paquets ? 3.2 Comment est-ce que je Filtre les Paquets Sous Linux ? 3.2.1 Iptables 3.2.2 Construire des Règles Permanentes 4. Bon Sang, Qui Êtes-Vous et Pourquoi Jouez-Vous avec mon Noyau ? 5. Le Guide Rapide de Rusty sur le Filtrage de Paquets 6. Comment les Paquets Traversent les Filtres 7. Utiliser Iptables 7.1 Ce que Vous Verrez Quand Votre Ordinateur Démarrera 7.2 Opérations sur une Seule Chaîne 7.3 Spécifications de Filtrage 7.3.1 Spécifier les Adresses IP Source et Destination 7.3.2 Spécifier une Inversion 7.3.3 Spécifier un Protocole 7.3.4 Spécifier une Interface 7.3.5 Spécifier des Fragments 7.3.6 Extensions à Iptables : Nouvelles Correspondances 7.3.6.1 Extensions de TCP 7.3.6.1.1 Une Explication des Fanions TCP 7.3.6.2 Extensions d'UDP 7.3.6.3 Extensions d'ICMP 7.3.6.4 Autres Extensions de Correspondance 7.3.6.5 La Correspondance d'État 7.4 Spécifications de Cible 7.4.1 Les Chaînes Créées Par l'Utilisateur 7.4.2 Extensions d'Iptables : Nouvelles Cibles 7.4.3 Cibles Pré-Définies Spéciales 7.5 Opérations sur une Chaîne Entière 7.5.1 Créer une Nouvelle Chaîne 7.5.2 Supprimer une Chaîne 7.5.3 Vider une Chaîne 7.5.4 Lister une Chaîne 7.5.5 Initialiser les Compteurs 7.5.6 Configurer le Comportement Par Défaut 8. Utiliser Ipchains et Ipfwadm 9. Mélanger le NAT et le Filtrage de Paquets 10. Différences Entre Iptables et Ipchains 11. Quelques Conseils sur la Conception d'un Filtre à Paquets 12. Commentaires et Corrections ______________________________________________________________________ 1. Introduction Bienvenue, ami lecteur. On suppose ici que vous savez ce que sont une adresse IP, une adresse réseau, le routage et le DNS. Sinon, je vous recommande de lire le Guide Pratique des Concepts du Réseau sous Linux. Ce Guide Pratique commence par une gentille introduction (qui va vous laisser bien au chaud pour l'instant, mais sans défense dans le monde réel) avant de basculer vers une douloureuse révélation (qui va tous vous laisser confus, paranoïaques et en recherche d'armes lourdes, hormis les plus hardis). Votre réseau n'est pas sécurisé. Permettre des communications faciles et rapides, en n'autorisant que les communications valides et bien intentionnées, équivaut à un autre problème insoluble, tel que permettre de parler normalement dans un théâtre bondé, tout en empêchant de hurler ``Au Feu !''. Bien sûr, ce cas ne sera pas résolu dans ce Guide Pratique. Ainsi, vous seul pouvez décider où se situera le compromis. J'essayerai de vous expliquer l'utilisation de quelques outils disponibles et certaines vulnérabilités auxquelles il faut prêter attention, en espérant que vous les utiliserez avec de bonnes et non de mauvaises intentions. Un autre souci. (C) 2000 Paul `Rusty' Russell. Sous license GNU GPL. 2. Où se Trouvent les Sites Web Officiels ? Existe-t'il une Liste de Diffusion ? Voici les trois sites officiels : · Merci à Filewatcher . · Merci à l'équipe de samba et SGI . · Merci à Harald Welte . Vous pouvez tous les atteindre en utilisant le DNS de type Round-Robin via et Pour la liste de diffusion officielle de Netfilter : Liste de Netfilter . 3. Alors Qu'est-ce Qu'un Filtre à Paquets ? Un filtre à paquets est un programme qui examine l'en-tête des paquets qui passent, et décide du sort du paquet entier. Il peut choisir de DÉTRUIRE (`DROP') le paquet (i.e. faire comme s'il n'avait jamais été reçu), d'ACCEPTER (`ACCEPT') le paquet (i.e. le laisser passer) ou quelque chose de plus compliqué. Sous Linux, le filtrage de paquets s'effectue au niveau du noyau (avec un module ou directement intégré dedans), et permet des choses plus astucieuses encore avec les paquets, mais le principe de base reste toujours d'examiner les en-têtes et de décider du sort du paquet. 3.1. Pourquoi Souhaiterais-je Filtrer des Paquets ? Contrôle. Sécurité. Vigilance. Contrôle : quand vous utilisez une machine sous Linux pour connecter votre propre réseau (interne) à un autre réseau (externe, disons Internet), vous avez la possibilité d'autoriser certains types de trafic et d'en interdire d'autres. Par exemple, comme l'en- tête d'un paquet contient son adresse de destination, vous pouvez l'empêcher d'aller vers une certaine partie du réseau externe. Comme autre exemple, j'utilise Netscape pour accéder aux archives de Dilbert. Il y a des publicités de doubleclick.net sur la page, et Netscape me fait perdre du temps à les télécharger. Préciser au filtre de n'autoriser aucun paquet de et vers doubleclick.net résout ce problème (même s'il y a de meilleures façons de faire ça : voir Junkbuster). Sécurité : quand votre machine sous Linux est le seul intermédiaire entre le chaos d'Internet et votre beau réseau bien ordonné, il est bon de savoir que vous pouvez en restreindre l'accès suivant ce qui frappe à votre porte. Par exemple, vous pouvez permettre toute connexion vers l'extérieur de votre réseau, mais vous pouvez être embêté par le célèbre `Ping de la Mort' venant d'étrangers malicieux. Comme autre exemple, vous ne voudriez pas qu'un inconnu se connecte par `telnet' sur votre machine, même si tous vos comptes sont protégés par un mot de passe. Peut-être voulez-vous (comme la plupart des gens) être un observateur sur Internet et non un serveur (désiré ou non). Pour cela, ne laissez tout simplement personne se connecter chez vous grâce au filtrage de paquets, en refusant les paquets entrants employés pour établir des connexions. Vigilance : parfois, une machine mal configurée sur le réseau local décidera d'envoyer des paquets au monde extérieur. Il est intéressant de demander au filtrage de paquets de vous avertir si quelque chose d'inhabituel se produit; peut-être voulez-vous en tenir compte ou simplement êtes-vous curieux de nature. 3.2. Comment est-ce que je Filtre les Paquets Sous Linux ? Les noyaux Linux ont connu le filtrage de paquets depuis la série des 1.1. La première génération, basée sur Ipfw de BSD, a été adaptée par Alan Cox fin 1994. Elle a été amélioré par Jos Vos et d'autres pour Linux 2.0; l'outil de configuration `Ipfwadm' contrôlait les règles de filtrage du noyau. À la mi-1998, pour Linux 2.2, j'ai méchamment retravaillé le noyau, avec l'aide de Michael Neuling, et j'ai commencé l'outil appelé `Ipchains'. Finalement, l'outil de 4ème génération `Iptables' et une autre réécriture du noyau sont arrivés à la mi-1999 pour Linux 2.4. C'est sur Iptables que se concentre ce Guide Pratique. Vous avez besoin d'un noyau qui inclut l'infrastructure de Netfilter : Netfilter est un architecture générale à l'intérieur du noyau sur laquelle d'autres choses (comme le module Iptables) viennent se greffer. Cela signifie que vous avez besoin d'un noyau 2.3.15 ou plus, et de répondre `Y' à CONFIG_NETFILTER lors de la compilation du noyau. L'outil Iptables communique avec le noyau et lui indique les paquets à filtrer. A moins que vous ne soyez un programmeur ou bien excessivement curieux, c'est ainsi que vous contrôlerez le filtrage des paquets. 3.2.1. Iptables L'outil Iptables insère et retire des règles de la table de filtrage des paquets du noyau. Donc peu importe ce que vous configurez, tout sera perdu au redémarrage; voyez ``Construire des Règles Permanentes'' pour vous assurer que vos règles seront rétablies au prochain amorçage. Iptables est un successeur d'Ipfwadm et d'Ipchains : voyez ``Utiliser Ipchains et Ipfwadm'' pour éviter de peiner sur Iptables si vous utilisez déjà un des ces deux outils. 3.2.2. Construire des Règles Permanentes Votre configuration actuelle de pare-feu est stockée dans le noyau, et donc sera perdue au redémarrage. Vous pouvez essayer les scripts `iptables-save' et `iptables-restore' pour la sauvegarder et la restituer à partir d'un fichier. L'autre méthode consiste à mettre les commandes de configuration requises dans un script d'initialisation. Soyez sûr de faire quelque chose d'intelligent si l'une des commandes venait à échouer (habituellement `exec /sbin/sulogin'). 4. Bon Sang, Qui Êtes-Vous et Pourquoi Jouez-Vous avec mon Noyau ? Je m'appelle Rusty Russel; je suis le mainteneur du Pare-feu IP pour Linux et juste un autre codeur actif qui s'est trouvé à la bonne place au bon moment. J'ai écrit Ipchains (voir plus haut ``Comment est-ce que je Filtre les Paquets Sous Linux?'' pour les remerciements mérités aux personnes qui ont fait le vrai travail), et j'en ai appris assez pour effectuer le filtrage de paquets convenablement cette fois. J'espère. WatchGuard , une excellente entreprise de pare-feux, qui vend l'interface Firebox, m'a gentiment rémunéré à ne rien faire, excepté rédiger ce document et maintenir mes précédents travaux. J'avais prévu 6 mois et ça en a pris 12, mais je pense que cette fois, ça a été bien fait. Ne nombreuses réécritures, un crash- disque, un portable volé, quelques systèmes de fichiers corrompus et un écran détruit plus tard, voilà ce que ça donne. Pendant que j'y suis, je voudrais éclaircir quelques fausses idées récurrentes : je ne suis pas un gourou du noyau. Je le sais parce que mon travail sur le noyau m'a mis en contact avec certains d'entre- eux : David S. Miller, Alexey Kuznetsov, Andi Kleen, Alan Cox. De toute façon, ils sont tous occupés à faire de la magie en profondeur, me laissant barboter en surface, là où on est en sécurité. 5. Le Guide Rapide de Rusty sur le Filtrage de Paquets La plupart des gens ont juste une simple connexion PPP à Internet, et ne veulent pas que quelqu'un pénètre sur leur réseau ou leur pare- feu : ## Insérer les modules de suivi de connexion (non nécessaire si compilé dans le noyau). # insmod ip_conntrack # insmod ip_conntrack_ftp ## Créer une chaîne qui bloque les nouvelles connexions, sauf celles qui viennent de l'intérieur. # iptables -N block # iptables -A block -m state --state ESTABLISHED,RELATED -j ACCEPT # iptables -A block -m state --state NEW -i ! ppp0 -j ACCEPT # iptables -A block -j DROP ## Sauter sur cette chaîne à partir des chaînes INPUT et FORWARD. # iptables -A INPUT -j block # iptables -A FORWARD -j block 6. Comment les Paquets Traversent les Filtres Le noyau contient à la base trois listes de règles dans la table `filter'; ces listes sont appelées chaînes de pare-feu ou simplement chaînes. Les trois chaînes sont nommées INPUT, OUTPUT et FORWARD. Pour les fans de l'art ASCII, les chaînes sont arrangées comme suit : (Note : c'est un agencement très différent des noyaux 2.0 et 2.2 !) _____ Entrée / \ Sortie --> [Décision] ---->|FORWARD|-----> [de routage] \_____/ ^ | | v ____ ___ / \ / \ |OUTPUT| |INPUT| \____/ \___/ ^ | | ---> Processus local --- Les trois cercles représentent les trois chaînes mentionnées ci- dessus. Lorsqu'un paquet atteint un cercle dans le diagramme, cette chaîne est examinée pour décider du sort du paquet. Si la chaîne stipule de DÉTRUIRE (`DROP') le paquet, il est supprimé ici, mais si la chaîne stipule d'ACCEPTER (`ACCEPT') le paquet, il continue sa route dans le diagramme. Une chaîne est un liste de vérification de règles. Chaque règle énonce `si l'en-tête du paquet est comme ceci, voilà ce qu'il convient de faire du paquet'. Si une règle ne concorde pas avec le paquet, alors la règle suivante est examinée. Finalement, s'il ne reste plus de chaînes à examiner, le noyau consulte la règle par défaut de la chaîne pour prendre une décision. Dans un système sécuritaire et consciencieux, cette politique par défaut devrait DÉTRUIRE le paquet. 1. Quand un paquet arrive (supposons par la carte Ethernet), le noyau regarde en premier sa destination : on appelle ceci le `routage'. 2. S'il est destiné à cette machine, le paquet continue vers le bas du diagramme, vers la chaîne INPUT. S'il la traverse, les processus en attente du paquet le recevront. 3. Autrement, si le noyau n'a pas autorisé la réexpédition (`forwarding') ou s'il ne sait pas comment réexpédier le paquet, celui-ci est détruit. Si la réexpédition est autorisée et que le paquet est destiné à une autre interface réseau (si vous en possédez une autre), il passe directement à la chaîne FORWARD dans le diagramme. S'il est accepté (`ACCEPT'), il sera envoyé. 4. Finalement, un programme en exécution sur la machine peut aussi envoyer des paquets sur le réseau. Ces paquets iront immédiatement vers la chaîne OUTPUT : si elle l'accepte (`ACCEPT'), alors le paquet continuera vers l'interface à laquelle il est destiné. 7. Utiliser Iptables Iptables bénéficie d'une page de manuel bien détaillée (man iptables) si vous avez besoin de détails particuliers. Pour ceux qui sont familiers d'Ipchains, vous devriez simplement aller voir ``Différences entre Iptables et Ipchains'' car ils sont vraiment similaires. Différentes choses peuvent être réalisées avec Iptables. Pour commencer, travaillons avec les trois chaînes pré-définies INPUT, OUTPUT et FORWARD que vous ne pouvez pas effacer. Et analysons les opérations pour administrer les chaînes : 1. Créer une nouvelle chaîne (-N). 2. Effacer une chaîne vide (-X). 3. Changer la règle par défaut pour une chaîne pré-définie (-P). 4. Lister les règles d'une chaîne (-L). 5. Retirer les règles d'une chaîne (-F). 6. Mettre à zéro les compteurs de bits et de paquets d'une chaîne (-Z). Il y a plusieurs manières de manipuler une règle à l'intérieur d'une chaîne : 1. Ajouter une nouvelle règle à la chaîne (-A). 2. Insérer une nouvelle règle à une position précise dans la chaîne (-I). 3. Remplacer une règle à une position précise dans la chaîne (-R). 4. Supprimer une règle à une position précise dans la chaîne ou la première qui concorde (-D). 7.1. Ce que Vous Verrez Quand Votre Ordinateur Démarrera Iptables peut être utilisé sous forme d'un module, appelé (`iptable_filter.o'), qui devrait être automatiquement chargé lorsque vous exécutez la commande iptables. Il peut également être compilé de façon permanente dans le noyau. Avant qu'aucune commande n'ait été exécutée (attention : certaines distributions lanceront Iptables dans leurs scripts d'initialisation), il n'y a de règles dans aucune des chaînes pré-définies (`INPUT', `FORWARD' et `OUTPUT'); toutes les chaînes ont une règle par défaut de type ACCEPT. Vous pouvez modifier la règle par défaut de la chaîne FORWARD en spécifiant l'option `forward=0' au module iptable_filter. 7.2. Opérations sur une Seule Chaîne C'est le gagne-pain du filtrage de paquets ; manipuler des règles. Dans la plupart des cas, vous utiliserez les commandes d'ajout (-A) et d'effacement (-D). Les autres (-I pour insérer et -R pour remplacer) sont de simples extensions de ces concepts. Chaque règle spécifie un ensemble de conditions que le paquet doit remplir et ce qui sera fait si le paquet les remplit (une `cible'). Par exemple, vous voudriez détruire tous les paquets ICMP qui proviennent de l'adresse IP 127.0.0.1. Dans ce cas, les conditions sont que le protocole est ICMP et que l'adresse source est 127.0.0.1. Notre cible est de type `DROP'. 127.0.0.1 est l'interface de bouclage (`loopback'), que vous posséderez même si vous n'avez pas de réelle connexion réseau. Vous pouvez utiliser la commande `ping' pour générer de tels paquets. Elle envoie simplement un ICMP de type 8 (echo request) auquel tous les hôtes coopératifs devraient répondre aimablement avec un ICMP de type 0 (echo reply). En cela, il est très utile pour le test. # ping -c 1 127.0.0.1 PING 127.0.0.1 (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.2 ms --- 127.0.0.1 ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 0.2/0.2/0.2 ms # iptables -A INPUT -s 127.0.0.1 -p icmp -j DROP # ping -c 1 127.0.0.1 PING 127.0.0.1 (127.0.0.1): 56 data bytes --- 127.0.0.1 ping statistics --- 1 packets transmitted, 0 packets received, 100% packet loss # Vous pouvez constater que le 1er ping a fonctionné (le `-c 1' signale à ping de n'envoyer qu'un seul paquet). Ensuite, nous ajoutons (-A) à la chaîne `INPUT', une règle spécifiant que pour les paquets issus de 127.0.0.1 (`-s 127.0.0.1') avec le protocole ICMP (`-p icmp'), nous devons sauter vers la cible DROP (`-j DROP'). Ensuite, nous testons notre règle en utilisant le second ping. Il y aura une pause avant que le programme ne stoppe parce qu'il attendra une réponse qui ne viendra jamais. Nous pouvons effacer une règle de deux façons. Premièrement, comme nous savons que c'est la seule règle dans la chaîne INPUT, nous pouvons utiliser un effacement par numérotation : # iptables -D INPUT 1 # pour effacer la règle numéro 1 dans la chaîne INPUT. La seconde façon correspond au reflet de la commande -A, mais en substituant -A à -D. C'est pratique quand votre chaîne de règles devient complexe et que vous ne souhaitez pas les compter pour découvrir que c'est la règle 37 que vous voulez supprimer. Dans ce cas, on utiliserait : # iptables -D INPUT -s 127.0.0.1 -p icmp -j DROP # La syntaxe de la commande -D doit avoir exactement les mêmes options que celles de -A (ou -I, ou -R). S'il y a plusieurs règles identiques dans la même chaîne, la première seulement sera effacée. 7.3. Spécifications de Filtrage Nous avons vu l'utilisation de `-p' pour spécifier le protocole et de `-s' pour spécifier l'adresse source, mais il y a d'autres options que vous pouvez utiliser pour spécifier les caractéristiques d'un paquet. Ce qui suit en est un inventaire exhaustif. 7.3.1. Spécifier les Adresses IP Source et Destination Les adresses IP source (`-s', `--source' ou `--src') et destination (`-d', `--destination' ou `--dst') peuvent être spécifiées de 4 façons. La plus courante est d'utiliser le nom complet, comme `localhost' ou `www.linuxhq.com'. La seconde façon est de spécifier l'adresse IP comme `127.0.0.1'. Les troisième et quatrième façons permettent de spécifier un groupe d'adresses IP, comme `199.95.207.0/24' ou `199.95.207.0/255.255.255.0'. Toutes deux spécifient toutes les adresses de 199.95.207.0 à 199.95.207.255 inclus; les chiffres après le `/' précisent la partie signifiante des adresses IP. `/32' ou `/255.255.255.255' correspondent au cas par défaut (soit à toutes les adresses IP). Pour spécifier absolument toutes les adresses IP, `/0' peut être utilisé, comme dans : [ NOTE: `-s 0/0' est ici redondant. ] # iptables -A INPUT -s 0/0 -j DROP # Ceci est rarement utilisé, puisque l'effet de la commande ci-dessus est le même que de ne pas spécifier du tout l'option `-s'. 7.3.2. Spécifier une Inversion De nombreuses options, dont `-s' (ou `--source' ) et `-d' (ou `--destination'), peuvent voir leurs arguments précédés de `!' (indiquant la négation) pour coïncider avec les adresses DIFFÉRENTES de celles indiquées. Par exemple `-s ! localhost' correspond à tout paquet qui ne provient pas de localhost. 7.3.3. Spécifier un Protocole Le protocole peut être désigné avec l'option `-p' (ou `--protocol'). Un protocole est soit un nombre (si vous connaissez les valeurs numériques des protocoles IP), soit un nom pour les cas particuliers comme `TCP', `UDP' ou `ICMP'. La casse n'a pas d'importance, donc `tcp' marche aussi bien que `TCP'. Le nom du protocole peut être préfixé d'un `!' pour l'inverser, comme `-p ! TCP' pour spécifier les paquets qui ne sont pas issus de TCP. 7.3.4. Spécifier une Interface Les options `-i' (ou `--in-interface') et `-o' (ou `--out-interface') précisent le nom d'une interface à laquelle le paquet doit correspondre. Une interface représente le dispositif matériel par lequel le paquet est entré (`-i') ou sortira (`-o'). Grâce à la commande ifconfig, vous pouvez lister les interfaces actives (ou `up'). Les paquets traversant la chaîne INPUT n'ont pas encore d'interface de sortie, donc toute règle utilisant `-o' dans cette chaîne ne coïncidera jamais. De la même manière, les paquets traversant la chaîne OUTPUT n'ont pas d'interface d'entrée, donc toute règle utilisant `-i' dans cette chaîne ne coïncidera jamais. Seuls les paquets traversant la chaîne FORWARD ont à la fois une interface d'entrée et de sortie. Il est parfaitement autorisé de spécifier une interface qui n'existe pas à cet instant ; la règle ne coïncidera pas jusqu'à ce que l'interface soit active (ou `up'). C'est particulièrement utile pour les accès par ligne commutée avec PPP (habituellement l'interface ppp0) et ses semblables. Comme cas particulier, un nom d'interface se terminant par un `+' coïncidera avec toutes les interfaces qui commencent par ce nom (qu'elles existent déjà ou non). Par exemple, pour spécifier une règle qui concorde avec toutes les interfaces PPP, on utilisera l'option -i ppp+. Le nom de l'interface peut être précédé par un `!' (avec des espaces autour), pour concorder avec un paquet qui n'appartient pas à l'interface spécifiée, par exemple -i ! ppp+. 7.3.5. Spécifier des Fragments Parfois, un paquet est trop volumineux pour être transmis en une fois sur la ligne. Quand ça arrive, il est divisé en fragments et envoyé en plusieurs paquets. L'autre extrémité réassemble ces fragments pour reconstruire le paquet entier. Le problème avec les fragments, c'est que le fragment initial possède l'en-tête complet (IP + TCP, UDP et ICMP) à examiner, mais que les paquets suivants ont seulement un morceau de l'en-tête (IP sans les champs additionnels de protocole). Donc il est impossible de rechercher à l'intérieur des fragments suivants les en-têtes de protocoles (comme c'est fait pour les extensions TCP, UDP et ICMP). Si vous faîtes du traçage de connexion (ou NAT), alors tous les fragments seront fusionnés avant qu'ils n'atteignent le code de filtrage de paquets, par conséquent vous n'aurez pas à vous soucier des fragments. Attention, notez également que la chaîne INPUT de la table `filter' (ou toute autre table du `hook' NF_IP_LOCAL_IN) n'est traversée qu'après défragmentation du coeur de la pile IP. Autrement, il est important de comprendre comment les fragments sont traités par les règles de filtrage. Toute règle de filtrage qui demande des informations indisponibles ne concordera pas. Cela signifie que le premier fragment est traité comme tout autre paquet, mais que le second et les suivants ne le seront pas. Donc une règle -p TCP --sport www (qui spécifie le port source `www') ne coïncidera jamais avec un fragment (autre que le premier fragment). Il en est de même de la règle inverse -p TCP --sport ! www. Cependant, vous pouvez spécifier une règle pour les fragments au-delà du premier, à l'aide de l'option `-f' (ou `--fragment'). Il est aussi valide de spécifier une règle qui ne s'applique pas aux fragments autres que le premier, en faisant précéder `-f' de `!'. Habituellement, accepter les fragments suivant le premier est considéré comme sûr, parce que le filtrage étant effectif sur le premier fragment, on empêche donc le réassemblage sur la machine cible; mais des bogues ont été trouvés qui permettent de planter des machines simplement en leur envoyant des fragments. Vous êtes prévenus. Note pour les experts en réseaux : les paquets malformés (les paquets TCP, UDP et ICMP trop courts pour que le code du pare-feu ne puisse lire les ports, le code ICMP ou son type) sont détruits quand de telles combinaisons sont tentées, comme les fragments TCP qui commencent en position 8. À titre d'exemple, la règle suivante va détruire tous les fragments à destination de 192.168.1.1 : # iptables -A OUTPUT -f -d 192.168.1.1 -j DROP # 7.3.6. Extensions à Iptables : Nouvelles Correspondances Iptables est extensible, ce qui veut dire que le noyau et le programme Iptables peuvent être étendus pour avoir de nouvelles fonctionnalités. Quelques-unes de ces extensions sont normalisées, et d'autres sont plus exotiques. Elles peuvent être réalisées par quiconque et distribuées séparément à la demande d'utilisateurs. Les extensions du noyau se situent normalement dans le sous-répertoire des modules du noyau comme /lib/modules/2.4.0-test10/kernel/net/ipv4/netfilter. Elles sont chargées à la demande si votre noyau a été compilé avec CONFIG_KMOD, donc vous ne devriez pas avoir à les insérer à la main. Les extensions au programme Iptables sont des bibliothèques partagées qui se situent généralement dans /usr/local/lib/iptables/, bien qu'une distribution puisse les mettre dans /lib/iptables ou /usr/lib/iptables. Les extensions sont de deux types : nouvelles correspondances et nouvelles cibles (nous aborderons les nouvelles cibles plus tard). Quelques protocoles offrent aussi de nouveaux tests : pour le moment TCP, UDP et ICMP. Pour ceux-ci, vous pourrez spécifier de nouveaux tests en ligne de commande après l'option `-p', qui chargera implicitement l'extension. Pour spécifier explicitement de nouveaux tests, utilisez l'option `-m' pour charger l'extension, après quoi, ses options seront disponibles. Pour obtenir de l'aide sur une extension, utilisez l'option pour la charger (`-p', `-j' ou `-m') suivie de `-h' ou `--help', par exemple : # iptables -p tcp --help # 7.3.6.1. Extensions de TCP Les extensions de TCP sont automatiquement chargées si `-p tcp' est spécifié. Elles offrent les options suivantes (aucune d'entre-elles ne convient aux fragments). --tcp-flags suivi d'un `!' optionnel, puis 2 chaînes de caractères pour les fanions, vous permet de filtrer sur des fanions TCP spécifiques. La première chaîne correspond au masque : la liste de fanions que vous désirez examiner. La deuxième chaîne précisent lesquels doivent être présents. Par exemple : # iptables -A INPUT --protocol tcp --tcp-flags ALL SYN,ACK -j DROP Ceci indique que tous les fanions doivent être examinés (`ALL' est synonyme de `SYN,ACK,FIN,RST,URG,PSH'), mais seulement SYN et ACK doivent être présents. Il y a aussi l'argument `NONE' signifiant aucun fanion. --syn précédé optionnellement d'un `!', c'est un raccourci pour `--tcp-flags SYN,RST,ACK SYN'. --source-port suivi d'un `!' optionnel, puis soit un port TCP seul ou une plage de ports. Les ports peuvent être des noms, tels qu'ils sont listés dans `/etc/services', ou des nombres. Les plages sont soit 2 noms de ports séparés par `:' (pour exprimer un intervalle), un port suivi d'un `:' (pour exprimer supérieur ou égal à), ou un port précédé de `:' (pour exprimer inférieur ou égal à). --sport est synonyme de `--source-port'. --destination-port et --dport correspondent aux mêmes options qu'au-dessus, si ce n'est qu'elles spécifient le port de destination au lieu du port de source. --tcp-option suivi d'un `!' optionnel et d'un nombre, correspond à un paquet avec une option TCP égale à ce nombre. Un paquet qui n'a pas un en-tête TCP complet est automatiquement détruit lors d'une tentative pour examiner ses options TCP. 7.3.6.1.1. Une Explication des Fanions TCP Il est parfois utile d'autoriser les connexions TCP dans un sens mais pas dans l'autre. Par exemple, vous pourriez vouloir autoriser les connexions vers un serveur WWW externe, mais pas les connexions à partir de ce serveur. Une approche naïve serait de bloquer les paquets TCP venant du serveur. Malheureusement, les connexions TCP nécessitent des paquets évoluant dans les deux sens pour fonctionner. La solution est de bloquer seulement les paquets utilisés pour demander une connexion. Ces paquets sont appelés des paquets SYN (d'accord, techniquement, ce sont des paquets avec le fanion SYN et pas de fanions FIN et ACK, mais nous les appelons des paquets SYN pour simplifier). En disqualifiant uniquement ces paquets, nous pouvons stopper les tentatives de connexions. Le fanion `--syn' est utilisé pour cela : il est valide seulement pour les règles qui spécifient TCP comme protocole. Par exemple, pour spécifier une tentative de connexion à partir de l'adresse 192.168.1.1 : -p TCP -s 192.168.1.1 --syn Ce fanion peut être inversé en le faisant précéder de `!', qui signifie alors tous les paquets sauf ceux d'initiation d'une connexion. 7.3.6.2. Extensions d'UDP Ces extensions sont automatiquement chargées si `-p udp' est spécifié. Elles procurent les options `--source-port', `--sport', `--destination-port' et `--dport' comme explicité ci-dessus pour le protocole TCP. 7.3.6.3. Extensions d'ICMP Cette extension est automatiquement chargée si `-p icmp' est spécifié. Elle ne fournit qu'une seule nouvelle option : --icmp-type suivi d'un `!' optionnel, puis un nom de type ICMP (par exemple `host-unreachable'), ou un type sous forme numérique (par exemple `3'), ou encore un type et un code numériques séparés par un `/' (par exemple `3/3'). Une liste des types ICMP disponibles est fournie avec `-p icmp --help'. 7.3.6.4. Autres Extensions de Correspondance Les autres extensions du paquetage Netfilter sont des extensions de démonstration qui, une fois installées, peuvent être invoquées avec l'option `-m'. mac Ce module doit être spécifié explicitement avec `-m mac' ou `--match mac'. Il est utilisé pour correspondre avec des adresses Ethernet (MAC) de paquets entrants, et il est donc seulement utile pour des paquets traversant les chaînes INPUT et PREROUTING. Il ne propose qu'une seule option : --mac-source suivi d'un `!' optionnel, puis d'une adresse Ethernet en octets (notation hexadécimale) séparés par des `:', par exemple `--mac-source 00:60:08:91:CC:B7'. limit Ce module doit être spécifié explicitement avec `-m limit' ou `--match limit'. Il est utilisé pour limiter le taux de correspondances, typiquement pour réduire des messages de journalisation (ou `log'). Il prendra en compte les correspondances seulement un certain nombre de fois pas seconde (par défaut, 3 correspondances par heure, avec une réserve de 5). Il possède deux arguments optionnels : --limit suivi d'un nombre, pour spécifier (en moyenne) le nombre maximum de correspondances acceptées par seconde. On peut spécifier son unité explicitement, en utilisant `/second', `/minute', `/hour' ou `/day', ou en abrégé (ainsi `5/second' est identique à `5/s'). --limit-burst suivi d'un nombre, indique la réserve maximale (ou la salve) avant que la limite ci-dessus n'entre en jeu. Cette correspondance peut souvent être employée avec la cible LOG pour limiter les occurences de journalisation. Pour comprendre comment cela fonctionne, examinons la règle suivante, qui journalise les paquets avec les paramètres de limite par défaut : # iptables -A FORWARD -m limit -j LOG La première fois que cette règle est satisfaite, le paquet est journalisé. En fait, avec une réserve de 5, seuls les 5 premiers paquets seront journalisés. Ensuite, 20 minutes doivent passer avant qu'un nouveau paquet ne soit journalisé par cette règle, sans tenir compte du nombre de paquets qui correspondent. Aussi, chaque fois que 20 minutes s'écoulent sans constater de correspondance, un paquet de la réserve est récupéré (sa valeur est incrémentée). Si aucun paquet ne satisfait la règle pendant 100 minutes, la réserve est complètement rechargée et on est revenu au point de départ. Note : vous ne pouvez actuellement créer de règle avec un temps de recharge de plus de 59 heures, donc si vous configurez un débit moyen de 1 par jour, alors le débit de réserve doit être inférieur à 3. Vous pouvez aussi utiliser ce module pour éviter les diverses attaques engendrant un déni de service (DoS) et avec un débit supérieur pour augmenter la vitesse de réaction. Protection contre les inondations de requêtes de connexions (`syn- flood') : # iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT Balayage de ports furtif : # iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT Ping de la mort : # iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT Ce module fonctionne comme une porte à hystérésis, comme le montre l'illustration ci-dessous. Débit (pqts/s) ^ .---. | / DoS \ | / \ Limite de DoS -|.....:.........\....................... = (limit * | /: \ limit-burst) | / : \ .-. | / : \ / \ | / : \ / \ Fin de DoS -|/....:..............:.../.......\..../. = limit | : :`-' `--' ---------------+-----+--------------+------------------> Temps (s) LOGIQUE => Concord.| Non concord. | Concordance On mentionne un paquet par seconde avec une réserve de 5 paquets, mais ici, les paquets commencent à arriver avec un débit de 4/s pendant 3 secondes puis recommencent après 3 autres secondes. <-Inond. 1 -> <- Inond. 2 -> Nb total de ^ Maximum __-- YNNN paquets| Débit __-- YNNN | de __-- YNNN 10 | Ligne __-- Y | __-- Y | __-- Y | __-- YNNN |- YNNN 5 | Y | Y Key: Y -> La règle concorde | Y N -> La règle ne concorde pas | Y |Y 0 +--------------------------------------------------> Temps (secondes) 0 1 2 3 4 5 6 7 8 9 10 11 12 Vous constatez que les 5 premiers paquets sont autorisés à dépasser la limite d'un paquet par seconde, puis la limitation entre en jeu. Si une pause intervient, une autre rafale est autorisée, mais pas au-delà du débit maximum fixée par la règle (1 paquet par seconde après épuisement de la réserve). owner Ce module essaie de faire correspondre les diverses caractéristiques du créateur du paquet, pour les paquets générés localement. Il est uniquement valide dans la chaîne OUTPUT, et même dans ce cas, certains paquets sans propriétaire (comme les réponses ICMP d'un ping) ne corresponderont jamais. --uid-owner id_utilisateur Concorde si le paquet a été créé par un processus avec l'identifiant d'utilisateur (numérique) indiqué. --uid-owner id_de_groupe Concorde si le paquet a été créé par un processus avec l'identifiant de groupe (numérique) indiqué. --pid-owner id_de_processus Concorde si le paquet a été créé par un processus avec le numéro de processus indiqué. --sid-owner id_de_session Concorde si le paquet a été créé par un processus appartenant au groupe de session indiqué. unclean Ce module expérimental doit être spécifié explicitement avec `-m unclean ou `--match unclean'. Il effectue des vérifications diverses et variées sur la bonne constitution des paquets. Ce module n'a pas été vérifié et ne devrait pas être utilisé comme dispositif de sécurité (il pourrait rendre les choses plus dangereuses s'il contient lui-même des bogues). Il ne dispose d'aucune option. 7.3.6.5. La Correspondance d'État Le critère de correspondance le plus utile est fourni par l'extension `state', qui interprète l'analyse de traçage de connexion du module `ip_conntrack'. Il est fortement recommandé. Spécifier `-m state' permet d'accéder à l'option supplémentaire `--state', qui évalue la correspondance avec une liste d'états séparés par des virgules (les `!' indiquent les états qui ne correspondent pas). Ces états sont : NEW Le paquet démarre une nouvelle connexion. ESTABLISHED Le paquet est lié à une connexion existante (c'est-à-dire un paquet de réponse ou un paquet envoyé vers l'extérieur appartenant à une connexion qui a déjà répondu). RELATED Le paquet est associé à une connexion existante sans faire partie de cette connexion, comme une erreur ICMP ou (avec le module FTP chargé) un paquet établissant une connexion de données FTP. INVALID Le paquet ne peut pas être identifié pour une raison quelconque : ceci comprend un manque de mémoire et des erreurs ICMP décorrélées d'une connexion connue. Généralement, ces paquets devraient être détruits. Un exemple de cette puissante extension de correspondance pourrait être : # iptables -A FORWARD -i ppp0 -m state ! --state NEW -j DROP 7.4. Spécifications de Cible Maintenant que nous connaissons les tests réalisables sur un paquet, nous avons besoin de déterminer ce qu'il convient de faire des paquets sélectionnés par nos tests. C'est ce qu'on appelle la cible d'une règle. Les deux cibles pré-définies sont simples : DROP et ACCEPT. Nous les avons déjà abordées. Si une règle correspond à un paquet et que la cible est une de ces deux-là, aucune autre règle ne sera consultée : le sort du paquet est déjà décidé. Il existe deux types de cibles différentes des cibles pré-définies : les extensions et les chaînes créées par l'utilisateur. 7.4.1. Les Chaînes Créées Par l'Utilisateur Une propriété puissante d'Iptables (héritée d'Ipchains) est la possibilité pour l'utilisateur de créer de nouvelles chaînes, en plus de celles existantes (INPUT, FORWARD et OUTPUT). Par convention, les chaînes utilisateur sont en minuscule pour les différencier (nous décrirons comment créer de nouvelles chaînes utilisateur dans ``Opérations sur une Chaîne Entière'' ci-dessous). Quand un paquet correspond à une règle dont la cible est une chaîne utilisateur, le paquet commence à traverser les règles de cette chaîne. Si cette chaîne utilisateur ne décide pas du sort du paquet, alors une fois la traversée terminée, le test reprend sur la règle suivante de la chaîne courante. Le temps est venu pour un peu plus d'art ASCII. Considérons deux chaînes rudimentaires : INPUT (la chaîne pré-définie) et test (une chaîne définie par l'utilisateur). `INPUT' `test' ---------------------------- ---------------------------- | Règle1: -p ICMP -j DROP | | Règle1: -s 192.168.1.1 | |--------------------------| |--------------------------| | Règle2: -p TCP -j test | | Règle2: -d 192.168.1.1 | |--------------------------| ---------------------------- | Règle3: -p UDP -j DROP | ---------------------------- Considérons un paquet TCP venant de 192.168.1.1 et à destination de 1.2.3.4. Il pénètre dans la chaîne INPUT, et est évalué par la Règle1 - il n'y a pas de correspondance. Par contre, la Règle2 concorde et sa cible s'avère être la chaîne test, par conséquent, la règle suivante examinée est le début de cette nouvelle chaîne. La Règle1 de test concorde mais ne spécifie pas de cible, donc la règle suivante est examinée, soit la Règle2. Elle ne concorde pas et nous avons atteint la fin de la chaîne test. Nous retournons donc à la chaîne INPUT, dont nous venons d'examiner la Règle2. Nous passons alors à la Règle3, qui ne concorde pas davantage. On peut schématiser ainsi l'itinéraire du paquet : v __________________________ `INPUT' | / `test' v ------------------------|--/ -----------------------|---- | Règle1 | /| | Règle1 | | |-----------------------|/-| |----------------------|---| | Règle2 / | | Règle2 | | |--------------------------| -----------------------v---- | Règle3 /--+___________________________/ ------------------------|--- v Les chaînes utilisateur peuvent sauter dans d'autres chaînes utilisateur (mais ne faîtes pas de boucle : vos paquets seraient irrémédiablement détruits). 7.4.2. Extensions d'Iptables : Nouvelles Cibles L'autre type d'extension est une cible. Une extension de cible est constituée d'un module du noyau et d'une extension optionnelle d'Iptables pour permettre de nouvelles options en ligne de commande. À l'origine, plusieurs extensions existent déjà dans la distribution de Netfilter : LOG Ce module permet de journaliser les paquets qui correspondent. Il propose des options supplémentaires : --log-level Suivi d'un nombre de niveaux ou d'un nom. Les noms valides (insensibles à la casse) sont `debug', `info', `notice', `warning', `err', `crit', `alert' et `emerg'. Ils correspondent respectivement aux nombres 7 à 0. Lisez la page de manuel de syslog.conf pour connaître leur signification. Le niveau par défaut est `warning'. --log-prefix Suivi d'une chaîne de 29 caractères maximum; ce message est envoyé au début du message de journalisation, pour rendre son identification unique. Ce module est surtout utile lors du dépassement d'une limite de correspondance, pour ne pas submerger les journaux. REJECT Ce module se comporte comme `DROP', excepté que l'expéditeur du paquet reçoit en plus un message d'erreur ICMP `port unreachable'. Notez que le message d'erreur ICMP n'est pas envoyé si (voir RFC 1122) : · Le paquet filtré est un message d'erreur ICMP ou un type ICMP inconnu. · Le paquet filtré est un fragment sans en-tête. · Trop de messages d'erreur ICMP ont été envoyés à cette destination récemment (voir /proc/sys/net/ipv4/icmp_ratelimit). REJECT peut aussi recevoir une option `--reject-with' qui change le type du paquet de réponse utilisé : consultez la page de manuel. 7.4.3. Cibles Pré-Définies Spéciales Il y a deux cibles spéciales pré-définies : RETURN et QUEUE. RETURN a le même effet que d'atteindre la fin d'une chaîne : pour une règle dans une chaîne pré-définie, le comportement par défaut de la chaîne est exécuté; pour une règle dans une chaîne utilisateur, l'analyse se poursuit dans la chaîne précédente, immédiatement après la règle qui a bifurqué sur cette chaîne utilisateur. QUEUE est une cible spéciale, qui met les paquets en file d'attente pour les traiter dans l'environnement de l'utilisateur. Pour que ça fonctionne, deux éléments supplémentaires sont requis : · un "arbitre de queue" (ou gestionnaire de file d'attente), qui compose avec les mécanismes de transfert des paquets entre le noyau et l'espace utilisateur; et · une application utilisateur, pour recevoir, éventuellement manipuler et établir un verdict sur le sort des paquets. L'arbitre de queue standard pour Iptables (version IPv4) est le module ip_queue. Il est distribué avec le noyau et signalé comme expérimental. Voici un exemple rapide de l'utilisation d'Iptables pour mettre des paquets en file d'attente afin de les traiter dans un environnement utilisateur : # modprobe iptable_filter # modprobe ip_queue # iptables -A OUTPUT -p icmp -j QUEUE Avec cette règle, les paquets ICMP sortants générés en local (par exemple créés avec ping) sont transmis au module ip_queue, qui tente ensuite de les délivrer à une application utilisateur. Si aucune application n'est prête à recevoir ces paquets, ils sont détruits. Pour écrire une application utilisateur, utilisez l'API libipq. Elle est distribuée avec Iptables. Des exemples de code peuvent être trouvés dans les outils "testsuite" (par exemple redirect.c) accessibles via CVS. Le statut de ip_queue peut être vérifié via : /proc/net/ip_queue La longueur maximale de la file d'attente (c'est-à-dire le nombre maximal de paquets sans verdict délivrés à l'espace utilisateur) peut être contrôlée via : /proc/sys/net/ipv4/ip_queue_maxlen La valeur par défaut de cette longueur maximale est 1024. Une fois cette limite atteinte, les nouveaux paquets seront détruits jusqu'à ce que la longueur de la file redescende sous la limite. Les protocoles bien conçus comme TCP interprètent une destruction de paquets comme une congestion, et se limiteront lorsque la file se remplit. Cependant, des expériences sont nécessaires pour déterminer idéalement la longueur maximale de file d'attente pour une situation donnée, si la valeur par défaut est trop faible. 7.5. Opérations sur une Chaîne Entière Une propriété utile d'Iptables est la possibilité de rassembler des règles apparentées dans des chaînes. Vous pouvez appeler les chaînes comme vous le souhaitez, mais je vous recommande les minuscules pour éviter la confusion avec les chaînes pré-définies et les cibles. Les noms de chaînes peuvent aller jusqu'à 31 caractères maximum. 7.5.1. Créer une Nouvelle Chaîne Créons une nouvelle chaîne. Comme je suis quelqu'un d'imaginatif, je l'appelle test. Nous lui appliquons l'option `-N' ou `--new-chain' : # iptables -N test # C'est aussi simple que ça. Maintenant, vous pouvez lui ajouter des règles comme expliqué précédemment. 7.5.2. Supprimer une Chaîne Effacer une chaîne est également très simple, grâce à l'option `-X' ou `--delete-chain'. Pourquoi `-X' ? Et bien, toutes les lettres satisfaisantes étaient déjà prises. # iptables -X test # Il y a des restrictions à la suppression d'une chaîne : elle doit être vide (voir ``Vider une Chaîne'' ci-dessous) et elle ne doit pas être la cible d'une autre règle. Et vous ne pouvez pas supprimer une des trois chaînes pré-définies. Si vous ne spécifiez pas de chaîne, alors toutes les chaînes définies par l'utilisateur seront effacées, si possible. 7.5.3. Vider une Chaîne Il y a une façon simple de vider une chaîne de toutes ses règles, en utilisant la commande `-F' (ou `--flush'). # iptables -F FORWARD # Si vous ne spécifiez pas de chaîne, alors toutes les chaînes seront vidées. 7.5.4. Lister une Chaîne Vous pouvez lister toutes les règles d'une chaîne en utilisant la commande `-L' (ou `--list'). Le paramètre `refcnt' listé pour chaque chaîne utilisateur correspond au nombre de règles ayant cette chaîne pour cible. Il doit être à zéro (et la chaîne doit être vide) avant qu'elle ne soit effacée. Si le nom de la chaîne est omis, toutes les chaînes sont listées, même les chaînes vides. Trois options peuvent accompagner `-L'. L'option `-n' (numérique) est vraiment utile car elle évite à Iptables d'essayer de résoudre les adresses IP, ce qui (si vous utilisez des DNS comme la plupart des gens) génèrera des temps d'attente si votre DNS n'est pas configuré convenablement, ou si vous avez filtré les requêtes DNS. Cette option force aussi l'affichage des ports TCP et UDP avec leur numéro plutôt qu'avec leur nom. L'option `-v' vous montre tous les détails des règles, tels que les compteurs de paquets et d'octets, les comparaisons de types de service (TOS) et les interfaces. Sinon ces paramètres sont omis. Notez que les compteurs de paquets et d'octets sont écrits avec les suffixes `K', `M' ou `G', respectivement pour 1.000, 1.000.000 et 1.000.000.000. L'option `-x' (pour `expand') écrit les nombres intégralement, quelle que soit leur taille. 7.5.5. Initialiser les Compteurs Il est pratique de pouvoir remettre les compteurs à zéro. Ceci peut être accompli avec l'option `-Z' (ou `--zero'). Considérons les commandes suivantes : # iptables -L FORWARD # iptables -Z FORWARD # Dans l'exemple ci-dessus, quelques paquets pourraient traverser, juste entre les commandes `-L' et `-Z'. Pour cette raison, vous pouvez utiliser les commandes `-L' et `-Z' ensemble, pour simultanément lister les chaînes et réinitialiser les compteurs. 7.5.6. Configurer le Comportement Par Défaut Auparavant, quand nous avons abordé le cheminement des paquets à travers les chaînes, nous avons considéré le sort d'un paquet atteignant la fin d'une chaîne pré-définie. Dans un telle situation, le comportement par défaut de la chaîne détermine le sort du paquet. Seules les chaînes pré-définies (INPUT, OUTPUT et FORWARD) possèdent un comportement par défaut. En effet, lorsqu'un paquet atteint la fin d'une chaîne utilisateur, la progression reprend à la chaîne précédente. Le comportement par défaut peut être soit ACCEPT, soit DROP. Par exemple : # iptables -P FORWARD DROP # 8. Utiliser Ipchains et Ipfwadm Dans la distribution de Netfilter, il y a des modules appelés ipchains.o et ipfwadm.o. Insérez l'un d'eux dans votre noyau (ATTENTION : ils sont incompatibles avec ip_tables.o !). Ensuite, vous pouvez utiliser Ipchains et Ipfwadm comme jadis. Ceci sera maintenu pendant encore quelque temps. Je pense qu'une formule raisonnable est 2 * [notification de remplacement - sortie de la version stable initiale], après la date de disponibilité d'une version stable de remplacement. Cela signifie que le support sera probablement abandonné dans Linux 2.6 ou 2.8. 9. Mélanger le NAT et le Filtrage de Paquets Il est courant de vouloir faire de la Traduction d'Adresses Réseaux ou NAT (voir le Guide Pratique du NAT) et du filtrage de paquets. La bonne nouvelle est qu'ils se mélangent extrêmement bien. Configurez complètement votre filtrage de paquets en ignorant le NAT que vous réalisez. Les adresses sources et destinations vues par le filtre à paquets seront les adresses `réelles'. Par exemple, si vous effectuez du DNAT pour envoyer toutes les connexions en direction du port 80 de l'adresse 1.2.3.4, vers le port 8080 de l'adresse 10.1.1.1, le filtre verra les paquets se dirigeant sur le port 8080 de 10.1.1.1 (la destination réelle), et non le port 80 de 1.2.3.4. De la même manière, vous pouvez ignorer le camouflage d'adresses (`masquerading') : les paquets sembleront venir de leurs adresses IP internes réelles (disons 10.1.1.1) et les réponses sembleront retourner là-bas. Vous pouvez utiliser l'extension de correspondance d'état (`state') sans imposer de travail supplémentaire au filtre à paquets, puisque le NAT requiert de toute façon le traçage de connexions. Pour enrichir l'exemple élémentaire sur le camouflage d'adresses dans le Guide Pratique du NAT (rejetant toute nouvelle connexion issue de l'interface ppp0), vous pourriez faire ceci : # Camoufler ppp0 iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE # Rejeter les paquets d'états NEW et INVALID venant de ou réexpédiés par ppp0 iptables -A INPUT -i ppp0 -m state --state NEW,INVALID -j DROP iptables -A FORWARD -i ppp0 -m state --state NEW,INVALID -j DROP # Activer la réexpedition d'adresse IP (`forwarding') echo 1 > /proc/sys/net/ipv4/ip_forward 10. Différences Entre Iptables et Ipchains · Premièrement, les noms des chaînes pré-définies ont changé, passant de minuscules en MAJUSCULES, parce que les chaînes INPUT et OUTPUT récupèrent maintenant seulement les paquets à destination locale et générés en local. Auparavant, elles voyaient respectivement tous les paquets entrants et sortants. · Le fanion `-i' identifie maintenant l'interface d'entrée, et fonctionne seulement dans les chaînes INPUT et FORWARD. Les règles dans les chaînes FORWARD ou OUTPUT qui utilisaient `-i' doivent être changées en `-o'. · Les ports TCP et UDP sont maintenant explicités avec les options --source-port ou --sport (ou --destination-port/--dport), et doivent être placés après les options `-p tcp' ou `-p udp', puisqu'ils concernent respectivement les extensions TCP ou UDP. · Le fanion TCP `-y' est maintenant devenu `--syn', et doit être placé après `-p tcp'. · La cible `DENY' est dorénavant appelée `DROP', finalement. · Réinitialiser une chaîne en la listant fonctionne. · Réinitialiser les chaînes pré-définies réinitialise aussi les compteurs du comportement par défaut. · Lister les chaînes vous renvoie une vue instantanée des compteurs. · REJECT et LOG sont maintenant des cibles étendues, autrement dit, ce sont des modules du noyau distincts. · Les noms de chaînes peuvent aller jusqu'à 31 caractères. · MASQ est à présent devenu MASQUERADE et utilise une syntaxe différente. REDIRECT, tout en gardant le même nom, a aussi subi un changement de syntaxe. Voir le Guide Pratique du NAT pour plus d'informations sur leur configuration. · L'option `-o' n'est plus utilisée pour diriger les paquets vers l'espace utilisateur (voir `-i' ci-dessus). Les paquets sont maintenant envoyés dans l'espace utilisateur via la cible QUEUE. · Probablement un tas d'autres choses que j'ai oublié. 11. Quelques Conseils sur la Conception d'un Filtre à Paquets Dans l'univers de la sécurité informatique, la sagesse élémentaire suggère de tout fermer puis de créer des ouvertures quand c'est nécessaire. On l'exprime habituellement ainsi : `tout ce qui n'est pas explicitement autorisé est interdit'. Je vous recommande cette approche si la sécurité est votre souci majeur. Ne faites pas tourner de services dont vous n'avez pas besoin, même si vous pensez avoir bloqué l'accès vers ceux-ci. Si vous créez un pare-feu dédié, commencez par ne rien faire tourner et bloquer tous les paquets. Ensuite, ajoutez les services et laissez passer les paquets quand c'est nécessaire. Je suis partisan de la sécurité en profondeur : associez les enveloppeurs de paquets ou `tcp-wrappers' (pour les connexions au filtre à paquets lui-même), les mandataires ou `proxies' (pour les connexions traversant le filtre à paquets), la vérification de route et le filtrage de paquets. La vérification de route intervient quand un paquet issu d'une interface inattendue est détruit : par exemple, si votre réseau interne contient des adresses du genre 10.1.1.0/24, et qu'un paquet avec cette adresse source vient sur votre interface externe, il sera détruit. On peut activer ce mode pour une interface (comme ppp0) avec : # echo 1 > /proc/sys/net/ipv4/conf/ppp0/rp_filter # Ou pour toutes les interfaces présentes et futures avec : # for f in /proc/sys/net/ipv4/conf/*/rp_filter; do # echo 1 > $f # done # La distribution Debian fait cela par défaut quand c'est possible. Si vous utilisez un routage asymétrique (c'est-à-dire que vous attendez des paquets venant de directions étranges), vous souhaiterez sûrement désactiver ce filtrage sur ces interfaces. La journalisation est utile quand vous réalisez un pare-feu, surtout si quelque-chose ne marche pas. Mais sur un pare-feu de production, associez-le toujours avec la correspondance de type `limit', pour empêcher que quelqu'un ne sature vos journaux. Je recommande fortement le traçage de connexions sur les systèmes sécurisés : il introduit un peu plus de charge, comme toutes les connexions sont suivies, mais il est très utile pour contrôler l'accès à vos réseaux. Vous devrez charger le module `ip_conntrack.o' si votre noyau ne charge pas automatiquement les modules et s'il n'est pas déjà compilé dans le noyau. Si vous voulez tracer précisément des protocoles complexes, vous devrez charger le module d'assistance approprié (par exemple `ip_conntrack_ftp.o'). # iptables -N no-conns-from-ppp0 # iptables -A no-conns-from-ppp0 -m state --state ESTABLISHED,RELATED -j ACCEPT # iptables -A no-conns-from-ppp0 -m state --state NEW -i ! ppp0 -j ACCEPT # iptables -A no-conns-from-ppp0 -i ppp0 -m limit -j LOG --log-prefix "Bad packet from ppp0:" # iptables -A no-conns-from-ppp0 -i ! ppp0 -m limit -j LOG --log-prefix "Bad packet not from ppp0:" # iptables -A no-conns-from-ppp0 -j DROP # iptables -A INPUT -j no-conns-from-ppp0 # iptables -A FORWARD -j no-conns-from-ppp0 Construire un bon pare-feu est au-delà du sujet de ce Guide Pratique, mais suivez mon conseil, soyez toujours minimaliste. Consultez le Guide Pratique de la Sécurité pour avoir plus d'informations sur la manière de tester et sonder votre machine. 12. Commentaires et Corrections Merci de faire parvenir en anglais à l'auteur vos questions et commentaires relatifs à la version originale de ce document à l'adresse netfilter@lists.samba.org. N'hésitez pas à faire parvenir tout commentaire relatif à la version française de ce document à commentaires CHEZ traduc POINT org en précisant le titre et la version de ce document.