Netfilter est pratiquement une série de ``hooks'' (accroches) à quelques endroits dans la pile de protocoles (pour le moment, IPv4, IPv6, DECnet). Le shema de traversé ressemble (idéalement) à cela:
Un paquet qui traverse le système Netfilter:
--->[1]--->[ROUTE]--->[3]--->[4]--->
| ^
| |
| [ROUTE]
v |
[2] [5]
| ^
| |
v |
Sur la gauche, c'est la ou les paquets arrivent : en ayant passé un simple test de sanité (par exemple: pas coupé, IP checksum est OK, et que ce n'est pas un paquet reçu en promiscuous), ils sont passés au ``hook'' NF_IP_PRE_ROUTING [1] du canevas de netfilter.
Ensuite, il entrent dans le code de routage, qui décide si oui ou non le paquet est destiné à une autre interface, ou pour un processus en local. Le code de routage peut éventuellement détruire le paquet si il n'est pas routable.
Si il est destine pour la machine elle même, le canevas netfilter est appellé pour le hook NF_IP_LOCAL_IN [2], avant d'être passé au processus, si il y en a un.
Si à la place le paquet est destiné pour une autre interface, le canevas netfilter est appellé pour le hook NF_IP_FORWARD [3].
Le paquet passe ensuite le dernier hook de netfilter, le NF_POST_ROUTING [4], avant d'être envoyé sur le cable.
Le hook NF_IP_LOCAL_OUT [5] est appellé pour les paquets qui sont générés localement. Ici vous pouvez voir que le routage ce fait après que ce hook est appellé : en fait, le code de routage est appellé avant (pour trouver l'adresse source IP, et quelques options IP) : si vous voulez modifier le routage, vous devez modifier le champs `skb->dst' par vous même, comme dans le code de NAT.
Maintenant nous avons un exemple de netfilter pour IPv4, vous pouvez voir quand chacun des hooks est activé. C'est l'essence même de netfilter.
Les modules kernel peuvent s'enregistrer pour écouter à chacun de ces hooks. Un module qui enregistre une fonction doit spécifier la priorité de cette fonctions à l'intérieur du hook. De telle sorte que quand ce hook est appellé par netfilter, le code réseaux central appellera les fonctions du hook dans l'ordre des priorités. Le module peut dire à netfilter de faire l'une de ces 5 choses :
Les autres parties de Netfilter (gérer les paquets queutés, et les commentaires cools) seront couverts dans la section kernel un peu plus tard.
Basé sur cette fondation, nous pouvons construire des manipulations de paquets relativement complexes, comme démontré dans les deux sections suivantes.
Un système de sélection de paquets appellé `iptables' a été construit par dessus le canevas netfilter. C'est le descendant direct de `ipchains' (qui descendait de `ipfwadm', qui venait lui meme de ipfw de BSD) mais amélioré car plus extensible. Les modules kernels peuvent demander à enregistrer une table nouvelle, et demander à ce qu'un paquet traverse un table donnée. Cette méthode de sélection de paquets est utilisée pour filtrer les paquets (la table `filter'), pour NAT (la table `nat') et pour modifier des paquets avant routage (la table `mangle').
Les hooks qui sont enregistrés avec netfilter sont comme suit (avec les fonctions de chaque hooks dans l'ordre ou ils sont appelles) :
--->PRE------>[ROUTE]--->FWD---------->POST------>
Conntrack | Filter ^ NAT (Src)
Mangle | | Conntrack
NAT (Dst) | [ROUTE]
(QDisc) v |
IN Filter OUT Conntrack
| Conntrack ^ Mangle
| | NAT (Dst)
v | Filter
Cette table, `filter', ne devrait jamais modifier les paquets : seulement les filtrer.
Un des avantages des filtres de iptables comparés à ceux de ipchains est que c'est petit et rapide, et que ça s'accroche dans netfilter aux points NF_IP_LOCAL_IN, NF_IP_FORWARD, et NF_IP_LOCAL_OUT. Ça veut dire que pour un paquet donné, il n'y a qu'une et un seule place pour le filtrer. Cela rend les choses bien plus simples pour l'utilisateur que ipchains ne l'était. Aussi, le fait que le canevas netfilter fournit l'interface input et output pour les hooks NF_IP_FORWARD signifie que beaucoup de types de filtrage sont rendus plus simples.
Note: J'ai porté les parties kernel de ipchains et de ipfwadm en modules par dessus le canevas netfilter. Cela permet l'usage des vieux utilitaires en userspace ipfwadm et ipchains, sans avoir à mettre à jour.
Voici la réaction de la table `nat', à qui l'on passe des paquets par deux hooks netfilter : pour les paquets qui ne sont pas générés localement, les hooks NF_IP_PRE_ROUTING et NF_IP_POST_ROUTING sont une place parfaite pour modifier respectivement la destination et la source d'un paquet. Si CONFIG_IP_NF_NAT_LOCAL est définie, le hook NF_IP_LOCAL_IN est utilisé pour modifier la destination des paquets générés localement.
Cette table est légèrement diffèrente de la table `filter', effectivement, seulement le premier paquet d'une nouvelle connection va traverser la table : le résultat de cette traversé est ensuite appliquée à tous les futurs paquets qui font partie de la même connection.
Je divise NAT en Source NAT (ou le premier paquet voit sa source être modifiée) et Destination NAT (ou le premier paquet voit sa destination être modifiée).
Le Masquerading est une forme spéciale de Source NAT, port-forwarding et transparent proxying sont des formes spéciales de Destination NAT. Elles sont toutes maintenant effectuées à l'aide du canevas NAT, plutôt que d'être des entités indépendantes.
La table de modification de paquets (la table `mangle') est utilisée pour des changements concrets des informations d'un paquet. Elle s'accroche à netfilter aux points NF_IP_PRE_ROUTING et NF_IP_LOCAL_OUT.
Le suivi des connections est fondamental pour NAT, mais il est implémenté dans un module à part entière. Cela permet une extension au code de filtrage de paquets pour simplement et proprement implémenter le suivi de connections (le module `state').
Cette nouvelle flexibilité fournit une opportunité de faire des choses vraiment cools, et de manière plus importante permet aux gens d'écrire des améliorations ou des remplacement complets.