XI. La machine d'état▲
Ce chapitre aborde et explique en détails la machine d'état. Après avoir lu ceci, vous devriez avoir pleinement compris son fonctionnement. Vous parcourerez un nombre important d'exemples sur la façon dont les états sont traités par la machine d'état elle-même. Ces cas concrets devraient vous éclairer parfaitement.
XI-A. Introduction▲
La machine d'état correspond à une partie spéciale à l'intérieur d'iptables. En fait, elle porte très mal son nom puisqu'il s'agit en réalité d'une machine de traçage de connexion. Cependant, la plupart des gens la connaissent sous la première appellation. Au cours de ce chapitre, les deux noms sont utilisés indistinctement comme ils sont synonymes. Ceci ne devrait pas trop vous perturber. Le traçage de connexion est effectué afin que l'architecture de Netfilter puisse connaître l'état d'une connexion spécifique. Les pare-feux qui implémentent ceci sont habituellement appelés pare-feux à état. Un pare-feu à état est généralement bien plus sûr qu'un pare-feu sans état, puisqu'il impose une plus grande rigueur sur l'écriture des livres de règles.
Dans iptables, les paquets peuvent être reliés aux connexions tracées dans quatre états différents, qui sont connus sous les noms de NEW, ESTABLISHED, RELATED et INVALID. Chacun de ces états sera approfondi plus loin. Avec la correspondance --state, il est facile de contrôler qui, ou ce qui, est autorisé à démarrer de nouvelles sessions.
L'intégralité du traçage de connexion est effectué par une structure particulière à l'intérieur du noyau appelée conntrack. La structure conntrack peut soit être chargée comme un module, soit être interne au noyau. La plupart du temps, on a besoin de fonctions supplémentaires de traçage de connexion autres que celles proposées par défaut dans le moteur conntrack. De ce fait, des parties spécifiques de conntrack prennent en charge les protocoles TCP, UDP et ICMP. Ces modules capturent des informations spécifiques et uniques sur les paquets, afin de pouvoir tracer chaque flux de données. L'information récupérée par conntrack lui permet de connaître l'état dans lequel se trouve chaque flux actuellement. Par exemple, un flux UDP est, en général, identifié uniquement par son adresse IP destination, son adresse IP source, son port destination et son port source.
Dans les noyaux précédents, il était possible d'activer ou désactiver la défragementation. Cependant, depuis qu'iptables et Netfilter ont été incorporés avec, en particulier, le traçage de connexion, cette option a disparu. La raison en est simple, le traçage de connexion ne peut pas fonctionner correctement sans défragmenter les paquets, par conséquent la défragmentation a été intégrée dans conntrack, et elle est réalisée automatiquement. Elle ne peut donc plus être désactivée, sauf en désactivant le traçage de connexion. En définitive, la défragmentation a toujours cours si le traçage de connexion est actif.
Le traçage de connexion est entièrement pris en charge dans la chaîne PREROUTING, sauf pour les paquets générés en local, qui sont pris en charge dans la chaîne OUTPUT. Ceci signifie qu'iptable effectue tous les calculs d'état dans la chaîne PREROUTING. Si on envoie le premier paquet d'un flux, l'état est défini comme NEW dans la chaîne OUTPUT, et quand on reçoit un paquet de réponse, l'état passe à ESTABLISHED, et ainsi de suite. Si le premier paquet n'est pas envoyé par nous-mêmes, l'état NEW est naturellemt défini dans la chaîne PREROUTING. Ainsi, tous les changements d'état et calculs sont réalisés dans les chaînes PREROUTING et OUTPUT de la table nat.
XI-B. Les entrées de conntrack▲
Examinons rapidement le contenu d'une donnée d'entrée de conntrack et lisons-la dans /proc/net/ip_conntrack. Ce lien contient une liste de toutes les entrées actuelles de la base de données de conntrack. Si vous avez chargé le module ip_conntrack, faites un cat de /proc/net/ip_conntrack pour obtenir quelque-chose comme ceci :
tcp 6 117 SYN_SENT src=192.168.1.6 dst=192.168.1.9 sport=32775 \
dport=22 [UNREPLIED] src=192.168.1.9 dst=192.168.1.6 sport=22 \
dport=32775 [ASSURED] use=2
Cet exemple contient toute l'information gérée par le module conntrack pour savoir dans quel état se trouve une connexion. Tout d'abord, il y a le protocole, ici tcp. Ensuite, encore le protocole mais codé en décimal. Après cela, on voit combien de temps doit survivre cette entrée de conntrack. La valeur à cet instant est de 117 secondes, et elle est decrémentée régulièrement jusqu'à ce qu'on voit à nouveau du trafic pour cette connexion. Cette valeur est alors réinitialisée à la valeur par défaut pour l'état en question à cet instant donné. Ensuite vient l'état actuel de cette entrée. Dans le cas présenté ci-dessus, on visualise une connexion qui est dans l'état SYN_SENT. La valeur interne d'une connexion est légèrement différente de celles utilisées en externe avec iptables. La valeur SYN_SENT indique que cette connexion a seulement vu un paquet TCP SYN dans une direction. Puis, on voit l'adresse IP source, l'adresse IP destination, le port source et le port destination. Arrivé à ce niveau, on voit un mot-clé spécifique qui signale qu'aucun trafic n'a été observé en retour pour cette connexion. Enfin, on voit ce qui est attendu pour les paquets de réponse. Entre autres, l'adresse IP source et l'adresse IP destination (qui sont inversées, puisque le paquet attendu doit être dirigé dans l'autre sens). La même chose s'applique aux port source et port destination de la connexion. Ces valeurs nous intéressent particulièrement.
Les entrées du traçage de connexion peuvent prendre un ensemble de valeurs différentes, toutes spécifiées dans les en-têtes de conntrack et disponibles dans les fichiers linux/include/netfilter-ipv4/ip_conntrack*.h. Ces valeurs dépendent du sous-protocole IP qu'on utilise. Les protocoles TCP, UDP et ICMP correspondent à des valeurs fixées et spécifiées dans le fichier linux/include/netfilter-ipv4/ip_conntrack.h. Ceci sera analysé plus en détails lors de l'analyse de chaque protocole ; cependant, ils ne seront pas employés intensivement dans ce chapitre, puisqu'ils ne sont pas utilisés en dehors du fonctionnement interne de conntrack. Ainsi, en fonction de l'évolution de cet état, on change la valeur du temps restant avant la destruction de la connexion.
Récemment, un nouveau patch est devenu disponible dans patch-o-matic, appelé tcp-window-tracking. Il ajoute, entre autres, toutes les temporisations précitées aux variables spéciales sysctl, ce qui signifie qu'elles peuvent être modifiées à la volée, alors que le système est toujours en fonctionnement. Par conséquent, il ne devient plus indispensable de recompiler le noyau à chaque changement dans les temporisations.
Tout ceci peut être modifié par le biais d'appels système spécifiques, disponibles dans le répertoire /proc/sys/net/ipv4/netfilter. Vous devriez regarder en particulier les variables /proc/sys/net/ipv4/netfilter/ip_ct_*.
Quand une connexion a observé du trafic dans les deux directions, l'entrée de conntrack efface le fanion [UNREPLIED], et donc le réinitialise. Elle le remplace par le fanion [ASSURED], vers la fin. Il signale que cette connexion est confirmée, donc elle ne sera pas supprimée si on atteint le maximum de connexions tracées possible. En fait, les connexions estampillées [ASSURED] ne seront pas supprimées, au contraire des connexions non confirmées (sans le fanion [ASSURED]). Le nombre maximum de connexions gérées par la table de traçage de connexion dépend d'une variable qui peut être définie à l'aide de la fonction ip-sysctl dans les noyaux récents. La valeur par défaut prise en charge varie fortement avec la quantité de mémoire disponible. Avec 128 Mo de RAM, vous pourrez avoir 8192 entrées possibles, et avec 256 Mo, ce sera 16376 entrées. Vous pouvez lire et définir vos réglages à l'aide de /proc/sys/net/ipv4/ip_conntrack_max.
Un moyen différent de faire ceci, plus efficace, est de placer la taille de la fonction de hachage pour le module ip_conntrack une fois qu'il est chargé. Dans des circonstances normales ip_conntrack_max égale 8 * la taille de la fonction de hachage. En d'autres termes, placer cette taille à 4096 fera que ip_conntrack_max aura 32768 entrées conntrack. Un exemple de ce qui pourrait être :
work3:/home/blueflux# modprobe ip_conntrack hashsize=4096
work3:/home/blueflux# cat /proc/sys/net/ipv4/ip_conntrack_max
32768
work3:/home/blueflux#
XI-C. États de l'espace utilisateur▲
Comme vous l'avez vu, les paquets peuvent prendre différents états à l'intérieur du noyau, en fonction du protocole considéré. Cependant, à l'extérieur du noyau, seuls 4 états sont disponibles, comme c'est expliqué précédemment. Ces états peuvent être associés à la correspondance state qui est capable de sélectionner les paquets à partir de l'état actuel du traçage de connexion. Les états valides sont NEW, ESTABLISHED, RELATED et INVALID. Le tableau suivant décrit brièvement chacun d'eux.
Tableau 1. États de l'espace utilisateur
État | Explication |
---|---|
NEW | L'état NEW indique que le paquet est le premier de la connexion. Cela signifie que, pour une connexion donnée, le premier paquet que le module conntrack aperçoit est sélectionné. Par exemple, si on rencontre un paquet SYN et que c'est le premier paquet d'une connexion, on établit la correspondance. Cependant, le paquet peut aussi ne pas être de type SYN et considéré tout de même dans l'état NEW. Ceci peut s'avérer problématique dans certaines situations, mais peut aussi être extrêmement utile quand on doit récupérer les connexions perdues issues d'autres pare-feux, ou quand une connexion a dépassé son temps de survie, mais n'est pas réellement fermée. |
ESTABLISHED | L'état ESTABLISHED résulte de l'observation d'un trafic dans les deux sens, et donc établit une correspondance avec ce type de paquets. Les connexions établies (ESTABLISHED) sont particulièrement simple à comprendre. La seule condition pour entrer dans l'état ESTABLISHED est qu'un hôte ayant envoyé un paquet reçoive plus tard une réponse de l'hôte destinataire de ce paquet. A la réception du paquet de réponse, l'état NEW est transformé en ESTABLISHED. Les messages d'erreur et de redirection ICMP peuvent aussi être considérés comme ESTABLISHED, si on a généré un paquet qui en retour génère le message ICMP. |
RELATED | L'état RELATED est un des états les plus astucieux. Une connexion est considérée comme RELATED quand elle est liée à une autre connexion déjà établie, donc dans l'état ESTABLISHED. Ainsi, pour qu'une connexion soit identifiée comme RELATED, on doit tout d'abord disposer d'une autre dans l'état ESTABLISHED. La connexion ESTABLISHED crée alors une connexion extérieure à la connexion principale. La nouvelle connexion créée est donc considérée comme RELATED, si le module conntrack l'identifie comme en relation avec l'autre. Les exemples suivants peuvent être considérés comme RELATED : les connexions FTP-data sont liées au port FTP control, et les connexions DCC interviennent par l'intermédiaire de IRC. Ceci permet d'utiliser des réponses ICMP, des transferts FTP et des DCC pour travailler convenablement à travers un pare-feu. Remarquez que la plupart des protocoles TCP et certains protocoles UDP qui reposent sur ce mécanisme sont particulièrement complexes. Ils envoient des informations de connexion à l'intérieur des données utiles, qui par conséquent requièrent des modules helper spécifiques pour être correctement interprétées. |
INVALID | L'état INVALID signifie que le paquet ne peut pas être identifié ou qu'il n'a aucun état connu. Il peut y avoir plusieurs raisons à cela : par exemple, un système en dépassement de mémoire ou des messages d'erreur ICMP ne répondant à aucune connexion connue. Généralement, il est préférable de détruire tout ce qui se trouve dans cet état. |
Ces états peuvent être utilisés avec la correspondance --state pour sélectionner des paquets à partir de leur état de traçage de connexion. C'est ce qui rend la machine d'état si puissante et efficace pour votre pare-feu. Auparavant, nous devions souvent ouvrir tous les ports supérieurs à 1024 pour permettre le trafic inverse à destination de notre réseau local. Avec la machine d'état à l'oeuvre, ce n'est plus nécessaire, puisqu'il est possible d'ouvrir le pare-feu pour les réponses sans l'ouvrir pour le reste du trafic.
XI-D. Connexions TCP▲
Dans cette section et les suivantes, nous examinons davantage les états et comment ils sont gérés pour les trois protocoles élémentaires TCP, UDP et ICMP. Nous verrons aussi comment les états sont gérés par défaut, s'ils ne peuvent être assimilés à un quelconque de ces trois protocoles. Nous choisissons de démarrer avec le protocole TCP comme c'est un protocole à état en lui-même, avec nombre de caractéristiques intéressantes en rapport avec la machine d'état d'iptables.
Une connexion TCP démarre toujours avec l'établissement d'une liaison en 3 phases, qui met en place et négocie la connexion qui servira pour le transfert des données. Toute la session commence par un paquet SYN, suivi d'un paquet SYN/ACK et se termine par un paquet ACK pour accuser réception de l'établissement de la session. A cet instant, la connexion est établie et prête à envoyer des données. La problème est le suivant : comment le traçage de connexion peut-il s'accrocher à cette étape ? En fait, très simplement.
En ce qui concerne l'utilisateur, le traçage de connexion fonctionne de façon identique pour tout type de connexion. Observez le schéma ci-dessous pour comprendre dans quel état se trouve le flux aux différentes étapes de la connexion. Comme vous le voyez, le code du traçage de connexion ne suit pas vraiment les étapes de la connexion TCP du point de vue de l'utilisateur. Dès qu'un paquet SYN arrive, il considère la connexion comme nouvelle (NEW). Dès qu'un paquet de réponse SYN/ACK est observé, il considère la connexion comme établie (ESTABLISHED).
Si vous réfléchissez une seconde, vous comprendrez pourquoi. Avec cette implémentation particulière, vous pouvez autoriser des paquets NEW et ESTABLISHED à quitter votre réseau local, et autoriser seulement des connexions ESTABLISHED en retour, et ça fonctionnera sans problème. A contrario, si la machine de traçage de connexion considérait l'établissement complet de la connexion comme NEW, il serait impossible d'arrêter les connexions issues de l'extérieur vers le réseau local, puisqu'il faudrait à nouveau autoriser le retour de paquets NEW. Pour rendre les choses encore plus compliquées, il existe de nombreux autres états internes qui sont utilisés pour les connexions TCP à l'intérieur du noyau, mais qui ne sont pas disponibles dans l'espace utilisateur. Brièvement, ils respectent les états standards spécifiés dans le documentRFC 793 - Transmission Control Protocol aux pages 21-23.
Comme vous pouvez le voir, c'est tout à fait simple, du point de vue de l'utilisateur. Cependant, en regardant la construction complète du point de vue du noyau, c'est un peu plus difficile. Voyons un exemple. Regardons exactement comment les états de connexion changent dans la table /proc/net/ip_conntrack. Le premier état est rapporté sur le reçu d'un premier paquet SYN dans la connexion.
tcp 6 117 SYN_SENT src=192.168.1.5 dst=192.168.1.35 sport=1031 \
dport=23 [UNREPLIED] src=192.168.1.35 dst=192.168.1.5 sport=23 \
dport=1031 use=1
Comme nous l'indique l'entrée ci-dessus, nous avons un état précis dans lequel un paquet SYN a été envoyé, (le drapeau SYN_SENT est placé), et pour lequel aucune réponse n'a été envoyée (en témoigne le drapeau [UNREPLIED]). L'état interne suivant sera joint quand nous verrons un autre paquet dans l'autre direction.
tcp 6 57 SYN_RECV src=192.168.1.5 dst=192.168.1.35 sport=1031 \
dport=23 src=192.168.1.35 dst=192.168.1.5 sport=23 dport=1031 \
use=1
Maintenant nous avons reçu un SYN/ACK correspondant en retour. Dès que ce paquet a été reçu, l'état change encore une fois, cette fois vers SYN_RECV. SYN_RECV nous indique que le SYN d'origine a été délivré correctement et que le SYN/ACK en retour passe aussi à travers le pare-feu proprement. D'ailleurs, cette entrée de traçage de connexion a vu le trafic dans les deux directions et considère désormais qu'il y a été répondu. Ceci n'est pas explicite, mais nous assumons, comme l'était le drapeau [UNREPLIED] au-dessus. L'étape finale sera atteinte lorsque nous aurons vu le ACK dans l'établissement d'une liaison à trois voies.
tcp 6 431999 ESTABLISHED src=192.168.1.5 dst=192.168.1.35 \
sport=1031 dport=23 src=192.168.1.35 dst=192.168.1.5 \
sport=23 dport=1031 [ASSURED] use=1
Dans le dernier exemple, nous avons obtenu le ACK final dans l'établissement d'une liaison à trois voies et la connexion a pris l'état ESTABLISHED, pour autant que les mécanismes internes de Iptables soient avisés. Normalement, le flux de données sera ASSURED maintenant.
Une connexion peut aussi être dans l'état ESTABLISHED, mais pas [ASSURED]. Ceci survient lorsque nous avons une connexion captée ouverte (nécessite la patch tcp-window-tracking et le ip_conntrack_tcp_loose placé à 1 ou plus haut). Par défaut, sans la patch tcp-window-tracking, c'est ce comportement qui s'applique, et il n'est pas modifiable.
Quand une connexion TCP est close, elle est faite de cette façon et prend les états suivants.
Comme vous pouvez le voir, la connexion n'est jamais réellement fermée jusqu'à ce que le ACK soit envoyé. Notez que cette figure décrit simplement comment elle est fermée dans des circonstances normales. Une connexion peut aussi, par exemple, être fermée par l'envoi d'un RST (reset), si celle-ci a été refusée. Dans ce cas, la connexion sera fermée immédiatement.
Quand la connexion TCP a été fermée, elle entre dans l'état TIME_WAIT, qui est, par défaut, de 2 minutes. Ceci est utilisé pour que tous les paquets sortis puissent encore passer à travers notre table de règles, même après que la connexion soit fermée. Ceci est employé comme une sorte de tampon pour que les paquets qui ont été immobilisés dans un ou d'autres routeurs engorgés puissent encore passer le pare-feu, ou vers une autre fin de connexion.
Si la connexion est réinitialisée par un paquet RST, l'état est modifié en CLOSE. Ce qui indique que la connexion a, par défaut, 10 secondes avant que la connexion complète soit fermée définitivement. Les paquets RST ne sont pas reconnus dans aucun sens, et couperont la connexion directement. Il existe aussi d'autres états que ceux dont nous avons parlé. Voici une liste complète des états qu'un flux TCP peut prendre, et leurs valeurs de délai d'attente.
Tableau 2. États internes
État | Délai |
---|---|
NONE | 30 minutes |
ESTABLISHED | 5 jours |
SYN_SENT | 2 minutes |
SYN_RECV | 60 secondes |
FIN_WAIT | 2 minutes |
TIME_WAIT | 2 minutes |
CLOSE | 10 secondes |
CLOSE_WAIT | 12 heures |
LAST_ACK | 30 secondes |
LISTEN> | 2 minutes |
Ces valeurs ne sont pas absolues. Elles peuvent changer en fonction des versions du noyau, et également par le système de fichiers dans les variables /proc/sys/net/ipv4/netfilter/ip_ct_tcp_*. Les valeurs par défaut seront, cependant, justes en pratique. Ces valeurs sont établies en secondes.
Notez aussi que le domaine utilisateur de la machine d'état ne doit pas voir les drapeaux TCP (i.e., RST, ACK et SYN sont des drapeaux) placés dans les paquets TCP. C'est généralement pas recommandé, car vous pourriez autoriser les paquets dans l'état NEW à traverser le pare-feu, mais quand vous spécifiez le drapeau NEW, vous indiquez les paquets SYN.
Ce n'est pas ce qui se produit avec l'implémentation de l'état; ce qui veut dire, même un paquet avec aucun bit de placé ou un drapeau ACK, sera compté comme NEW. Ceci peut être utilisé pour faire de la redondance de pare-feu, mais c'est en général très déconseillé pour un réseau domestique, dans lequel vous avez un seul pare-feu. Pour en savoir plus vous pouvez utiliser la commande expliquée dans la section Paquets état NEW sans bit SYN placé de l'annexe Problèmes et questions courants. Un autre moyen est d'installer l'extension tcp-window-tracking depuis patch-o-matic, et de placer /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_loose à zéro, le pare-feu effacera tous les paquets NEW en ayant le drapeau SYN placé.
XI-E. Connexions UDP▲
Les connexions UDP ne sont pas des connexions à part entière, mais plutôt des connexions "apatrides". Il y a plusieurs raisons pour cela, la principale parce qu'elles ne contiennent aucun établissement ou fermeture de connexion; la plupart n'ont pas de liaison. En recevant deux datagrammes UDP dans un ordre spécifique, on ne peut savoir dans quel ordre ils ont été envoyés. Cependant, il est toujours possible de placer des états sur les connexions dans le noyau. Voyons comment une connexion peut être tracée et à quoi elle ressemblerait dans le conntrack.
Comme on peut le voir, la connexion circule presque exactement de la même façon qu'une connexion TCP. Ceci, du point de vue de l'utilisateur. En interne, l'information conntrack est un peu différente, mais intrinsèquement les détails sont les mêmes. Premièrement, regardons les entrées après que le paquet UDP initial ait été envoyé.
udp 17 20 src=192.168.1.2 dst=192.168.1.5 sport=137 dport=1025 \
[UNREPLIED] src=192.168.1.5 dst=192.168.1.2 sport=1025 \
dport=137 use=1
Comme vous pouvez le voir entre la première et deuxième valeur, c'est un paquet UDP. Le premier est le nom du protocole, le second le numéro du protocole. C'est identique pour une connexion TCP. La troisième valeur indique combien de secondes cet état s'est maintenu. Après cela, nous avons les valeurs du paquet que nous avons vu et les probabilités que les paquets sur cette connexion nous joignent depuis l'expéditeur. Ce sont la source, la destination, le port source et le port destination. À ce point le drapeau [UNREPLIED] nous indique qu'il n'y a pas eu de réponse au paquet. Enfin, nous avons une courte liste de probabilités de retour de paquets. Notez que les dernières entrées sont en ordre inverse des premières valeurs. Le délai d'attente est de 30 secondes dans ce cas, par défaut.
udp 17 170 src=192.168.1.2 dst=192.168.1.5 sport=137 \
dport=1025 src=192.168.1.5 dst=192.168.1.2 sport=1025 \
dport=137 [ASSURED] use=1
À ce point le serveur a vu une réponse au premier paquet envoyé et la connexion est maintenant considérée comme ESTABLISHED. Ce n'est pas indiqué dans le traçage de connexion comme vous pouvez le voir. La principale différence est que le drapeau [UNREPLIED] est maintenant fourni. D'ailleurs, le temps d'attente par défaut a changé pour passer à 180 secondes - mais dans cet exemple il a été décrémenté pour passer à 170 secondes - avec un délai de 10 secondes, il sera de 160 secondes. Une chose qui a été oubliée et qui peut changer légèrement est le drapeau [ASSURED] décrit ci-dessus. Pour placer le fanion [ASSURED] sur un traçage de connexion, il doit y avoir un paquet en réponse au paquet NEW.
udp 17 175 src=192.168.1.5 dst=195.22.79.2 sport=1025 \
dport=53 src=195.22.79.2 dst=192.168.1.5 sport=53 \
dport=1025 [ASSURED] use=1
Ici, la connexion est assurée. La connexion a exactement le même aspect que dans l'exemple précédent. Si cette connexion n'est pas utilisée dans les 180 secondes, elle est hors délai. 180 secondes est comparativement une valeur basse, mais qui devrait être suffisante dans la plupart des cas. Cette valeur est réinitialisée complètement pour chaque paquet qui correspond à la même entrée et passe à travers la pare-feu, comme pour tous les états internes.
XI-F. Connexions ICMP▲
Les paquets ICMP sont loin d'être un flux véritable, car ils sont seulement utilisés pour le contrôle et n'établissent jamais aucun type de connexion. Il existe quatre types ICMP qui généreront cependant des paquets en retour, et qui possèdent deux états différents. Ces messages ICMP peuvent prendre les états NEW et ESTABLISHED. Les types ICMP dont nous parlons sont les requêtes et réponse Echo, les requêtes et réponses Timestamp, les requêtes et réponses Information, et enfin les requêtes et réponses de masque d'Adresse. En dehors de ça, les requêtes d'horodatage et d'information sont obsolètes et seront probablement effacées. Cependant, les messages Echo sont utilisés dans plusieurs cas comme le ping sur des hôtes. Les requêtes de masque d'adresse ne sont pas utilisées souvent, mais peuvent être utiles quelques fois. Pour en avoir une idée, voyons l'image suivante.
Comme vous pouvez le voir dans l'image ci-dessus, l'hôte envoie une requête écho vers la cible, laquelle est considérée comme NEW par le pare-feu. La cible répond alors avec un écho que le pare-feu considère comme état ESTABLISHED. Quand la première requête écho a été vue, les entrées état suivantes se dirigent dans le ip_conntrack.
icmp 1 25 src=192.168.1.6 dst=192.168.1.10 type=8 code=0 \
id=33029 [UNREPLIED] src=192.168.1.10 dst=192.168.1.6 \
type=0 code=0 id=33029 use=1
Ces entrées semblent un peu différentes des états standards pour TCP et UDP. Le protocole est présent, et la temporisation, de même que les adresses source et destination. Le problème survient après. Nous avons maintenant trois nouveaux champs appelés type, code et id. Il n'y a rien de spécial, le champ type contient le type ICMP et le champ code contient le code ICMP. Toutes les variables sont présentées dans l'annexe Types ICMP. Le dernier champ id, contient l'ID ICMP. Chaque paquet ICMP obtient un ID quand il est envoyé, et lorsque le destinataire reçoit le message ICMP, il place le même ID dans le nouveau message ICMP, que l'expéditeur reconnaîtra dans la réponse et pourra se connecter avec la requête ICMP correcte.
Dans le champ suivant, nous avons reconnu le drapeau [UNREPLIED]. Ce fanion nous indique que nous observons une entrée de traçage de connexion, dont le trafic est dans une direction. Enfin, nous voyons la probabilité de réponse à un paquet ICMP, qui est l'inversion des adresses IP source et destination. Comme pour le type et le code, ils ont été modifiés en valeurs correctes pour le paquet de retour, ainsi une requête écho est changée en réponse écho et ainsi de suite. L'ID ICMP est préservé depuis le paquet requête.
Le paquet réponse est considéré comme ESTABLISHED, ainsi que nous l'avons déjà expliqué. Cependant, nous pouvons savoir avec certitude qu'après la réponse ICMP, il n'y aura plus de trafic régulier dans la même connexion. Pour cette raison, l'entrée de traçage de connexion est détruite une fois que la réponse soit passée à travers la structure de Netfilter.
Dans chacun des cas ci-dessus, la requête est considérée comme NEW, tandis que la réponse est considérée comme ESTABLISHED. Voyons cela de plus près. Quand le pare-feu voit un paquet requête, il le considère comme NEW. Quand l'hôte envoit un paquet en réponse à la requête il est considéré comme ESTABLISHED.
Notez que cela indique que le paquet réponse doit apparier le critère donné par l'entrée de traçage de connexion pour être considéré comme établi, de la même façon que tous les autres types de trafic.
Les requêtes ICMP ont un délai par défaut de 30 secondes, que vous pouvez modifier dans l'entrée /proc/sys/net/ipv4/netfilter/ip_ct_icmp_timeout. C'est, en général, une bonne valeur de temps d'attente, car elle permet de capturer la plupart des paquets en transit.
Une autre partie très importante de ICMP est le fait qu'il est utilisé pour indiquer aux hôtes les événements au niveau des connexions spécifiques UDP et TCP ou des tentatives de connexions. Pour cette raison, les réponses ICMP seront très souvent reconnues comme RELATED. Un exemple simple est le ICMP Host unreachable ou ICMP Network unreachable. Ceci est toujours généré en retour vers notre hôte si il tente une connexion vers quelque autre hôte, mais que le réseau ou l'hôte en question ne soit pas connecté, ainsi le dernier routeur essayant de joindre le site répondra par un message ICMP nous l'indiquant. Dans ce cas, la réponse ICMP est considérée comme un paquet RELATED. L'image suivante explique ceci.
Dans l'exemple ci-dessus, nous envoyons un paquet SYN vers une adresse spécifique. Ceci est considéré comme une connexion NEW par le pare-feu. Cependant, le réseau que le paquet essaie de joindre est injoignable, donc un routeur va nous renvoyer une erreur ICMP indiquant que le réseau est injoignable. Le code de traçage de connexion peut reconnaître ce paquet comme RELATED, ainsi la réponse ICMP est correctement envoyée au client. En attendant, le pare-feu a détruit l'entrée de traçage de connexion depuis qu'il a eu connaissance du message d'erreur.
Le même comportement que ci-dessus est observé avec les connexions UDP avec des problèmes identiques que précédemment. Tous les messages ICMP envoyés en réponse aux connexions UDP sont considérés comme RELATED. Voyons l'image suivante.
Un paquet UDP est envoyé à un hôte. Cette connexion UDP est considérée comme NEW. Cependant, le réseau est interdit administrativement par un pare-feu quelconque ou un routeur. Donc, notre pare-feu reçoit un "ICMP Network Prohibited" en retour. Le pare-feu sait que ce message d'erreur ICMP est en relation avec la connexion UDP déjà ouverte et envoit un paquet RELATED au client. À ce niveau, le pare-feu détruit les entrées de traçage de connexion, et le client reçoit le message ICMP.
XI-G. Connexions par défaut▲
Dans certains cas, la machine conntrack ne sait pas comment traiter un protocole spécifique. Ceci se produit lorsqu'elle ne connait pas le protocole en particulier, ou ne sait pas comment il fonctionne. Dans ces cas là, elle utilise un comportement par défaut. Ce comportement est utilisé sur, par exemple, NETBLT, MUX et EGP. Ce comportement ressemble au traçage de connexion UDP. Le premier paquet est considéré comme NEW, et le trafic en réponse comme ESTABLISHED.
Quand ce comportement par défaut est utilisé, tous les paquets ont la même valeur de délai par défaut. Ceci peut être paramétré via la variable /proc/sys/net/ipv4/netfilter/ip_ct_generic_timeout. La valeur par défaut est ici de 600 secondes, soit 10 minutes. En fonction du trafic, ceci peut avoir besoin d'être modifié. Spécialement si vous renvoyez le trafic par satellite, ce qui peut prendre un long moment.
XI-H. Protocoles complexes et traçage de connexion▲
Certains protocoles sont plus complexes que d'autres. Ce qui fait que, lorsqu'ils interfèrent avec du traçage de connexion ils peuvent être plus difficiles à tracer correctement. De bons exemples en sont les protocoles ICQ, IRC et FTP. Chacun des ces protocoles transporte l'information dans les données utiles des paquets, et donc nécessitent un traçage de connexion spécial pour fonctionner correctement.
Voici une liste des protocoles complexes supportés par le noyau Linux, et la version du noyau dans laquelle il a été implémenté.
Tableau 3. Support des protocoles complexes
Nom du protocole | Version du noyau |
---|---|
FTP | 2.3 |
IRC | 2.3 |
TFTP | 2.5 |
Amanda | 2.5 |
- FTP
- IRC
- TFTP
Prenons le protocole FTP comme premier exemple. Ce protocole ouvre en premier une seule connexion appelée contrôle de session FTP. Quand nous lançons des commandes dans cette session, d'autres ports sont ouverts pour transporter le reste des données relatives à ces commandes spécifiques. Ces connexions peuvent être réalisées de deux manières, de façon active ou passive. Quand une connexion est en mode actif, le client FTP envoie au serveur un port et une adresse IP pour se connecter. Après cela, le client FTP ouvre le port et le serveur, le connecte depuis un domaine de ports non privilégiés (>1024) et envoie les données sur celui-ci.
Le problème est que le pare-feu ne connaît pas ces connexions, car elles ont été négociées dans les données utiles du protocole. À cause de ça, le pare-feu sera incapable de savoir s'il doit laisser le serveur connecté au client sur ces ports spécifiques.
La solution est d'ajouter une aide spéciale au module de traçage de connexion qui scannera les données dans le contrôle de connexion à la recherche d'information et de syntaxes spécifiques. Quand il fonctionne avec l'information correcte, il indique cette information spécifique comme RELATED et le serveur sera capable de tracer la connexion. Voyons l'image suivante pour comprendre les états quand le serveur FTP a envoyé le retour de connexion au client.
Le FTP passif fonctionne de la façon inverse. Le client FTP indique au serveur qu'il désire certaines données spécifiques, le serveur lui répond avec l'adresse IP à connecter et le port. Le client pourra, au reçu de ces données, se connecter à ce port depuis son propre port 20 (port FTP), et obtenir les données en question. Si vous avez un serveur FTP derrière votre pare-feu, vous aurez besoin de ce module en supplément de vos modules standards Iptables pour permettre aux clients sur l'Internet de se connecter au serveur FTP correctement. C'est la même chose si vous êtes très restrictif pour vos utilisateurs, et les laissez se connecter seulement aux serveurs HTTP et FTP sur l'Internet, et que vous bloquez tous les autres ports. Regardons l'image suivante à propos du FTP passif.
Certains assistants conntrack sont déjà disponibles dans le noyau lui-même. Plus spécifiquement, les protocoles FTP et IRC possèdent des assistants. Si vous ne trouvez pas les assistants conntrack dont vous avez besoin dans le noyau, vous devriez regarder l'arborescence patch-o-matic dans le domaine utilisateur Iptables. L'arborescence patch-o-matic peut contenir d'avantage d'assistants conntrack, comme ceux des protocoles ntalk ou H.323. S'ils ne sont pas disponibles dans l'arborescence patch-o-matic, vous avez plusieurs options. Soit vous cherchez dans le source CVS d'Iptables, si il a été récemment modifié, soit vous contactez la liste de diffusion Netfilter-devel et demandez leurs disponibilités. Sinon, et s'il n'y a pas de projet en vue, lisez le Rusty Russell's Unreliable Netfilter Hacking HOW-TO dont le lien est dans Autres ressources et liens.
Les assistants conntrack peuvent être soit compilés statiquement dans le noyau, soit en modules. S'ils sont compilés en modules, vous pouvez les charger avec les commandes suivantes :
modprobe ip_conntrack_ftp
modprobe ip_conntrack_irc
modprobe ip_conntrack_tftp
modprobe ip_conntrack_amanda
Notez que la traçage de connexion n'a rien à voir avec le NAT, et donc vous pouvez avoir besoin de d'avantage de modules si vous NATez les connexions. Par exemple, si vous voulez NATer et tracer les connexions FTP, vous aurez besoin du module NAT. Tous les assistants NAT débutent avec ip_nat_ et suivant; exemple, l'assistant FTP NAT sera nommé ip_nat_ftp et le module IRC nommé ip_nat_irc. Les assistants conntrack suivent la même convention, et donc l'assistant IRC conntrack s'appellera ip_conntrack_irc, alors que l'assistant FTP conntrack sera nommé ip_conntrack_ftp. Comme dans la sortie d'écran ci-dessus.