• Aucun résultat trouvé

Chapitre suivant

Dans le document Iptables Tutorial 1.2.2 (Page 62-0)

7. La machine d'état

7.10. Chapitre suivant

Dans le prochain chapitre nous verrons comment sauvegarder et restaurer les tables de règles en utilisant les programmes iptables-save et iptables-restore distribués avec les applications iptables.

CHAPITRE 8

Sauvegarde et restauration des tables de règles importantes

Le paquetage iptables est fourni avec deux outils très utiles, spécialement si vous utilisez des tables de règles importantes. Ces deux outils sont appelés iptables-save et iptables-restore et sont utilisés pour la sauvegarde et la restauration des tables de règles dans un format spécifique qui semble un peu différent du code shell standard que nous avons vu dans ce didacticiel.

Astuce

iptables-restore peut être utilisé en conjonction avec des langages de script. Le gros problème est que vous devrez envoyer les résultats dans le stdin de iptables-restore. Si vous avez créé une très grosse table de règles (plusieurs milliers de règles) ce peut être une bonne idée, car il est plus rapide d'insérer toutes les nouvelles règles. Par exemple, vous pourrez exécuter make_rules.sh | iptables-restore.

8.1. Considérations de vitesse

Une des principales raisons d'utiliser iptables-save et iptables-restore est qu'elles améliorent la vitesse de chargement et de restauration des tables de règles importantes. Le problème principal lors du lancement de scripts shell contenant des règles iptables est que chaque invocation d'iptables dans le script extraira l'ensemble des règles de l'espace Netfilter du noyau, et après cela, inserrera les règles, ou toute autre action en réponse à la commande spécifique. Enfin, ajoutera les nouvelles règles issues de sa propre mémoire dans l'espace noyau. L'utilisation d'un script shell, créé pour chacune des règles que vous voulez insérer, prend plus de temps pour l'extraction et l'insertion de la table de règles.

Pour résoudre ce problème, il existe les commandes iptables-save et restore. La commande iptables-save est utilisée pour sauvegarder la table de règles dans un fichier texte au format spécial, et la commande iptables-restore est utilisée pour charger ce fichier à nouveau dans le noyau. Le plus intéressant de ces commandes est qu'elles chargent et sauvegardent la table de règles en une seule action. iptables-save récupérera la table de règles du noyau et la sauvegardera dans un fichier en une seule action. iptables-restore enverra la table de règles au noyau en une seule action pour chaque table. En d'autres termes, au lieu d'effacer la table de règles du noyau quelques 30 000 fois, ce qui arrive pour les tables de règles importantes, et ensuite la renvoyer au noyau, nous pouvons maintenant sauvegarder cet ensemble dans un fichier en une ou deux actions.

Comme vous pouvez le comprendre, ces outils sont définitivement faits pour vous si vous utilisez un vaste ensemble de règles. Cependant, elles ont des inconvénients, comme nous le verrons dans la section suivante.

8.2. Inconvénients avec restore

Comme vous avez pû vous en étonner, iptables-restore fonctionne-t-il avec toutes sortes de scripts ? De loin, non, il ne pourra probablement jamais le faire. C'est le principal défaut d' iptables-restore car il n'est pas capable de faire beaucoup de choses avec ces fichiers. Par exemple, si vous avez une connexion qui utilise une IP dynamique et que vous voulez récupérer cette IP à chaque démarrage de la machine et ensuite insérer cette valeur dans vos scripts ? Avec iptables-restore, c'est plus ou moins impossible.

Une possibilté pour faire ceci est de créer un petit script qui récupère les valeurs que vous voulez utiliser, ensuite faire un sed du fichier iptables-restore pour ces mots-clé spécifiques et les remplacer avec les valeurs collectées via le petit script. À ce point, vous pouvez les sauvegarder dans un fichier temporaire, et ensuite utiliser iptables-restore pour charger ces nouvelles valeurs. Ceci provoque cependant certains problèmes, et vous serez incapables de vous servir de iptables-save correctement car il effacera probablement vos mots-clé ajoutés à la main dans le script de restauration. C'est une solution maladroite.

