Tuto Netfiler1

De Page Personnelle de Cédric Blancher.

Sommaire

[modifier] Présentation

Les noyaux de la série 2.4 introduisent un nouveau système de filtrage de paquet appelé Netfilter. Par Netfilter, on désigne toute l'architecture présente au sein du noyau. Un outil permet de configurer cette architecture : c'est iptables. Sur Internet ou dans la littérature, on utilise iptables pour désigner l'ensemble. Mais bon, comme on est ici pour apprendre à devenir des vrais durs de dur, on va faire le distinguo.

Netfilter possède toutes les fonctionnalités d'ipchains, auxquelles il ajoute le filtrage à état (cf fiche n°2) et une traduction d'adresses complète (cf fiche n°3). Il introduit en outre un nombre conséquent de nouvelles options pour identifier des éléments particuliers dans les paquets IP. Enfin, il s'appuie sur une nouvelle architecture, plus modulaire et extensible.

Mais trêve de discussion, attaquons le vif du sujet.


[modifier] Architecture

Je sais que vous êtes impatients d'en découdre, mais il va falloir patienter un peu ;) Je vais d'abord vous présenter les notions de base qui vous permettront de comprendre le fonctionnement de Netfiler et donc de pouvoir, à terme, écrire vos règles tout seul.

Netfilter s'appuie sur des chaînes dans lesquelles passent les paquets. Elles sont au nombre des 5 :

  • PREROUTING
  • INPUT
  • FORWARD
  • OUTPUT
  • POSTROUTING

Lorsqu'un paquet arrive sur votre machine, selon sa destination, il traverse certaines chaînes. Les chaînes s'organisent comme suit :

	PREROUTING --- FORWARD --- POSTROUTING
		    |		|
		    |		|
		  INPUT	      OUTPUT
		    |		|
		     \         /
		    applications
		    locales

Ainsi, si un paquet est destiné à votre machine, il traversera les chaînes PREROUTING, puis INPUT. S'il est destiné à traverser votre machine, il passera par PREROUTING, FORWARD, puis POSTROUTING. Enfin, un paquet qui sortira de votre machine passera par OUTPUT et POSTROUTING.

Pour filtrer les paquets, on va introduire des règles dans les chaînes. Pour y arriver, on passe par une table. Une table définit le comportement général de la règle qu'on va appliquer. Il y a trois tables :

  • filter qui sert à filtrer les paquets
  • nat qui sert à modifier la source et/ou la destination de paquet
  • mangle qui sert à modifier certains champs dans les entêtes des paquets

Nous détaillerons ce concept dans la troisième fiche. Retenez seulement pour le moment que chaque table ne permet d'agir que sur certaines chaînes et que celle qui est utilisée par défaut est la table filter, qui agit sur les chaînes INPUT, FORWARD et OUTPUT. Nous verrons en fin de fiche un usage de la table nat, mais nous la détaillerons dans la fiche n°3.

Une règle peut être décomposée en quatre partie :

  • la table a laquelle elle s'applique (facultative, filter par défaut)
  • la chaîne sur laquelle on la greffe
  • la définition des paquets qu'elle veut reconnaicirc;tre
  • une action, définie par une cible

Une cible correspond la décision prise lorsqu'un paquet est reconnu par la règle. Une cible peut être une cible pré-compilée, une extension ou une chaîne utilisateur. Netfilter possède deux cibles dites pré-compilées :

  • ACCEPT : le paquet a le droit de passer
  • DROP : le paquet est rejeté et est détruit

Ces cibles sont incluses dans Netfilter. Les extensions (cf. fiche 3) sont des cibles ajoutées à Netfilter via des modules qui permettent des traitements plus spécifiques sur les paquets. Alors que les cibles pré-compilées sont valide pour l'ensemble du framework Netfilter, donc pour toutes les chaînes, dans toutes les tables, les extensions peuvent (et le sont souvent) être spécifiques à une table, voire même à certaines chaînes de cette table. Enfin, les chaînes utilisateur (cf. fiche 2) sont des chaîne que l'utilisateur peut créer pour ses besoins propres.

Lorsqu'un paquet est reconnu par une règle, il sort de la chaîne et l'action lui est appliquée. Si l'action est ACCEPT, il continue son chemin dans l'architecture, passant à l'étape suivante. Lorsqu'un paquet traverse une chaîne sans avoir été reconnu par une règle, on lui applique la politique de la chaîne. La politique est l'action par défaut de la chaîne. Cette action ne peut être qu'une cible pré-compilée, donc ACCEPT ou DROP. Ce ne sera jamais une extension ou une chaîne utilisateur.

C'est l'outil iptables qui permet de construire ces règles. Entrons donc dans le vif du sujet, et voyons comment on s'en sert.


[modifier] Syntaxe

À partir de maintenant, nous travaillons sur la table filter. Une règle se construit comme suit :

	iptables <opération sur chaîne> [-t <table>] <motif de reconnaissance> -j <cible>

