Source de cours/iptables.php
<?
require ("../page.inc");
require ("lessons.inc");
$currentPage = new LessonPage("iptables");
$currentPage->setContent('');
$currentPage->addChapter('general', 'Généralités', '
<p>
Depuis la version 2.4, Linux contient un module destiné au filtrage réseau, <strong>Netfilter</strong>. Il se configure au moyen d\'un outil appelé <strong>iptables</strong>.
</p>
<p>
Le filtrage réseau consiste en l\'examen des paquets réseaux et à prendre des décisions sur le traitement à leur appliquer. C\'est ce que fait un <strong>pare-feu</strong> ou, en anglais, <strong>firewall</strong>. Avec un système <acronym xml:lang="en" lang="en" title="GNU\'s Not Unix">GNU</acronym>/Linux, pour configurer des règles de pare-feu, il faudra donc simplement utiliser Netfilter à l\'aide d\'iptables.
</p>
<p>
Cet article s\'interesse uniquement au filtrage réseau <acronym xml:lang="en" lang="en" title="Internet Protocol Version 4">IPV4</acronym> (qui est probablement celui que vous utilisez si cela ne vous évoque rien). Cela est possible pour d\'autres protocoles et les principes exposés ici resteront pour la plupart valides.
</p>
');
$currentPage->addChapter('presentation', 'Présentation de Netfilter', '
<p>
Netfilter travaille sur des paquets réseaux. Il s\'agit de parties des informations transmises. Pour, par exemple, télécharger un fichier, celui-ci est découpé en plusieurs paquets avant de transiter sur le réseau. Chacun de ces paquets comporte en plus des données, des informations ajoutées par les couches réseaux. Ce sont sur ces informations que s\'effectueront les tests de filtrage.
</p><p>
La couche réseau Linux présente plusieurs <strong>points d\'accès</strong> (en anglais <strong>hook</strong>). Netfilter dispose de <strong>fonctions de rappel</strong> (<strong>callback</strong>). Celles-ci sont des suites d\'instructions qui précisent ce qui doit être fait lorsque survient un événement.
</p><p>
Concrètement, lorsqu\'un paquet réseau atteint un de ces points d\'accès, il est passé à Netfilter par l\'intermédiaire de sa fonction de rappel. Il est alors examiné pour prendre une décision concernant son traitement futur.
</p><p>
Netfilter se comporte comme un automate qui compare le paquet successivement à plusieurs règles. Et selon le résultat du test, le paquet est traité ou transmis au test suivant.
</p>
');
$currentPage->addChapter('tables', 'Les tables, chaînes et cibles', '
<p>
Aux points d\'accès sont associées des <strong>chaînes</strong> de traitement. C\'est dans celles-ci que sont effectués les tests. Elles sont regroupées par <strong>tables</strong> selon le type de traitement.
</p><p>
Les tables sont ajoutées par des modules. Il en existe 3 principales pouvant être utilisées. Voici ci-après leurs noms et la tâche à laquelle elles sont destinées.
</p>
<div class="lesson-spacer">
<table class="lesson" summary="Description des tables principales de Netfilter avec leur rôle">
<caption>Tables principales de Netfilter</caption>
<tr>
<th scope="col" abbr="Table">Table</th><th scope="col" abbr="Description">Description</th>
</tr>
<tr>
<td class="lesson-spacing"></td><td class="lesson-spacing"></td>
</tr>
<tr>
<td><strong>filter</strong></td><td>Cette table permet de filtrer les paquets. Typiquement ce sera pour les accepter ou non.</td>
</tr>
<tr>
<td><strong>nat</strong></td><td>Avec cette table, on peut réaliser des translations d\'adresse (ou de ports). Ceci sera notamment utile pour <a href="partage_connexion.php">partager une connexion</a>.</td>
</tr>
<tr>
<td><strong>mangle</strong></td><td>Elle sert pour modifier les en-têtes des paquets. On la rencontrera parfois pour marquer des paquets afin que d\'autres applications puissent les reconnaître.</td>
</tr>
</table>
</div>
<p>
A l\'intérieur d\'une table, on peut trouver plusieurs chaînes. Ce sont elles qui contiendront les <strong>règles</strong> à appliquer aux paquets. Ces règles seront évaluées séquentiellement. On trouve deux types de chaînes.
</p><p>
Tout d\'abord celles qui sont associées aux différents points d\'entrées existants. Un paquet atteignant un de ces points sera envoyé vers la chaîne associée. Ce sont les fonctions de rappel evoquées précédemment qui réalisent cela. Elles effectuent les uns après les autres les tests que contient la chaîne. Ces chaînes sont en nombre fini et ne sont pertinentes que pour certaines tables. Le tableau suivant les liste, en indiquant quelle table a une chaîne de ce type.
</p>
<div class="lesson-spacer">
<table class="lesson" summary="Description des chaînes Netfilter indiquant les tables les contenant">
<caption>Chaînes de Netfilter</caption>
<tr>
<th scope="col" abbr="Chaîne">Chaîne</th><th scope="col" abbr="Table">Table</th><th scope="col" abbr="Description">Description</th>
</tr>
<tr>
<td class="lesson-spacing"></td><td class="lesson-spacing"></td><td class="lesson-spacing"></td>
</tr>
<tr>
<td><strong>PREROUTING</strong></td><td>nat, mangle</td><td>Par cette chaîne passeront les paquets entrant dans la machine avant routage.</td>
</tr>
<tr>
<td><strong>INPUT</strong></td><td>filter</td><td>Cette chaîne traitera les paquets entrants avant qu\'ils ne soient passées aux couches supérieures (les applications).</td>
</tr>
<tr>
<td><strong>FORWARD</strong></td><td>filter</td><td>Ce sont les paquets uniquement transmis par la machine sans que les applications n\'en aient connaissance.</td>
</tr>
<tr>
<td><strong>OUTPUT</strong></td><td>filter, nat, mangle</td><td>Cette chaîne sera appelée pour des paquets envoyés par des programmes présents sur la machine.</td>
</tr>
<tr>
<td><strong>POSTROUTING</strong></td><td>nat</td><td>Les paquets prêts à être envoyés (soit transmis, soit générés) seront pris en charge par cette chaîne.</td>
</tr>
</table>
</div>
<p>
On trouve aussi des chaînes utilisateurs. Elles peuvent librement être créées mais ne seront pas associées à un point d\'accès. En fait on ne pourra rentrer dans une de ces chaînes que si une règle d\'une des chaînes existantes dirige le paquet vers celle-ci.
</p><p>
Enfin, le dernier élément important est la notion de <strong>cible</strong>. Il s\'agit du traitement que l\'on décide d\'appliquer au paquet. C\'est la cible qui se chargera de faire les opérations nécessaires. En plus de celles prédéfinies, il est possible d\'indiquer comme cible une chaîne utilisateur. Cela permet d\'imbriquer différents tests et traitements.
</p><p>
Chaque chaîne peut être vue comme un ensemble de tests, chacun ayant pour résultat l\'envoi du paquet vers la cible spécifiée si la condition est vérifiée. Si ce n\'est pas le cas, on passe à la suivante. En arrivant à la fin d\'une des chaînes du tableau précédent, une cible par défaut est utilisée. A la fin d\'une chaîne utilisateur, si aucune décision n\'a été prise, on revient à la chaîne appelante.
</p><p>
Voici les cibles prédéfinies les plus courantes :
</p>
<div class="lesson-spacer">
<table class="lesson" summary="Descriptions des cibles prédéfinies permettant de connaître leur utilité">
<caption>Cibles prédéfinies</caption>
<tr>
<th scope="col" abbr="Cible">Cible</th><th scope="col" abbr="Description">Description</th>
</tr>
<tr>
<td class="lesson-spacing"></td><td class="lesson-spacing"></td>
</tr>
<tr>
<td><strong>ACCEPT</strong></td><td>Les paquets envoyés vers cette cible seront tout simplement acceptés et pourront poursuivre leur cheminement au travers des couches réseaux.</td>
</tr>
<tr>
<td><strong>DROP</strong></td><td>Cette cible permet de jeter des paquets qui seront donc ignorés.</td>
</tr>
<tr>
<td><strong>REJECT</strong></td><td>Permet d\'envoyer une réponse à l\'émetteur pour lui signaler que son paquet a été refusé.</td>
</tr>
<tr>
<td><strong>LOG</strong></td><td>Demande au noyau d\'enregistrer des informations sur le paquet courant. Cela se fera généralement dans le fichier /var/log/messages (selon la configuration du programme syslogd).</td>
</tr>
<tr>
<td><strong>MASQUERADE</strong></td><td>Cible valable uniquement dans la chaîne POSTROUTING de la table nat. Elle change l\'adresse <acronym xml:lang="en" lang="en" title="Internet Protocol">IP</acronym> de l\'émetteur par celle courante de la machine pour l\'interface spécifiée. Cela permet de masquer des machines et de faire par exemple du partage de connexion.</td>
</tr>
<tr>
<td><strong>SNAT</strong></td><td>Egalement valable pour la chaîne POSTROUTING de la table nat seulement. Elle modifie aussi la valeur de l\'adresse IP de l\'émetteur en la remplaçant par la valeur fixe spécifiée.</td>
</tr>
<tr>
<td><strong>DNAT</strong></td><td>Valable uniquement pour les chaînes PREROUTING et OUTPUT de la table nat. Elle modifie la valeur de l\'adresse IP du destinataire en la remplaçant par la valeur fixe spécifiée.</td>
</tr>
<tr>
<td><strong>RETURN</strong></td><td>Utile dans les chaînes utilisateurs. Cette cible permet de revenir à la chaîne appelante. Si RETURN est utilisé dans une des chaînes de base précédente, cela est équivalent à l\'utilisation de sa cible par défaut.</td>
</tr>
</table>
</div>
');
$currentPage->addChapter('iptables', 'Présentation d\'iptables', '
<p>
<strong>iptables</strong> est l\'outil qui est fourni à l\'administateur pour agir sur tous les concepts vus précédemment et pour modifier les règles de filtrage donc.
</p><p>
La première option à connaître est <strong>-t</strong> qui permet de spécifier le nom de la table sur laquelle porteront les autres paramètres. Si cette option n\'est pas spécifiée, ce sera par défaut la table filter.
</p><p>
On peut aussi demander à iptables de charger un module particulier avec l\'option <strong>-m</strong>. Ce module peut ajouter de nouvelles tables ou de nouvelles manières de tester les paquets.
</p><p>
Il faut ensuite indiquer une commande pour indiquer par exemple qu\'une nouvelle règle doit être ajoutée dans la chaîne spécifiée. Ci-après la liste des options les plus courantes pour spécifier une commande. Une seule à la fois peut être présente, et toutes devront être suivies du nom de la chaîne à prendre en compte.
</p>
<div class="lesson-spacer">
<table class="lesson" summary="Options les plus fréquemment utilisées avec iptables et leur description">
<caption>Options d\'iptables</caption>
<tr>
<th scope="col" abbr="Option">Option</th><th scope="col" abbr="Rôle">Rôle</th>
</tr>
<tr>
<td class="lesson-spacing"></td><td class="lesson-spacing"></td>
</tr>
<tr>
<td><strong>-L</strong></td><td>Affiche toutes les règles de la chaîne indiquée.</td>
</tr>
<tr>
<td><strong>-F</strong></td><td>Supprime toutes les règles de la chaîne. Si aucune chaîne n\'est spécifiée, toutes celles de la table sont vidées.</td>
</tr>
<tr>
<td><strong>-N</strong></td><td>Crée une nouvelle chaîne utilisateur avec le nom passé en paramètre.</td>
</tr>
<tr>
<td><strong>-X</strong></td><td>Supprime la chaîne utilisateur. Si aucun nom n\'est spécifié, toutes les chaînes utilisateur seront supprimées</td>
</tr>
<tr>
<td><strong>-P</strong></td><td>Modifie la politique par défaut de la chaîne. Il faut indiquer en plus comme paramètre la cible à utiliser.</td>
</tr>
<tr>
<td><strong>-A</strong></td><td>Ajoute une règle à la fin de la chaîne spécifiée.</td>
</tr>
<tr>
<td><strong>-I</strong></td><td>Insère la règle avant celle indiquée. Cette place est précisée par un numéro qui fait suite au nom de la chaîne. La première porte le numéro 1. Si aucun numéro n\'est indiqué, la règle est insérée au début.</td>
</tr>
<tr>
<td><strong>-D</strong></td><td>Supprime une règle de la chaîne. Soit un numéro peut être précisé, soit la définition de la chaîne à supprimer (ses tests de concordance et sa cible).</td>
</tr>
</table>
</div>
<p>
Quelques <a href="#examples">exemples</a> montreront l\'utilisation de ces options.
</p>
');
$currentPage->addChapter('tests', 'Les tests de concordance et options de cible', '
<p>
Pour pouvoir créer des règles, il faut effectuer des <strong>tests de concordance</strong>. Ceux-ci définissent les caractéristiques que doivent présenter les paquets pour être concernés par la règle, et donc être dirigés vers la cible spécifiée.
</p><p>
Certains paramètres de tests ne sont valables que si d\'autres options sont précisées. Le tableau suivant, qui présente les plus utilisés de ces tests, indiquera donc le contexte d\'utilisation qui correspondra aux autres options nécessaires (avec leurs paramètres) s\'il y en a.
</p><p>
Plusieurs de ces paramètres existent en version longue ou abrégée, celle longue étant précédée de -- (deux tirets). Lorsqu\'une version courte existe, elle sera indiquée ci-dessous. L\'utilisation de l\'une ou de l\'autre est strictement équivalent.
</p>
<div class="lesson-spacer">
<table class="lesson" summary="Paramètres de test utilisés par les règles de concordance, leur version abrégée si elle existe et le contexte d\'utilisation">
<caption>Paramètres de test</caption>
<tr>
<th scope="col" abbr="Option">Option de test</th><th scope="col" abbr="Abrégé">Version abrégée</th><th scope="col" abbr="Contexte">Contexte</th><th scope="col" abbr="Description">Description</th>
</tr>
<tr>
<td class="lesson-spacing"></td><td class="lesson-spacing"></td><td class="lesson-spacing"></td><td class="lesson-spacing"></td>
</tr>
<tr>
<td><strong>--source</strong></td><td><strong>-s</strong></td><td></td><td>Adresse source. Cette option est suivie par l\'adresse de la machine qui doit avoir émis ce paquet. Celle-ci peut-être sous forme numérique, ou sous forme de nom de machine. Si l\'adresse est précédée d\'un ! (point d\'exclamation), le test est alors inversé et la condition sera donc remplie si l\'adresse de l\'émetteur ne correspond pas à celle spécifiée. On peut aussi à la suite de l\'adresse indiquer un masque de sous-réseau en séparant par un / (barre oblique) ces deux éléments.</td>
</tr>
<tr>
<td><strong>--destination</strong></td><td><strong>-d</strong></td><td></td><td>Adresse de destination. On trouve ensuite l\'adresse de destination du paquet, avec les mêmes possibilités que pour --source.</td>
</tr>
<tr>
<td><strong>--in-interface</strong></td><td><strong>-i</strong></td><td>Chaînes INPUT, FORWARD ou PREROUTING</td><td>Interface d\'entrée. Suivie par le nom de l\'interface par laquelle doivent arriver les paquets. Par exemple, ce sera ppp0 pour un modem, ou eth0 pour la première carte ethernet. Le nom de l\'interface peut être précédé d\'un ! (point d\'exclamation) pour inverser le test.</td>
</tr>
<tr>
<td><strong>--out-interface</strong></td><td><strong>-o</strong></td><td>Chaînes FORWARD, OUTPUT ou POSTROUTING</td><td>Interface de sortie. Suivi du même paramètre que pour l\'option --in-interface. Dans ce cas-là est testée l\'interface par laquelle vont être envoyés les paquets.</td>
</tr>
<tr>
<td><strong>--protocol</strong></td><td><strong>-p</strong></td><td></td><td>Protocole. Permet de vérifier le protocole du paquet. Les valeurs littérales pouvant être utilisées à la suite de cette option sont <acronym xml:lang="en" lang="en" title="Transmission Control Protocol">tcp</acronym>, <acronym xml:lang="en" lang="en" title="User Datagram Protocol">udp</acronym>, <acronym xml:lang="en" lang="en" title="Internet Control Message Protocol">icmp</acronym> ou <strong>all</strong> qui les regroupe toutes.</td>
</tr>
<tr>
<td><strong>--source-port</strong></td><td></td><td>--protocol tcp <i>ou</i> --protocol udp</td><td>Port source. Cette option permet de vérifier le port source (celui utilisé par l\'émetteur). Il est spécifié sous forme numérique ou par nom de service (comme <acronym xml:lang="en" lang="en" title="HyperText Transfer Protocol">http</acronym> ou <acronym xml:lang="en" lang="en" title="Simple Mail Transfer Protocol">smtp</acronym>). On peut aussi indiquer une plage de port en séparant les deux bornes par : (deux points). Par exemple 25:110 pour tous les ports compris entre 25 et 110. Pour exclure le ou les ports spécifiés, il faut utiliser un ! (point d\'exclamation) après --source-port.</td>
</tr>
<tr>
<td><strong>--destination-port</strong></td><td></td><td>--protocol tcp <i>ou</i> --protocol udp</td><td>Port destination. Compare le port utilisé pour se connecter sur la machine avec la valeur ou plage de valeur indiquée. Ces dernières sont indiquées comme pour --source-port.</td>
</tr>
<tr>
<td><strong>--state</strong></td><td></td><td>-m state</td><td>Etat du paquet. Une liste de plusieurs valeurs peut être indiquée en les séparant par des virgules. L\'état de ce paquet est comparé alors à ces valeurs. <strong>NEW</strong> correspond à un paquet initiant une nouvelle connexion. <strong>ESTABLISHED</strong> est un paquet participant à une conversation déjà établie. <strong>RELATED</strong> est pour un paquet qui ouvre une nouvelle connexion, mais ceci en rapport avec une précédente déjà établie. <strong>INVALID</strong> indique un paquet qui n\'est rattaché à aucune connexion.</td>
</tr>
</table>
</div>
<p>
Une fois spécifiés les critères auxquels doivent répondre les paquets, il faut indiquer vers quelle cible l\'envoyer s\'il y répond. Cela se fait avec l\'option <strong>--jump</strong> ou en abrégé <strong>-j</strong> suivie par le nom de la cible.
</p><p>
Certaines de ces cibles nécessitent des options pour les paramétrer. Elles sont indiquées sous la même forme que les options de tests. Ci-suivent les plus couramment utilisées.
</p>
<div class="lesson-spacer">
<table class="lesson" summary="Options utilisées par les cibles afin de parametrer leur fonctionnement">
<caption>Options des cibles</caption>
<tr>
<th scope="col" abbr="Paramètre">Paramètre</th><th scope="col" abbr="Cible">Cible</th><th scope="col" abbr="Description">Description</th>
</tr>
<tr>
<td class="lesson-spacing"></td><td class="lesson-spacing"></td><td class="lesson-spacing"></td>
</tr>
<tr>
<td><strong>--log-prefix</strong></td><td>LOG</td><td>Préfixe dans le journal. Cette option est suivie d\'une chaîne de moins de 30 caractères. Celle-ci est ajoutée devant les lignes qui sont inserées dans les fichiers journaux. Cela permet de plus facilement les retrouver par la suite.</td>
</tr>
<tr>
<td><strong>--reject-with</strong></td><td>REJECT</td><td>Message de rejet. Avec --reject-with, on peut indiquer quel type de message ICMP doit être envoyé vers la machine dont le paquet est rejeté. A la suite de l\'option, on peut trouver <strong>icmp-net-unreachable</strong> (réseau inaccessible), <strong>icmp-host-unreachable</strong> (machine inaccessible), <strong>icmp-port-unreachable</strong> (port inaccessible), <strong>icmp-proto-unreachable</strong> (protocole inaccessible), <strong>icmp-net-prohibited</strong> (réseau interdit) ou <strong>icmp-host-prohibited</strong> (machine interdite). Si le type de protocol est tcp, on peut aussi trouver <strong>tcp-reset</strong> qui indique qu\'il faudra envoyer un paquet RST qui permet de fermer une connexion.</td>
</tr>
<tr>
<td><strong>--to-source</strong></td><td>SNAT</td><td>Nouvelle adresse source. Permet d\'indiquer quelle adresse doit être mise en tant qu\'adresse source dans le paquet pour remplacer celle existante. On peut en indiquer une seule, ou une plage en séparant les bornes par un - (tiret). On peut aussi modifier le port avec cette option. Cela se fait en spécifiant un port (ou une plage de ports) en le séparant de l\'adresse par : (deux points).</td>
</tr>
<tr>
<td><strong>--to-destination</strong></td><td>DNAT</td><td>Nouvelle adresse destination. Utilisée pour modifier l\'adresse de destination en la remplaçant par celle indiquée à la suite de cette option. Le format du paramètre suivant --to-destination est le même que pour --to-source.</td>
</tr>
</table>
</div>
');
$currentPage->addChapter('examples', 'Exemples courants', '
<p>
Voici une suite de quelques exemples pouvant être utiles. Ils seront accompagnés d\'une explication sur leurs rôles. Vous pouvez aussi vous référer au <a href="/affiche_script.php?script=tian_firewall">script de pare-feu que j\'utilise</a>.
</p>
<code class="terminal">
> iptables -t filter -A INPUT --source 207.46.134.190 --jump DROP
</code>
<p>
Cet exemple permet de jeter tout ce qui vient de l\'adresse 207.46.134.190. La spécification de la table filter est facultative car par défaut c\'est celle qui est utilisée. On pourrait abréger cette commande en la suivante :
</p>
<code class="terminal">
> iptables -A INPUT -s 207.46.134.190 -j DROP
</code>
<p>
Qui produit exactement le même résultat. L\'utilisation de -A ajoute cette règle à la fin de la chaîne. Donc si une précédente règle laissait passer des paquets, ils n\'arriveront pas jusqu\'à celle-ci.
</p><p>
Pour construire un ensemble de règles de filtrage, on commencera généralement par supprimer toutes celles créées précédemment.
</p>
<code class="terminal">
> iptables -t filter -F
</code>
<p>
Cette commande vide intégralement la table filter de toutes les règles qui auraient précédemment été définies.
</p><p>
Ensuite on indiquera plutôt en premier tout ce que l\'on accepte, pour ensuite refuser tout le reste. On commencera donc par des règles ressemblant à la suivante :
</p>
<code class="terminal">
> iptables -t filter -A INPUT --protocol tcp --destination-port 80 --jump ACCEPT
</code>
<p>
Cette règle permet de laisser passer tout le trafic TCP entrant sur le port 80. Ce sera utile par exemple si un serveur web (par défaut sur le port 80) est présent sur la machine. Mais il faut ensuite que les réponses envoyées puissent l\'être. Dans ce cas, la règle précédente autorise des personnes extérieures à demander une page. Pour que le serveur puisse la transmettre, il faudra une règle comme suit :
</p>
<code class="terminal">
> iptables -t filter -A OUTPUT --protocol tcp --source-port 80 --jump ACCEPT
</code>
<p>
Pour laisser les utilisateurs internes accéder aux sites Internet, on peut définir cette règle :
</p>
<code class="terminal">
> iptables -t filter -A OUTPUT --protocol tcp --destination-port 80 --jump ACCEPT
</code>
<p>
Celle-ci permet donc de laisser passer les paquets à destination du port 80 d\'une machine extérieure. Et pour que les utilisateurs puissent recevoir les pages envoyées par ces machines, il faudra ajouter :
</p>
<code class="terminal">
> iptables -t filter -A INPUT --protocol tcp --source-port 80 --jump ACCEPT
</code>
<p>
Pour ne pas confondre ce que font les quatre règles précédentes, voici un résumé de ce qu\'elles font :
</p>
<ul>
<li>La première laisse entrer ce qui est pour le port 80 de la machine.</li>
<li>La deuxième laisse sortir les paquets par le port 80 de la machine.</li>
<li>La troisième laisse sortir ce qui est pour le port 80 d\'une autre machine.</li>
<li>La quatrième laisse entre ce qui vient du port 80 d\'une autre machine.</li>
</ul>
<p>
Dans le cas où ce sont les seules choses permises sur cette machine, on terminera par indiquer que tout le reste doit être ignoré. Arriveront à ce point seulement les paquets qui n\'auront pas répondu aux critères précédents. On peut donc alors les jeter (avec la cible DROP). Une règle toute simple pourrait être la suivante :
</p>
<code class="terminal">
> iptables -t filter -A INPUT --jump DROP<br />
> iptables -t filter -A OUTPUT --jump DROP
</code>
<p>
Ces deux règles indiquent de détruire tous les paquets entrants ou sortants. On peut souhaiter en plus garder une trace de tous ces paquets refusés. Nous allons créer une chaîne utilisateur pour cela :
</p>
<code class="terminal">
> iptables -N bloquer
</code>
<p>
Cette chaîne porte le nom "bloquer". On y ajoute ensuite une première règle pour l\'enregistrement :
</p>
<code class="terminal">
> iptables -t filter -A bloquer --jump LOG --log-prefix "Jeté: "
</code>
<p>
Tous les paquets passant par cette chaîne seront enregistré avec le message "Jeté: " devant.
</p>
<p>
On ajoute ensuite une règle semblable à celle vue plus haut :
</p>
<code class="terminal">
> iptables -t filter -A bloquer --jump DROP
</code>
<p>
Tout ce qui arrive à la fin est donc bloqué. On dirige alors tous les paquets entrants et sortants vers cette chaîne plutôt que vers la cible DROP :
</p>
<code class="terminal">
> iptables -t filter -A INPUT --jump bloquer<br />
> iptables -t filter -A OUTPUT --jump bloquer
</code>
<p>
Si aucune connexion de l\'extérieur ne doit être possible, si par exemple aucun serveur n\'est disponible sur la machine, on peut utiliser une règle se basant sur les états :
</p>
<code class="terminal">
> iptables -t filter -A INPUT -m state --state NEW,INVALID --jump DROP
</code>
<p>
Cet exemple est indépendant des précédents. Mais on peut l\'utiliser à la place de la règle finale qui rejetait tout pour autoriser les connexions de l\'intérieur.
</p><p>
On indique ici que le module state doit être chargé. Puis sur les paquets entrants, on refuse tous ceux qui sont à l\'état NEW (nouvelle connexion créée) ou INVALID (non liés à une connexion existante). Cela permet d\'empêcher toute connexion depuis l\'extérieur. Si des services sont proposés depuis la machine, on fera précéder cette règle par celles permettant d\'accepter les paquets sur les ports souhaités.
</p><p>
Un dernier exemple avec les états, qui est un peu le pendant de la règle ci-dessus.
</p>
<code class="terminal">
> iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED --jump ACCEPT
</code>
<p>
Tous les paquets entrants correspondant à une connexion déjà établie seront acceptés. En plaçant cette règle au début de la chaîne INPUT, cela évite de devoir explicitement laisser passer les paquets entrants vers les ports laissés ouverts pour un service interne (la deuxième règle de la liste de quatre vue précédemment).
</p><p>
Voici donc un petit exemple de script de pare-feu. Dans ce cas, on suppose que le seul serveur tournant sur la machine est un serveur web sur le port 80 et que l\'on souhaite refuser toute autre connexion depuis l\'extérieur. En revanche, toutes celles qui sont créées depuis l\'intérieur doivent pouvoir passer.
</p>
<code>
iptables -t filter -F<br />
iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED --jump ACCEPT<br />
iptables -t filter -A INPUT --protocol tcp --destination-port 80 --jump ACCEPT<br />
iptables -t filter -A INPUT -m state --state NEW,INVALID --jump DROP
</code>
<p>
En fait, on ne crée de règle explicites que pour la chaîne INPUT dans cet exemple. La chaîne OUTPUT ayant pour politique par défaut ACCEPT, tous les paquets sortants seront donc acceptés.
</p><p>
Ces exemples concernaient la table filter. La page décrivant comment <a href="partage_connexion.php">partager une connexion</a> en donne pour la table nat.
</p>
');
$currentPage->display();
?>
require ("../page.inc");
require ("lessons.inc");
$currentPage = new LessonPage("iptables");
$currentPage->setContent('');
$currentPage->addChapter('general', 'Généralités', '
<p>
Depuis la version 2.4, Linux contient un module destiné au filtrage réseau, <strong>Netfilter</strong>. Il se configure au moyen d\'un outil appelé <strong>iptables</strong>.
</p>
<p>
Le filtrage réseau consiste en l\'examen des paquets réseaux et à prendre des décisions sur le traitement à leur appliquer. C\'est ce que fait un <strong>pare-feu</strong> ou, en anglais, <strong>firewall</strong>. Avec un système <acronym xml:lang="en" lang="en" title="GNU\'s Not Unix">GNU</acronym>/Linux, pour configurer des règles de pare-feu, il faudra donc simplement utiliser Netfilter à l\'aide d\'iptables.
</p>
<p>
Cet article s\'interesse uniquement au filtrage réseau <acronym xml:lang="en" lang="en" title="Internet Protocol Version 4">IPV4</acronym> (qui est probablement celui que vous utilisez si cela ne vous évoque rien). Cela est possible pour d\'autres protocoles et les principes exposés ici resteront pour la plupart valides.
</p>
');
$currentPage->addChapter('presentation', 'Présentation de Netfilter', '
<p>
Netfilter travaille sur des paquets réseaux. Il s\'agit de parties des informations transmises. Pour, par exemple, télécharger un fichier, celui-ci est découpé en plusieurs paquets avant de transiter sur le réseau. Chacun de ces paquets comporte en plus des données, des informations ajoutées par les couches réseaux. Ce sont sur ces informations que s\'effectueront les tests de filtrage.
</p><p>
La couche réseau Linux présente plusieurs <strong>points d\'accès</strong> (en anglais <strong>hook</strong>). Netfilter dispose de <strong>fonctions de rappel</strong> (<strong>callback</strong>). Celles-ci sont des suites d\'instructions qui précisent ce qui doit être fait lorsque survient un événement.
</p><p>
Concrètement, lorsqu\'un paquet réseau atteint un de ces points d\'accès, il est passé à Netfilter par l\'intermédiaire de sa fonction de rappel. Il est alors examiné pour prendre une décision concernant son traitement futur.
</p><p>
Netfilter se comporte comme un automate qui compare le paquet successivement à plusieurs règles. Et selon le résultat du test, le paquet est traité ou transmis au test suivant.
</p>
');
$currentPage->addChapter('tables', 'Les tables, chaînes et cibles', '
<p>
Aux points d\'accès sont associées des <strong>chaînes</strong> de traitement. C\'est dans celles-ci que sont effectués les tests. Elles sont regroupées par <strong>tables</strong> selon le type de traitement.
</p><p>
Les tables sont ajoutées par des modules. Il en existe 3 principales pouvant être utilisées. Voici ci-après leurs noms et la tâche à laquelle elles sont destinées.
</p>
<div class="lesson-spacer">
<table class="lesson" summary="Description des tables principales de Netfilter avec leur rôle">
<caption>Tables principales de Netfilter</caption>
<tr>
<th scope="col" abbr="Table">Table</th><th scope="col" abbr="Description">Description</th>
</tr>
<tr>
<td class="lesson-spacing"></td><td class="lesson-spacing"></td>
</tr>
<tr>
<td><strong>filter</strong></td><td>Cette table permet de filtrer les paquets. Typiquement ce sera pour les accepter ou non.</td>
</tr>
<tr>
<td><strong>nat</strong></td><td>Avec cette table, on peut réaliser des translations d\'adresse (ou de ports). Ceci sera notamment utile pour <a href="partage_connexion.php">partager une connexion</a>.</td>
</tr>
<tr>
<td><strong>mangle</strong></td><td>Elle sert pour modifier les en-têtes des paquets. On la rencontrera parfois pour marquer des paquets afin que d\'autres applications puissent les reconnaître.</td>
</tr>
</table>
</div>
<p>
A l\'intérieur d\'une table, on peut trouver plusieurs chaînes. Ce sont elles qui contiendront les <strong>règles</strong> à appliquer aux paquets. Ces règles seront évaluées séquentiellement. On trouve deux types de chaînes.
</p><p>
Tout d\'abord celles qui sont associées aux différents points d\'entrées existants. Un paquet atteignant un de ces points sera envoyé vers la chaîne associée. Ce sont les fonctions de rappel evoquées précédemment qui réalisent cela. Elles effectuent les uns après les autres les tests que contient la chaîne. Ces chaînes sont en nombre fini et ne sont pertinentes que pour certaines tables. Le tableau suivant les liste, en indiquant quelle table a une chaîne de ce type.
</p>
<div class="lesson-spacer">
<table class="lesson" summary="Description des chaînes Netfilter indiquant les tables les contenant">
<caption>Chaînes de Netfilter</caption>
<tr>
<th scope="col" abbr="Chaîne">Chaîne</th><th scope="col" abbr="Table">Table</th><th scope="col" abbr="Description">Description</th>
</tr>
<tr>
<td class="lesson-spacing"></td><td class="lesson-spacing"></td><td class="lesson-spacing"></td>
</tr>
<tr>
<td><strong>PREROUTING</strong></td><td>nat, mangle</td><td>Par cette chaîne passeront les paquets entrant dans la machine avant routage.</td>
</tr>
<tr>
<td><strong>INPUT</strong></td><td>filter</td><td>Cette chaîne traitera les paquets entrants avant qu\'ils ne soient passées aux couches supérieures (les applications).</td>
</tr>
<tr>
<td><strong>FORWARD</strong></td><td>filter</td><td>Ce sont les paquets uniquement transmis par la machine sans que les applications n\'en aient connaissance.</td>
</tr>
<tr>
<td><strong>OUTPUT</strong></td><td>filter, nat, mangle</td><td>Cette chaîne sera appelée pour des paquets envoyés par des programmes présents sur la machine.</td>
</tr>
<tr>
<td><strong>POSTROUTING</strong></td><td>nat</td><td>Les paquets prêts à être envoyés (soit transmis, soit générés) seront pris en charge par cette chaîne.</td>
</tr>
</table>
</div>
<p>
On trouve aussi des chaînes utilisateurs. Elles peuvent librement être créées mais ne seront pas associées à un point d\'accès. En fait on ne pourra rentrer dans une de ces chaînes que si une règle d\'une des chaînes existantes dirige le paquet vers celle-ci.
</p><p>
Enfin, le dernier élément important est la notion de <strong>cible</strong>. Il s\'agit du traitement que l\'on décide d\'appliquer au paquet. C\'est la cible qui se chargera de faire les opérations nécessaires. En plus de celles prédéfinies, il est possible d\'indiquer comme cible une chaîne utilisateur. Cela permet d\'imbriquer différents tests et traitements.
</p><p>
Chaque chaîne peut être vue comme un ensemble de tests, chacun ayant pour résultat l\'envoi du paquet vers la cible spécifiée si la condition est vérifiée. Si ce n\'est pas le cas, on passe à la suivante. En arrivant à la fin d\'une des chaînes du tableau précédent, une cible par défaut est utilisée. A la fin d\'une chaîne utilisateur, si aucune décision n\'a été prise, on revient à la chaîne appelante.
</p><p>
Voici les cibles prédéfinies les plus courantes :
</p>
<div class="lesson-spacer">
<table class="lesson" summary="Descriptions des cibles prédéfinies permettant de connaître leur utilité">
<caption>Cibles prédéfinies</caption>
<tr>
<th scope="col" abbr="Cible">Cible</th><th scope="col" abbr="Description">Description</th>
</tr>
<tr>
<td class="lesson-spacing"></td><td class="lesson-spacing"></td>
</tr>
<tr>
<td><strong>ACCEPT</strong></td><td>Les paquets envoyés vers cette cible seront tout simplement acceptés et pourront poursuivre leur cheminement au travers des couches réseaux.</td>
</tr>
<tr>
<td><strong>DROP</strong></td><td>Cette cible permet de jeter des paquets qui seront donc ignorés.</td>
</tr>
<tr>
<td><strong>REJECT</strong></td><td>Permet d\'envoyer une réponse à l\'émetteur pour lui signaler que son paquet a été refusé.</td>
</tr>
<tr>
<td><strong>LOG</strong></td><td>Demande au noyau d\'enregistrer des informations sur le paquet courant. Cela se fera généralement dans le fichier /var/log/messages (selon la configuration du programme syslogd).</td>
</tr>
<tr>
<td><strong>MASQUERADE</strong></td><td>Cible valable uniquement dans la chaîne POSTROUTING de la table nat. Elle change l\'adresse <acronym xml:lang="en" lang="en" title="Internet Protocol">IP</acronym> de l\'émetteur par celle courante de la machine pour l\'interface spécifiée. Cela permet de masquer des machines et de faire par exemple du partage de connexion.</td>
</tr>
<tr>
<td><strong>SNAT</strong></td><td>Egalement valable pour la chaîne POSTROUTING de la table nat seulement. Elle modifie aussi la valeur de l\'adresse IP de l\'émetteur en la remplaçant par la valeur fixe spécifiée.</td>
</tr>
<tr>
<td><strong>DNAT</strong></td><td>Valable uniquement pour les chaînes PREROUTING et OUTPUT de la table nat. Elle modifie la valeur de l\'adresse IP du destinataire en la remplaçant par la valeur fixe spécifiée.</td>
</tr>
<tr>
<td><strong>RETURN</strong></td><td>Utile dans les chaînes utilisateurs. Cette cible permet de revenir à la chaîne appelante. Si RETURN est utilisé dans une des chaînes de base précédente, cela est équivalent à l\'utilisation de sa cible par défaut.</td>
</tr>
</table>
</div>
');
$currentPage->addChapter('iptables', 'Présentation d\'iptables', '
<p>
<strong>iptables</strong> est l\'outil qui est fourni à l\'administateur pour agir sur tous les concepts vus précédemment et pour modifier les règles de filtrage donc.
</p><p>
La première option à connaître est <strong>-t</strong> qui permet de spécifier le nom de la table sur laquelle porteront les autres paramètres. Si cette option n\'est pas spécifiée, ce sera par défaut la table filter.
</p><p>
On peut aussi demander à iptables de charger un module particulier avec l\'option <strong>-m</strong>. Ce module peut ajouter de nouvelles tables ou de nouvelles manières de tester les paquets.
</p><p>
Il faut ensuite indiquer une commande pour indiquer par exemple qu\'une nouvelle règle doit être ajoutée dans la chaîne spécifiée. Ci-après la liste des options les plus courantes pour spécifier une commande. Une seule à la fois peut être présente, et toutes devront être suivies du nom de la chaîne à prendre en compte.
</p>
<div class="lesson-spacer">
<table class="lesson" summary="Options les plus fréquemment utilisées avec iptables et leur description">
<caption>Options d\'iptables</caption>
<tr>
<th scope="col" abbr="Option">Option</th><th scope="col" abbr="Rôle">Rôle</th>
</tr>
<tr>
<td class="lesson-spacing"></td><td class="lesson-spacing"></td>
</tr>
<tr>
<td><strong>-L</strong></td><td>Affiche toutes les règles de la chaîne indiquée.</td>
</tr>
<tr>
<td><strong>-F</strong></td><td>Supprime toutes les règles de la chaîne. Si aucune chaîne n\'est spécifiée, toutes celles de la table sont vidées.</td>
</tr>
<tr>
<td><strong>-N</strong></td><td>Crée une nouvelle chaîne utilisateur avec le nom passé en paramètre.</td>
</tr>
<tr>
<td><strong>-X</strong></td><td>Supprime la chaîne utilisateur. Si aucun nom n\'est spécifié, toutes les chaînes utilisateur seront supprimées</td>
</tr>
<tr>
<td><strong>-P</strong></td><td>Modifie la politique par défaut de la chaîne. Il faut indiquer en plus comme paramètre la cible à utiliser.</td>
</tr>
<tr>
<td><strong>-A</strong></td><td>Ajoute une règle à la fin de la chaîne spécifiée.</td>
</tr>
<tr>
<td><strong>-I</strong></td><td>Insère la règle avant celle indiquée. Cette place est précisée par un numéro qui fait suite au nom de la chaîne. La première porte le numéro 1. Si aucun numéro n\'est indiqué, la règle est insérée au début.</td>
</tr>
<tr>
<td><strong>-D</strong></td><td>Supprime une règle de la chaîne. Soit un numéro peut être précisé, soit la définition de la chaîne à supprimer (ses tests de concordance et sa cible).</td>
</tr>
</table>
</div>
<p>
Quelques <a href="#examples">exemples</a> montreront l\'utilisation de ces options.
</p>
');
$currentPage->addChapter('tests', 'Les tests de concordance et options de cible', '
<p>
Pour pouvoir créer des règles, il faut effectuer des <strong>tests de concordance</strong>. Ceux-ci définissent les caractéristiques que doivent présenter les paquets pour être concernés par la règle, et donc être dirigés vers la cible spécifiée.
</p><p>
Certains paramètres de tests ne sont valables que si d\'autres options sont précisées. Le tableau suivant, qui présente les plus utilisés de ces tests, indiquera donc le contexte d\'utilisation qui correspondra aux autres options nécessaires (avec leurs paramètres) s\'il y en a.
</p><p>
Plusieurs de ces paramètres existent en version longue ou abrégée, celle longue étant précédée de -- (deux tirets). Lorsqu\'une version courte existe, elle sera indiquée ci-dessous. L\'utilisation de l\'une ou de l\'autre est strictement équivalent.
</p>
<div class="lesson-spacer">
<table class="lesson" summary="Paramètres de test utilisés par les règles de concordance, leur version abrégée si elle existe et le contexte d\'utilisation">
<caption>Paramètres de test</caption>
<tr>
<th scope="col" abbr="Option">Option de test</th><th scope="col" abbr="Abrégé">Version abrégée</th><th scope="col" abbr="Contexte">Contexte</th><th scope="col" abbr="Description">Description</th>
</tr>
<tr>
<td class="lesson-spacing"></td><td class="lesson-spacing"></td><td class="lesson-spacing"></td><td class="lesson-spacing"></td>
</tr>
<tr>
<td><strong>--source</strong></td><td><strong>-s</strong></td><td></td><td>Adresse source. Cette option est suivie par l\'adresse de la machine qui doit avoir émis ce paquet. Celle-ci peut-être sous forme numérique, ou sous forme de nom de machine. Si l\'adresse est précédée d\'un ! (point d\'exclamation), le test est alors inversé et la condition sera donc remplie si l\'adresse de l\'émetteur ne correspond pas à celle spécifiée. On peut aussi à la suite de l\'adresse indiquer un masque de sous-réseau en séparant par un / (barre oblique) ces deux éléments.</td>
</tr>
<tr>
<td><strong>--destination</strong></td><td><strong>-d</strong></td><td></td><td>Adresse de destination. On trouve ensuite l\'adresse de destination du paquet, avec les mêmes possibilités que pour --source.</td>
</tr>
<tr>
<td><strong>--in-interface</strong></td><td><strong>-i</strong></td><td>Chaînes INPUT, FORWARD ou PREROUTING</td><td>Interface d\'entrée. Suivie par le nom de l\'interface par laquelle doivent arriver les paquets. Par exemple, ce sera ppp0 pour un modem, ou eth0 pour la première carte ethernet. Le nom de l\'interface peut être précédé d\'un ! (point d\'exclamation) pour inverser le test.</td>
</tr>
<tr>
<td><strong>--out-interface</strong></td><td><strong>-o</strong></td><td>Chaînes FORWARD, OUTPUT ou POSTROUTING</td><td>Interface de sortie. Suivi du même paramètre que pour l\'option --in-interface. Dans ce cas-là est testée l\'interface par laquelle vont être envoyés les paquets.</td>
</tr>
<tr>
<td><strong>--protocol</strong></td><td><strong>-p</strong></td><td></td><td>Protocole. Permet de vérifier le protocole du paquet. Les valeurs littérales pouvant être utilisées à la suite de cette option sont <acronym xml:lang="en" lang="en" title="Transmission Control Protocol">tcp</acronym>, <acronym xml:lang="en" lang="en" title="User Datagram Protocol">udp</acronym>, <acronym xml:lang="en" lang="en" title="Internet Control Message Protocol">icmp</acronym> ou <strong>all</strong> qui les regroupe toutes.</td>
</tr>
<tr>
<td><strong>--source-port</strong></td><td></td><td>--protocol tcp <i>ou</i> --protocol udp</td><td>Port source. Cette option permet de vérifier le port source (celui utilisé par l\'émetteur). Il est spécifié sous forme numérique ou par nom de service (comme <acronym xml:lang="en" lang="en" title="HyperText Transfer Protocol">http</acronym> ou <acronym xml:lang="en" lang="en" title="Simple Mail Transfer Protocol">smtp</acronym>). On peut aussi indiquer une plage de port en séparant les deux bornes par : (deux points). Par exemple 25:110 pour tous les ports compris entre 25 et 110. Pour exclure le ou les ports spécifiés, il faut utiliser un ! (point d\'exclamation) après --source-port.</td>
</tr>
<tr>
<td><strong>--destination-port</strong></td><td></td><td>--protocol tcp <i>ou</i> --protocol udp</td><td>Port destination. Compare le port utilisé pour se connecter sur la machine avec la valeur ou plage de valeur indiquée. Ces dernières sont indiquées comme pour --source-port.</td>
</tr>
<tr>
<td><strong>--state</strong></td><td></td><td>-m state</td><td>Etat du paquet. Une liste de plusieurs valeurs peut être indiquée en les séparant par des virgules. L\'état de ce paquet est comparé alors à ces valeurs. <strong>NEW</strong> correspond à un paquet initiant une nouvelle connexion. <strong>ESTABLISHED</strong> est un paquet participant à une conversation déjà établie. <strong>RELATED</strong> est pour un paquet qui ouvre une nouvelle connexion, mais ceci en rapport avec une précédente déjà établie. <strong>INVALID</strong> indique un paquet qui n\'est rattaché à aucune connexion.</td>
</tr>
</table>
</div>
<p>
Une fois spécifiés les critères auxquels doivent répondre les paquets, il faut indiquer vers quelle cible l\'envoyer s\'il y répond. Cela se fait avec l\'option <strong>--jump</strong> ou en abrégé <strong>-j</strong> suivie par le nom de la cible.
</p><p>
Certaines de ces cibles nécessitent des options pour les paramétrer. Elles sont indiquées sous la même forme que les options de tests. Ci-suivent les plus couramment utilisées.
</p>
<div class="lesson-spacer">
<table class="lesson" summary="Options utilisées par les cibles afin de parametrer leur fonctionnement">
<caption>Options des cibles</caption>
<tr>
<th scope="col" abbr="Paramètre">Paramètre</th><th scope="col" abbr="Cible">Cible</th><th scope="col" abbr="Description">Description</th>
</tr>
<tr>
<td class="lesson-spacing"></td><td class="lesson-spacing"></td><td class="lesson-spacing"></td>
</tr>
<tr>
<td><strong>--log-prefix</strong></td><td>LOG</td><td>Préfixe dans le journal. Cette option est suivie d\'une chaîne de moins de 30 caractères. Celle-ci est ajoutée devant les lignes qui sont inserées dans les fichiers journaux. Cela permet de plus facilement les retrouver par la suite.</td>
</tr>
<tr>
<td><strong>--reject-with</strong></td><td>REJECT</td><td>Message de rejet. Avec --reject-with, on peut indiquer quel type de message ICMP doit être envoyé vers la machine dont le paquet est rejeté. A la suite de l\'option, on peut trouver <strong>icmp-net-unreachable</strong> (réseau inaccessible), <strong>icmp-host-unreachable</strong> (machine inaccessible), <strong>icmp-port-unreachable</strong> (port inaccessible), <strong>icmp-proto-unreachable</strong> (protocole inaccessible), <strong>icmp-net-prohibited</strong> (réseau interdit) ou <strong>icmp-host-prohibited</strong> (machine interdite). Si le type de protocol est tcp, on peut aussi trouver <strong>tcp-reset</strong> qui indique qu\'il faudra envoyer un paquet RST qui permet de fermer une connexion.</td>
</tr>
<tr>
<td><strong>--to-source</strong></td><td>SNAT</td><td>Nouvelle adresse source. Permet d\'indiquer quelle adresse doit être mise en tant qu\'adresse source dans le paquet pour remplacer celle existante. On peut en indiquer une seule, ou une plage en séparant les bornes par un - (tiret). On peut aussi modifier le port avec cette option. Cela se fait en spécifiant un port (ou une plage de ports) en le séparant de l\'adresse par : (deux points).</td>
</tr>
<tr>
<td><strong>--to-destination</strong></td><td>DNAT</td><td>Nouvelle adresse destination. Utilisée pour modifier l\'adresse de destination en la remplaçant par celle indiquée à la suite de cette option. Le format du paramètre suivant --to-destination est le même que pour --to-source.</td>
</tr>
</table>
</div>
');
$currentPage->addChapter('examples', 'Exemples courants', '
<p>
Voici une suite de quelques exemples pouvant être utiles. Ils seront accompagnés d\'une explication sur leurs rôles. Vous pouvez aussi vous référer au <a href="/affiche_script.php?script=tian_firewall">script de pare-feu que j\'utilise</a>.
</p>
<code class="terminal">
> iptables -t filter -A INPUT --source 207.46.134.190 --jump DROP
</code>
<p>
Cet exemple permet de jeter tout ce qui vient de l\'adresse 207.46.134.190. La spécification de la table filter est facultative car par défaut c\'est celle qui est utilisée. On pourrait abréger cette commande en la suivante :
</p>
<code class="terminal">
> iptables -A INPUT -s 207.46.134.190 -j DROP
</code>
<p>
Qui produit exactement le même résultat. L\'utilisation de -A ajoute cette règle à la fin de la chaîne. Donc si une précédente règle laissait passer des paquets, ils n\'arriveront pas jusqu\'à celle-ci.
</p><p>
Pour construire un ensemble de règles de filtrage, on commencera généralement par supprimer toutes celles créées précédemment.
</p>
<code class="terminal">
> iptables -t filter -F
</code>
<p>
Cette commande vide intégralement la table filter de toutes les règles qui auraient précédemment été définies.
</p><p>
Ensuite on indiquera plutôt en premier tout ce que l\'on accepte, pour ensuite refuser tout le reste. On commencera donc par des règles ressemblant à la suivante :
</p>
<code class="terminal">
> iptables -t filter -A INPUT --protocol tcp --destination-port 80 --jump ACCEPT
</code>
<p>
Cette règle permet de laisser passer tout le trafic TCP entrant sur le port 80. Ce sera utile par exemple si un serveur web (par défaut sur le port 80) est présent sur la machine. Mais il faut ensuite que les réponses envoyées puissent l\'être. Dans ce cas, la règle précédente autorise des personnes extérieures à demander une page. Pour que le serveur puisse la transmettre, il faudra une règle comme suit :
</p>
<code class="terminal">
> iptables -t filter -A OUTPUT --protocol tcp --source-port 80 --jump ACCEPT
</code>
<p>
Pour laisser les utilisateurs internes accéder aux sites Internet, on peut définir cette règle :
</p>
<code class="terminal">
> iptables -t filter -A OUTPUT --protocol tcp --destination-port 80 --jump ACCEPT
</code>
<p>
Celle-ci permet donc de laisser passer les paquets à destination du port 80 d\'une machine extérieure. Et pour que les utilisateurs puissent recevoir les pages envoyées par ces machines, il faudra ajouter :
</p>
<code class="terminal">
> iptables -t filter -A INPUT --protocol tcp --source-port 80 --jump ACCEPT
</code>
<p>
Pour ne pas confondre ce que font les quatre règles précédentes, voici un résumé de ce qu\'elles font :
</p>
<ul>
<li>La première laisse entrer ce qui est pour le port 80 de la machine.</li>
<li>La deuxième laisse sortir les paquets par le port 80 de la machine.</li>
<li>La troisième laisse sortir ce qui est pour le port 80 d\'une autre machine.</li>
<li>La quatrième laisse entre ce qui vient du port 80 d\'une autre machine.</li>
</ul>
<p>
Dans le cas où ce sont les seules choses permises sur cette machine, on terminera par indiquer que tout le reste doit être ignoré. Arriveront à ce point seulement les paquets qui n\'auront pas répondu aux critères précédents. On peut donc alors les jeter (avec la cible DROP). Une règle toute simple pourrait être la suivante :
</p>
<code class="terminal">
> iptables -t filter -A INPUT --jump DROP<br />
> iptables -t filter -A OUTPUT --jump DROP
</code>
<p>
Ces deux règles indiquent de détruire tous les paquets entrants ou sortants. On peut souhaiter en plus garder une trace de tous ces paquets refusés. Nous allons créer une chaîne utilisateur pour cela :
</p>
<code class="terminal">
> iptables -N bloquer
</code>
<p>
Cette chaîne porte le nom "bloquer". On y ajoute ensuite une première règle pour l\'enregistrement :
</p>
<code class="terminal">
> iptables -t filter -A bloquer --jump LOG --log-prefix "Jeté: "
</code>
<p>
Tous les paquets passant par cette chaîne seront enregistré avec le message "Jeté: " devant.
</p>
<p>
On ajoute ensuite une règle semblable à celle vue plus haut :
</p>
<code class="terminal">
> iptables -t filter -A bloquer --jump DROP
</code>
<p>
Tout ce qui arrive à la fin est donc bloqué. On dirige alors tous les paquets entrants et sortants vers cette chaîne plutôt que vers la cible DROP :
</p>
<code class="terminal">
> iptables -t filter -A INPUT --jump bloquer<br />
> iptables -t filter -A OUTPUT --jump bloquer
</code>
<p>
Si aucune connexion de l\'extérieur ne doit être possible, si par exemple aucun serveur n\'est disponible sur la machine, on peut utiliser une règle se basant sur les états :
</p>
<code class="terminal">
> iptables -t filter -A INPUT -m state --state NEW,INVALID --jump DROP
</code>
<p>
Cet exemple est indépendant des précédents. Mais on peut l\'utiliser à la place de la règle finale qui rejetait tout pour autoriser les connexions de l\'intérieur.
</p><p>
On indique ici que le module state doit être chargé. Puis sur les paquets entrants, on refuse tous ceux qui sont à l\'état NEW (nouvelle connexion créée) ou INVALID (non liés à une connexion existante). Cela permet d\'empêcher toute connexion depuis l\'extérieur. Si des services sont proposés depuis la machine, on fera précéder cette règle par celles permettant d\'accepter les paquets sur les ports souhaités.
</p><p>
Un dernier exemple avec les états, qui est un peu le pendant de la règle ci-dessus.
</p>
<code class="terminal">
> iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED --jump ACCEPT
</code>
<p>
Tous les paquets entrants correspondant à une connexion déjà établie seront acceptés. En plaçant cette règle au début de la chaîne INPUT, cela évite de devoir explicitement laisser passer les paquets entrants vers les ports laissés ouverts pour un service interne (la deuxième règle de la liste de quatre vue précédemment).
</p><p>
Voici donc un petit exemple de script de pare-feu. Dans ce cas, on suppose que le seul serveur tournant sur la machine est un serveur web sur le port 80 et que l\'on souhaite refuser toute autre connexion depuis l\'extérieur. En revanche, toutes celles qui sont créées depuis l\'intérieur doivent pouvoir passer.
</p>
<code>
iptables -t filter -F<br />
iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED --jump ACCEPT<br />
iptables -t filter -A INPUT --protocol tcp --destination-port 80 --jump ACCEPT<br />
iptables -t filter -A INPUT -m state --state NEW,INVALID --jump DROP
</code>
<p>
En fait, on ne crée de règle explicites que pour la chaîne INPUT dans cet exemple. La chaîne OUTPUT ayant pour politique par défaut ACCEPT, tous les paquets sortants seront donc acceptés.
</p><p>
Ces exemples concernaient la table filter. La page décrivant comment <a href="partage_connexion.php">partager une connexion</a> en donne pour la table nat.
</p>
');
$currentPage->display();
?>
Si avez des problèmes ou des questions concernant ce fichier source, vous pouvez utiliser le Forum Sources du site