Une autre solution est de charger les scripts iptables-restore en premier, et ensuite charger les scripts qui insèrent les règles plus dynamiques à leur place. Bien sûr, comme vous pouvez le comprendre, c'est juste une reprise maladroite de la première solution. iptables-restore n'est tout simplement pas très bien adapté pour les configurations dans lesquelles les adresses IP sont assignées dynamiquement.

Un autre inconvénient avec iptables-restore et iptables-save est qu'il ne sont pas aussi complètement fonctionnels que si vous faites un script. Le problème est simplement que pas beaucoup de personnes l'utilisent et donc qu'il n'y a pas énormément de rapports de bugs. Même si ces problèmes existent, je vous recommande fortement d'utiliser ces outils qui fonctionnent très bien pour la plupart des tables de règles tant qu'elles ne contiennent pas certains nouveaux modules ou cibles qu'ils ne savent pas gérer correctement.

8.3. iptables-save

La commande iptables-save est, comme nous l'avons déjà expliqué, un outil pour sauvegarder dans la table de règles un fichier que iptables-restore peut utiliser. Cette commande est tout à fait simple, et prend seulement deux arguments. Regardons l'exemple suivant pour comprendre la syntaxe :

iptables-save [-c] [-t table]

Sauvegarde et restauration des tables de règles importantes

L'argument -c indique à iptables-save de conserver les valeurs spécifiées dans les compteurs de bits et de paquets. Ce qui pourrait être utile si vous voulez redémarrer votre pare-feu principal, mais sans perdre les compteurs de bits et de paquets que nous pourrions utiliser dans un but de statistiques. Exécuter une commande iptables-save avec l'argument -c nous permet de redémarrer sans briser les routines de statistique et de comptage. La valeur par défaut est, bien sûr, de ne pas garder les compteurs intacts quand cette commande est exécutée.

L'argument -t indique à la commande iptables-save quelle table sauvegarder. Sans cet argument toutes les tables disponibles dans le fichier seront automatiquement sauvegardées. Ci-dessous, un exemple de ce que donne une commande iptables-save sans avoir chargé de table de règles.

# Generated by iptables-save v1.2.6a on Wed Apr 24 10:19:17 2002

*filter

:INPUT ACCEPT [404:19766]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [530:43376]

COMMIT

# Completed on Wed Apr 24 10:19:17 2002

# Generated by iptables-save v1.2.6a on Wed Apr 24 10:19:17 2002

*mangle

# Completed on Wed Apr 24 10:19:17 2002

# Generated by iptables-save v1.2.6a on Wed Apr 24 10:19:17 2002

*nat:PREROUTING ACCEPT [0:0]

:POSTROUTING ACCEPT [3:450]

:OUTPUT ACCEPT [3:450]

COMMIT

# Completed on Wed Apr 24 10:19:17 2002

Les commentaires débutent avec la signe #. Chaque table est marquée par *<table-name>, par exemple,

*mangle. Dans chaque table nous avons les spécifications de chaînes et les règles. Une spécification de chaîne ressemble à : <chain-name> <chain-policy> [<packet-counter>:<byte-counter>]. Le chain-name peut être, par exemple, PREROUTING, la règle d'action est décrite avant et peut être, par exemple, ACCEPT. Enfin les compteurs d'octets et de paquets sont les mêmes que dans la sortie de la commande iptables -L -v. Chaque déclaration de table se termine avec un mot-clé COMMIT. Le mot-clé COMMIT indique qu'à ce niveau toutes les règles seront envoyées au noyau par l'opérateur de transfert de données.

L'exemple ci-dessus est tout à fait basique, et je crois qu'il est approprié de montrer un bref exemple qui contient un petit Iptables-save ruleset. Si nous voulons lancer iptables-save sur celui-ci, la sortie de la commande sera :

# Generated by iptables-save v1.2.6a on Wed Apr 24 10:19:55 2002

*filter

:INPUT DROP [1:229]

:FORWARD DROP [0:0]

:OUTPUT DROP [0:0]

-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

-A FORWARD -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT -A FORWARD -i eth1 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT -A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT

COMMIT

# Completed on Wed Apr 24 10:19:55 2002