Comme la table filter est la table par défaut, nous n'utiliserons pas l'option -t.

Les opérations sur les chaînes sont :

  • -A <chaîne> : ajoute une règle à la fin d'une chaîne
  • -I <chaîne> <position> : insère une règle à la position donnée
  • -D <chaîne> <position> : supprime la chaîne à la position donnée
  • -R <chaîne> <position> : remplace la chaîne à la position donnée
  • -F <chaîne> : efface toutes les règles de la chaîne
  • -P <chaîne> <politique> : définit la politique par défaut de la chaîne

Voyons donc par exemple comment dire à Netfilter de laisser passer un paquet HTTP à destination de notre machine :

	iptables -A INPUT -p tcp --dport 80 -j ACCEPT

Comme le paquet nous est destiné, il arrive par la chaiîne INPUT à laquelle nous ajoutons la règle par -A INPUT (attention aux majuscules !). Ensuite, nous définissons le paquet que nous voulons reconnaiître. Un paquet HTTP est un paquet TCP a destination du port 80. Nous spécifions donc la protocole par l'option -p et le port destination par l'option --dport. Enfin, nous spécifions la décision à prendre, à savoir laisser passer le paquet (-j ACCEPT).

On peut spécifier des plages de ports en faisant par exemple --dport 20:25 pour accepter les ports compris entre 20 et 25 compris. Si on ne précise par l'un des deux arguments, cela voudra dire qu'on ira jusqu'à la limite de la plage de ports. Ainsi, :25 correspondra à tous les ports en dessous de 25 compris tandis que 25: correspondra à tous les ports au dessus de 25 compris. Si on veut spécifier le port source, on utilise --sport.

Regardons à présent notre jeu de règles. Cela se fait par la commande :

	iptables -L [chaîne]

Par défaut, iptables listera toutes les chaînes. iptables -L nous donnera :

	Chain INPUT (policy ACCEPT)
	target     prot opt source               destination         
	ACCEPT     tcp  --  anywhere             anywhere           tcp dpt:www 

	Chain FORWARD (policy ACCEPT)
	target     prot opt source               destination         

	Chain OUTPUT (policy ACCEPT)
	target     prot opt source               destination         	

On voit ici les trois chaînes de la table filter, avec leur politique (ACCEPT pour les trois). Dans la chaîne INPUT, nous voyons la règle que nous venons d'ajouter en première position. On peut y lire successivement la cible (ACCEPT), le protocole (TCP), les options (aucune), la source (n'importe où), la destination (idem) et le motif de reconnaissance (TCP, port destination 80).

Quand vous ne spécifiez pas un argument, iptables comprend que vous ne voulez pas qu'il soit pris en compte dans le filtrage. Ainsi, comme nous n'avons précisé ni adresse source, ni adresse destination, il comprend que n'importe laquelle convient.

Dans une connexion TCP, les clients se connectent depuis un port au dessus de 1024. Nous allons donc spécifier les ports source. Nous allons donc remplacer la règle que nous venons d'ajouter. Comme c'est la règle n°1, nous allons faire :

	iptables -I INPUT 1 -p tcp --sport 1024: --dport 80 -j ACCEPT

Supposons que nous ayons un serveur FTP et que nous voulions le rendre accessible aussi. Nous allons donc entrer :

	iptables -A INPUT -p tcp --sport 1024: --dport 21 -j ACCEPT

Et comme nous ne voulons pas que d'autres choses entrent, nous passons la politique de la chaîne à DROP :

	iptables -P INPUT DROP

En fait, FTP est un protocole un peu complique qui nécessite que j'ouvre aussi le port 20 et les ports au dessus de 1024 pour le faire fonctionner :

	iptables -A INPUT -p tcp --sport 1024: --dport 20 ! --syn -j ACCEPT
	iptables -A INPUT -p tcp --sport 1024: --dport 1024: -j ACCEPT

L'option --syn désigne un paquet qui initie une connexion TCP. Le signe ! introduit la négation. L'argument ! --syn permet donc de désigner un paquet qui n'est pas un paquet d'initiation de connexion.

Regardons à présent notre chaîne INPUT (iptables -L INPUT) :

	Chain INPUT (policy DROP)
	target     prot opt source               destination
	ACCEPT     tcp  --  anywhere             anywhere           tcp spts:1024:65535 dpt:www 
	ACCEPT     tcp  --  anywhere             anywhere           tcp spts:1024:65535 dpt:ftp 
	ACCEPT     tcp  --  anywhere             anywhere           tcp spts:1024:65535 dpt:ftp-data flags:!SYN,RST,ACK/SYN 
	ACCEPT     tcp  --  anywhere             anywhere           tcp spts:1024:65535 dpts:1024:65535 

On y voit toutes les règles de la chaîne, avec leurs attributs et leur cible.

Quand un paquet traverse la chaîne, les règles lui sont appliquées dans l'ordre. De fait, si une règle reconnaît le paquet, il sortira de la chaîne et ne sera pas comparé aux autres règles. C'est un point auquel il faut penser : l'ordre des règles est important !