# Generated by iptables-save v1.2.6a on Wed Apr 24 10:19:55 2002

*mangle

# Completed on Wed Apr 24 10:19:55 2002

# Generated by iptables-save v1.2.6a on Wed Apr 24 10:19:55 2002

*nat:PREROUTING ACCEPT [1:229]

:POSTROUTING ACCEPT [3:450]

:OUTPUT ACCEPT [3:450]

-A POSTROUTING -o eth0 -j SNAT --to-source 195.233.192.1 COMMIT

# Completed on Wed Apr 24 10:19:55 2002

Comme on peut le voir, chaque commande a été préfixée avec les compteurs d'octets et de paquets car nous avons utilisé l'argument -c. Excepté pour ceci, la ligne de commande est tout à fait identique au script. Le seul problème, est de savoir comment sauvegarder la sortie dans un fichier. Vraiment simple, et vous devriez savoir le faire si vous avez utilisé Linux auparavant. Il suffit d'utiliser un "pipe" (canal de communication) pour enregistrer la sortie de la commande dans le fichier. Ça ressemblera à cela :

iptables-save -c > /etc/iptables-save

La commande ci-dessus fera une sauvegarde de toute la table de règles appelée /etc/iptables-save avec les compteurs d'octets et de paquets toujours intacts.

Sauvegarde et restauration des tables de règles importantes

8.4. iptables-restore

La commande iptables-restore est exécutée pour restaurer la table de règles de iptables qui a été sauvegardée par la commande iptables-save. Elle prend toutes les entrées standard mais ne peut faire de restauration depuis un fichier de règles écrit à la main (script), malheureusement. La syntaxe de cette commande :

iptables-restore [-c] [-n]

L'argument -c restaure les compteurs d'octets et de paquets et doit être utilisé si vous voulez garder les compteurs précédemment enregistrés avec iptables-save. Cet argument peut aussi s'écrire avec sa forme de nom long --counters.

L'argument -n indique à iptables-restore de ne pas écraser les règles précédemment écrites dans la table, ou les tables. Le comportement par défaut de iptables-restore est d'effacer et supprimer toutes les règles inscrites auparavant. L'argument court -n peut être remplacé par son format long --noflush.

Pour charger une table de règles avec la commande iptables-restore, il existe plusieurs solutions, mais nous ne verrons que la plus simple et la plus commune :

cat /etc/iptables-save | iptables-restore -c

Ceci fonctionnera également :

iptables-restore -c < /etc/iptables-save

Ceci concaténera la table de règles située dans le fichier /etc/iptables-save et ensuite l'enverra vers iptables-restore qui récupérera cette table de règles sur l'entrée standard et la restaurera, en incluant les compteurs d'octets et de paquets. Cette commande peut varier à l'infini et nous pourrions montrer les diverses possibilités de "piping", cependant, c'est un peu hors du sujet de ce chapitre, et nous laisserons ceci comme exercice pour le lecteur.

La table de règles devrait maintenant être chargée correctement dans le noyau et fonctionnelle. Sinon, vous avez peut être fait une erreur dans ces commandes.

8.5. Prochain chapitre

Le prochain chapitre sera consacré à la syntaxe des règles iptables et comment écrire proprement des tables de règles. Il montrera également certains styles de codage de base.

CHAPITRE 9

Création d'une règle

Ce chapitre présentera en détail comment créer vos propres règles. Une règle peut être décrite comme une directive au pare-feu et donc, son comportement au niveau du blocage ou de de l'autorisation des différentes connexions et paquets dans une chaîne spécifique. Chaque ligne que vous écrirez est insérée dans une chaîne qui sera considérée comme une règle. Nous verrons également les modules de base disponibles, comment les utiliser, de même que les diverses cibles et la façon de créer de nouvelles cibles (i.e., nouvelles sous-chaînes).

Ce chapitre montrera les lignes de base, comment une règle est créée, comment vous devrez l'écrire de façon à ce qu'elle soit acceptée par le programme domaine utilisateur de iptables, les différentes tables, de même que les commandes à exécuter. Après ça nous verrons dans le chapitre suivant tous les modules disponibles pour iptables, et en détail chaque type de cible et de saut.