On pourrait en outre limiter ces règles à certaines adresses source en utilisant l'option -s . Nous pourrions aussi spécifier l'adresse destination avec l'option -d <destination>. Nous pourrions en outre spécifier l'interface à laquelle s'applique la règle. Nous détaillerons comment dans la fiche n°2.

Nous laisserons la politique de la chaîne OUTPUT à ACCEPT puisque nous ne voulons pas restreindre le trafic que notre machine émet. Les options que nous venons de voir sont communes à la table filter et s'appliquent donc à nos trois chaînes.

Le but de cette article n'est pas de vous proposer une liste exhaustive des options de la commande iptables. Pour cela, vous disposez d'une excellent page de man (man iptables) et d'un excellent HOWTO disponible à sur http://netfilter.samba.org/unreliable-guides/fr/packet-filtering-HOWTO.html.


[modifier] Le forwarding

Voyons à présent comment on gère le forwarding des paquets à travers votre machine. Nous finirons l'article par un exemple de partage de connexion sur une machine qui héberge un serveur HTTP et un serveur FTP.

Votre machine peut servir de firewall, ou pare-feu, en filtrant le trafic qu'elle route entre ses interfaces. Pour que votre machine puisse router, il faut activer ce qu'on appelle l'IP forwarding. Ceci se fait avec la commande :

	echo 1 > /proc/sys/net/ipv4/ip_forward

En passant la valeur de /proc/sys/net/ipv4/ip_forward à 1, nous venons de transformer notre machine en routeur. Les paquets que nous routons peuvent être filtrés dans la chaîne FORWARD.

Actuellement, comme la politique de la chaîne FORWARD est ACCEPT, tous les paquets passent. quand on active l'IP forwarding, on voudra, pour des raisons sécurité, faire en sorte que la machine ne route que ce qu'on lui spécifie. On passera donc la politique de la chaîne FORWARD à DROP :

	iptables -P FORWARD DROP

Ensuite, nous autorisons des paquets à traverser :

	iptables -A FORWARD -s 192.168.1.0/24 -j ACCEPT

Ainsi, j'autorise les paquets venant du réseau 192.168.1.0-192.168.1.255 à traverser ma machine. Evidemment, si je veux que des connexions s'établissent, je vais autoriser le retour :

	iptables -A FORWARD -d 192.168.1.0/24 -j ACCEPT

Notre jeu de règles ressemble alors à cela :

	Chain INPUT (policy DROP)
	target     prot opt source               destination         
	ACCEPT     tcp  --  anywhere             anywhere           tcp spts:1024:65535 dpt:www 
	ACCEPT     tcp  --  anywhere             anywhere           tcp spts:1024:65535 dpt:ftp 
	ACCEPT     tcp  --  anywhere             anywhere           tcp spts:1024:65535 dpt:ftp-data flags:!SYN,RST,ACK/SYN 
	ACCEPT     tcp  --  anywhere             anywhere           tcp spts:1024:65535 dpts:1024:65535 

	Chain FORWARD (policy DROP)
	target     prot opt source               destination         
	ACCEPT     all  --  192.168.1.0/24       anywhere           
	ACCEPT     all  --  anywhere             192.168.1.0/24     

	Chain OUTPUT (policy ACCEPT)
	target     prot opt source               destination

Sauf que ce réseau est privé. Les adresses qu'il utilise ne sont pas utilisables sur Internet. Pour lui permettre d'accéder à Internet, nous allons vouloir partager une connexion classique qui relie notre machine à Internet. Le partage de connexion met en oeuvre des mécanisme de traduction d'adresses, plus couramment appelé NAT. Nous allons donc utiliser la table nat pour réaliser cette opération. Je ne vous détaille pas la manipulation, ce sera le sujet de la 3e ficher à laquelle je vous renvoie pour plus de détails. La commande sera :

	iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE

Cette commande dit à Netfilter de masquer tout le trafic venant du réseau 192.168.1.0/24 en remplaçant l'adresse IP source par celle de l'interface de sortie des paquets, donc votre adresse IP publique sur Internet. Quand un serveur vous répondra, Netfilter fera automatiquement l'opération inverse pour que le partage de connexion se fasse de manière transparente. Comme je vous le disais tout à l'heure, FTP est un protocole un peu compliqué qui nécessite (comme dans ipchains) l'ajout d'un module spécialisé en mémoire par la commande :

	modprobe ip_nat_ftp

Nous détaillerons le pourquoi du comment dans la fiche n°2.

Il ne vous restera plus qu'à donner l'adresse IP interne de votre machine comme passerelle par défaut aux postes de votre réseau, et vous pourrez accéder aux joies d'Internet en groupe !


Seconde fiche

Navigation
autres
Locations of visitors to this page

No software patents !

Valid XHTML 1.0 Transitional

Valid CSS 2.1