9.1. Bases de la commande iptables

Comme ceci a déjà été evoqué, chaque règle est une ligne lue par le noyau pour en déduire ce qu'il convient de faire d'un paquet. Si tous les critères - ou les correspondances - sont remplis, on exécute l'instruction donnée par la cible - ou le saut. Normalement, on écrit les règles dans une syntaxe qui ressemble à celle-ci :

iptables [-t table] commande [correspondance] [cible/saut]

Rien ne vous oblige à mettre l'instruction de cible en fin de la ligne. Toutefois, vous devriez préférer cette syntaxe qui améliore la lisibilité. En tout cas, la plupart des règles que vous découvrirez sont écrites de cette façon. Ainsi, si vous lisez le script de quelqu'un d'autre, vous reconnaitrez très probablement la syntaxe et comprendrez plus facilement la règle.

Si vous voulez utiliser une autre table que la table standard, insérer la spécification de table à la place de la mention [table]. Cependant, il n'est pas indispensable de déclarer explicitement la table à utiliser, puisqu'iptables utilise par défaut la table filter sur laquelle sont implémentées toutes les commandes. Vous n'êtes pas non plus obligé de spécifier la table à cet endroit dans la règle. Elle peut tout aussi bien être placée ailleurs dans la ligne. Malgré tout, il est plus ou moins habituel de placer la spécification de table au début.

Il y a une chose qu'il faut garder à l'esprit : la commande devrait toujours être en première position, ou à la rigueur juste après la spécification de table. La "commande" indique au programme ce qu'il doit faire, par exemple insérer une règle, ajouter une règle en fin de chaîne, ou encore supprimer une règle. Tout ceci est approfondi ultérieurement.

La correspondance est la partie de la règle qui est envoyée au noyau pour identifier la caractéristique particulière du paquet, c'est-à-dire ce qui le distingue de tous les autres paquets. On peut donc spécifier l'adresse IP dont provient le paquet, de quelle interface réseau, l'adresse IP à atteindre, un port, un protocole ou quoi que ce soit d'autre. Il existe un éventail de correspondances que l'on peut utiliser et qui seront développées au cours de ce chapitre.

Enfin, on trouve la cible du paquet. Si toutes les correspondances sont satisfaites pour un paquet, on informe le noyau de l'action à accomplir. Par exemple, vous pouvez stipuler au noyau d'envoyer le paquet à une autre chaîne créée par vous-même, et qui appartient à cette table. Vous pouvez aussi notifier au noyau de supprimer le paquet et de ne faire aucun autre traitement, ou encore d'envoyer une réponse particulière à l'expéditeur.

Comme pour les autres aspects de cette section, la cible est analysée en profondeur plus loin dans ce chapitre.

9.2. Les tables

L'option -t précise la table à utiliser. Par défaut, il s'agit de la table filter. On peut spécifier une des tables suivantes avec l'option -t. Remarquez que c'est une présentation extrêmement rapide du contenu du chapitre Traversée des tables et des chaînes.

Tableau 9.1. Tables

Table Explication

nat La table nat sert principalement à faire de la traduction d'adresse réseau. Les paquets soumis au NAT voient leur adresse modifiée, en accord avec les règles concernées.

Les paquets d'un flux ne traversent cette table qu'une seule fois. En effet, le sort du premier paquet d'un flux conditionne celui des autres. Si le premier paquet est accepté, les autres paquets du flux sont soumis automatiquement au NAT (ou au camouflage, etc.), donc subissent les mêmes actions que le premier paquet. Par conséquent, ils ne passeront pas par cette table, mais seront néanmoins traités de la même façon que le premier paquet du flux. C'est pour cette raison qu'on déconseille le filtrage dans cette table. La chaîne PREROUTING permet de modifier les paquets dès qu'ils entrent dans le pare-feu. La chaîne OUTPUT permet de modifier les paquets générés localement (c-à-d. dans le pare-feu) avant qu'ils n'accèdent à la décision de routage. En dernier lieu, la chaîne POSTROUTING offre la possibilité de modifier les paquets juste avant qu'ils ne quittent le pare-feu.

mangle Cette table sert à transformer les paquets. Entre autres, on peut modifier le contenu de differents paquets et celui de leurs en-têtes. Par exemple, on peut changer les champs TTL, TOS ou MARK. Notez que le champ MARK n'est pas à proprement parlé un changement sur le paquet, mais une valeur de marquage définie dans l'espace du noyau.

Création d'une règle

Table Explication

D'autres règles ou programmes peuvent s'appuyer sur ce marquage à l'intérieur du pare-feu pour filtrer ou opérer un routage évolué, tc en est un exemple. Cette table est constituée de cinq chaînes pré-définies, qui sont nommées PREROUTING, POSTROUTING, OUTPUT,

INPUT et FORWARD. La chaîne PREROUTING permet de modifier les paquets juste quand ils entrent dans le pare-feu mais avant qu'ils n'atteignent la décision de routage. La chaîne

POSTROUTING permet de modifier les paquets juste après toutes les décisions de routage.

La chaîne OUTPUT s'utilise pour transformer les paquets générés localement avant qu'ils ne sollicitent la décision de routage. La chaîne INPUT permet de modifier les paquets une fois qu'ils ont été routés vers la machine locale, mais avant que l'application de l'espace utilisateur n'ait réceptionné les données. La chaîne FORWARD permet de modifier les paquets après la première décision de routage mais avant la dernière. Notez que la table mangle ne peut en aucun cas servir à une forme de traduction d'adresse réseau ou de

camouflage, la table nat a été conçue pour ce genre d'opérations.

filter La table filter devrait être exclusivement consacrée à filtrer les paquets. Par exemple, elle permet de détruire (DROP), journaliser (LOG), accepter (ACCEPT) ou rejeter (REJECT) des paquets sans aucun problème, de la même manière que dans les autres tables. Cette table est constituée de trois chaînes pré-définies. La première se nomme

FORWARD et s'applique à tous les paquets qui ne sont ni générés localement, ni destinés à l'hôte local (c-à-d. le pare-feu). La chaîne INPUT s'applique à tous les paquets destinés à l'hôte local (le pare-feu), et au final, OUTPUT s'applique à tous les paquets générés localement.

raw La table raw et ses chaînes sont utilisées avant tout autre table dans Netfilter. Elle fût introduite pour utiliser la cible NOTRACK. Cette table est plutôt récente et seulement disponible, si compilée, avec les derniers noyaux 2.6. La table raw contient deux chaînes.

Les chaînes PREROUTING et OUTPUT, qui modifient les paquets avant qu'ils atteignent les autres sous-systèmes de Netfilter. La chaîne PREROUTING peut être utilisée pour tous les paquets entrants sur la machine, ou qui sont transférés (forward), tandis que la chaîne OUTPUT peut être utilisée pour modifier les paquets générés localement avant qu'ils atteignent les autres sous-systèmes de Netfilter.

Les explications précédentes devraient avoir fourni des notions fondamentales concernant les trois tables disponibles. Celles-ci s'emploient dans des situations complètement différentes, et vous devez maîtriser l'utilisation des différentes chaînes qui composent ces tables. Si vous ne comprenez pas leur utilisation, vous pourriez créer une faille dans votre pare-feu, dans laquelle quelqu'un peut s'engouffrer et vous nuire s'il la découvre. Les tables et chaînes indispensables ont déjà été présentées en détails dans le chapitre Traversée des tables et des chaînes. Si vous ne l'avez pas parfaitement assimilé, je vous conseille de vous y replonger.

Les explications précédentes devraient avoir fourni des notions fondamentales concernant les trois tables disponibles. Celles-ci s'emploient dans des situations complètement différentes, et vous devez maîtriser l'utilisation des différentes chaînes qui composent ces tables. Si vous ne comprenez pas leur utilisation, vous pourriez créer une faille dans votre pare-feu, dans laquelle quelqu'un peut s'engouffrer et vous nuire s'il la découvre. Les tables et chaînes indispensables ont déjà été présentées en détails dans le chapitre Traversée des tables et des chaînes. Si vous ne l'avez pas parfaitement assimilé, je vous conseille de vous y replonger.

Dans le document Iptables Tutorial 1.2.2 (Page 62-0)