Home (autres pages) Léa Linux TrustOn Me OpenVPN French Linux Doc Project

Fonctionnement du parefeu sous Linux

  • Fonctionnement
  • Le filtrage Linux, comment ça marche ?
    • Port source, port destination, mais c'est quoi tout ça, je comprends pas ?
    • Ok, belle analogie mais ça donne quoi sur le net ?
    • Définition de la police par défaut
  • Exercice pratique

Fonctionnement du parefeu sous Linux

Fonctionnement

Dans ce chapitre, on va approfondir le fonctionnement du parefeu Linux et construire un vrai bastion. Le but du parefeu est de réceptionner, filtrer et envoyer des trames IP. On pourra filtrer les protocoles TCP/IP, UDP/IP et ICMP. Avec ce parefeu, nous pourrons protéger notre LAN de vilains qui rôdent sur l'Internet...

Dans un chapitre précédent, nous avions configuré le parefeu avec des règles relativement permissives. Maintenant, nous allons cloisonné le parefeu et contrôler l'ensemble des flux entrants et sortants.

En bref, on définit une règle par défaut : rien ne rentre, rien ne sort. On autorisera au cas par cas... C'est très contraignant mais c'est ce qui pourra assurer que notre parefeu est totalement sûr.

Mais un parefeu sous linux, comment cela fonctionne ?

Tout d'abord, nous allons définir deux zones :

  • la zone "OUTSIDE" qui est la zone non sûre (là où rôdent les vilains pirates)
  • la zone "INSIDE" qui est la zone sûre, notre LAN

Parfois on entend parler de "DMZ" ce qui signifie "DeMilitarized Zone", c'est une zone tampon qui est accessible depuis l'Internet et depuis le LAN. On y place des serveurs qui seront potentiellement attaquées (même régulièrement). Il s'agit d'un second LAN moins sécurisé que l'INSIDE. Dans notre architecture, on n'utilise pas de DMZ.

Le filtrage Linux, comment ça marche ?

Le noyau Linux possède des fonctionnalités de filtrage de trames. Une trame arrive, que ce soit par l'une ou l'autre des interfaces ethernet, le parefeu va regarder si l'on a écrit une règle particulière pour cette trame et va appliquer la règle s'il y en a une.

Pour rappel, un paquet IP contient les informations nécessaires au routage du paquet, c'est à dire adresse IP source et adresse IP destination. Sur cette couche IP, on construit une couche session qui peut être TCP ou UDP. Cette couche apporte d'autres informations comme le port source et le port destination.

Port source, port destination, mais c'est quoi tout ça, je comprends pas ?

Ehm... Bon prenons par exemple un immeuble. Dans cette immeuble sans boîte à lettre, tu as un cordonnier, un forgeron et un informaticien (si on a toujours besoin d'un informaticien pour changer une ampoule). Tu as un trou dans tes chaussures et tu as donc besoin des services du cordonnier. Déjà, il va falloir que tu partes de chez toi pour aller jusqu'à cet immeuble, tu utilises l'adresse de l'immeuble pour trouver ta route. Une fois devant cet immeuble, si tu ne sais pas à quel étage se trouve le cordonier, tu vas rester planté devant l'immeuble... Par contre, si tu sais qu'il est au deuxième étage, tu vas aller taper à la bonne porte et le cordonnier pourra arranger tes chaussures. Ensuite tu repartiras chez toi en utilisant ton adresse à toi pour trouver ta route. Et puis tu remonteras à ton étage pour rentrer che toi. Les autres personnes de ton immeuble pourront aussi chercher les services de l'immeuble des services.

Ok, belle analogie mais ça donne quoi sur le net ?

Eh bien, tout d'abord mettons que nous avons sur le net un serveur qui propose un service FTP et un service HTTP (ou web). Ta machine et le serveur ont une adresse IP ce qui fait que tu pourras être "routé" de chez toi jusqu'à ce serveur. Une fois arrivé au serveur, grâce à l'adresse IP, tu vas demander un service spécifique, le service 21 pour le FTP ou le service 80 pour le HTTP. En fait, on appelle cela des ports et ils sont normalisés... Donc le port 20 et 21 sont les ports utilisés par le protocole FTP et le port 80 est utilisé par le protocole HTTP. Un programme spécifique "écoute" un port spécifique. Un serveur Web va écouter sur le port 80 et un serveur FTP sur le port 21. Un paquet IP arrive, le serveur va regarder l'entête TCP pour savoir vers quel port envoyer le paquet et donc vers quel programme. Le programme va prendre en compte la requête et y répondre par un paquet qui aura pour adresse source l'adresse du serveur, port source le port demandé par l'utilisateur et pour adresse destination ta machine et port destination le port ouvert par le programme qui a envoyé la requête.

Revenons maintenant au filtrage à proprement parlé... Linux utilise ce que l'on appelle des "chaînes" pour stocker les règles de filtrage. Un paquet est envoyé dans une chaîne où il est filtré en fonction des règles qui y ont été insérées.

En fait, que ce soit depuis l'Internet vers le LAN ou l'inverse, ou encore depuis l'Internet vers l'Internet ou depuis le LAN vers le LAN (par exemple si l'on fait tourner un serveur web sur notre parefeu, le paquet vient de l'Internet, est traité par notre serveur web et renvoyé sur l'Internet). Un paquet arrive sur notre parefeu. Il arrive tout d'abord dans le noeud PREROUTING où l'on peut exécuter certaines tâches (comme la translation d'adresses ou nattage).

Ensuite si le paquet est à destination d'une adresse de notre parefeu (82.46.73.52 depuis l'OUTSIDE ou 192.168.0.1depuis l'INSIDE) alors le paquet est envoyé dans la chaîne "INPUT". Sinon le paquet est envoyé dans la chaîne "FORWARD".

Si aucune règle n'a rejeté le paquet dans la chaîne INPUT, alors le paquet est traité par les processus locaux (par exemple un serveur WEB !) et envoyé dans la chaîne "OUTPUT" où il est filtré de nouveau.

Enfin les paquets des chaînes FORWARD et OUTPUT sont envoyés dans le noeud "POSTROUTING" où l'on peut exécuter certaines tâches (comme la translation d'adresses).

Je répète, un paquet est envoyé sur la chaîne FORWARD quand les adresses IP ne correspondent pas à l'une des adresses de notre serveur. Par exemple, depuis mon LAN je cherche à joindre le serveur de google. Je vais envoyer un paquet avec comme adresse IP source 192.168.0.2 et comme adresse destination 66.102.9.104. Le paquet arrive en PREROUTING puis il est routé en fonction de l'adresse destination. Linux regarde l'ensemble des adresses IP qu'il gère, 192.168.0.1 et 82.46.73.52, et décide que 66.102.9.104 n'appartient pas à ses adresses, il l'envoie dans la chaîne FORWARD et ce paquet n'arrivera jamais jusqu'aux programmes qui tournent sur notre parefeu. Ce paquet ne doit pas être traité par notre serveur mais par le serveur de Google.

Si l'on fait tourner un serveur Web sur notre parefeu, un paquet arrive avec pour adresse destination 82.46.73.52, Linux détermine qu'il s'agit d'une adresse qu'il gère et donc il l'envoie dans la chaîne "INPUT" et pas "FORWARD". Ensuite ce paquet, s'il n'est pas rejeté, arrive jusqu'aux processus où un prendra et traitera la requête pour renvoyer la réponse dans la chaîne "OUTPUT" puis renvoyé sur le net.

Schématiquement, on a (à peu près) ça :


Définition de la police par défaut

Commençons... Nous souhaitons que rien ne sorte et ne rentre sans notre permission. On va définir une "police" par défaut comme suit :

# iptables -P INPUT DROP
# iptables -P OUTPUT DROP
   -P INPUT: police par défaut sur la chaîne INPUT
DROP: on bêne

On dispose de plusieurs "fin" pour les trames :

  • DROP : on bêne sans concession, sans état d'âme
  • REJECT : on rejette le paquet et l'on avertit la machine qui nous a envoyé le paquet.
  • ACCEPT : on accepte les paquets

Exercice pratique

Dans l'état, la connexion Internet est partagée, nous avons activé le "FORWARDING" mais dans l'état actuel des choses, toute trame qui arrive dans la chaîne INPUT ou FORWARD est bênée.

Mettons que nous souhaitions permettre aux machines de notre LAN d'aller se connecter sur le serveur de google (66.102.9.104). Dans un premier temps, nous ne nous occupperons pas de la résolution DNS et l'on tapera comme adresse "http://66.102.9.104" au lieu de "http://www.google.fr".

Voilà ce que je vois sur mon parefeu avec l'utilitaire TCPDUMP (qui permet d'afficher l'ensemble des paquets, je renomme ETH0 en INSIDE et ETH1 en OUTSIDE) et je simplifie largement :

INSIDE :
192.168.0.2.1105 > 66.102.9.104.http
192.168.0.2.1105 > 66.102.9.104.http
OUTSIDE:
	

On voit que les paquets arrivent sur notre interface INSIDE mais ne sont pas transférées sur l'interface OUTSIDE. En effet, par défaut on bêne, il faut donc autoriser les paquets à destination d'un serveur Web à passer de l'INSIDE à l'OUTSIDE:

On autorise les paquets à être envoyée dans la chaîne FORWARD. On doit l'activer, une seule fois suffit
# echo 1 >/proc/sys/net/ipv4/ip_forward

# iptables -A FORWARD -p TCP --dport 80 -j ACCEPT
   -A FORWARD: on ajoute une règle à la chaîne FORWARD
   -p TCP : la règle concerne le protocole TCP, nécessaire pour pouvoir utiliser l'argument --dport 80
   --dport 80 : destination port 80, on spécifit le port destination du paquet
   -j ACCEPT : on accepte de laisser le paquet

Lors du filtrage, un paquet qui souhaite aller vers un serveur WEB (utilisation du protocole TCP et le port du serveur Web est 80), ce paquet est accepté.

Voici ce que l'on voit sur le parefeu maintenant :

INSIDE :
192.168.0.2.1105 > 66.102.9.104.http
192.168.0.2.1105 > 66.102.9.104.http
OUTSIDE:
192.168.0.2.1105 > 66.102.9.104.http
192.168.0.2.1105 > 66.102.9.104.http
	

Donc notre parefeu envoie sur le net une adresse privée ! non routable ! Nous n'obtiendrons jamais de réponse car les routeurs des FAI sont configurés pour rejeter tout paquet ayant pour adresse source une plage d'adresses privées. Eh oui, chez moi j'utilise 192.168.0.1, mais tout le monde peut utiliser ces adresses privées ! Ces adresses ne sont pas uniques et c'est pourquoi elles ne sont pas routées.


Pour remédier à cela, on met en place une translation d'adresse. C'est à dire qu'avant de sortir de notre interface OUTSIDE, on va remplacer l'adresse 192.168.0.2 par l'adresse Internet de notre parfeu. Automatiquement, le parefeu va noter cette translation d'adresse et lorsque le paquet revient, il changera son adresse publique par l'adresse privée et l'enverra sur le LAN.

# iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth1 -j SNAT --to 82.46.73.52
   -t NAT: type de service, NAT (Network Translation Adress)
   -A POSTROUTING: on ajoute le service de NAT au noeud POSTROUTING
   -s 192.168.0.0/24 : pour toutes les adresses sources appartenant au réseau 192.168.0.0/24 (c'est à dire 192168.0.0 -> 192.168.0.255).
   -j SNAT : on saute (jump) au service de NAT static
   --to 82.46.73.52 : et l'on transforme l'adresse du LAN avec l'adresse 82.46.73.52

deuxième méthode pour le nattage :

# iptables -A POSTROUTING -t nat -o eth1 -j MASQUERADE

Cette forme est plus simple que la précédente, le résultat est le même... Simplement, on laisse le noyau Linux décider de la politique de translation d'adresse tout seul comme un grand.

Et voilà ce que l'on obtient :

INSIDE :
192.168.0.2.1105 > 66.102.9.104.http
192.168.0.2.1105 > 66.102.9.104.http
OUTSIDE:
82.46.73.52.3544 > 66.102.9.104.http
66.102.9.104.http > 82.46.73.52.3544
	

Ah ! Grande évolution ! On voit bien la translation d'adresse ! et le serveur répond ! Mais le paquet n'est pas retransmit de l'OUTSIDE vers l'INSIDE, de fait notre explorateur continue de lancer sa requête.... mais ne reçoit jamais de réponse...


Pour cela, que faut il faire ? Eh bien comme on a permit à la trame de passer de l'INSIDE vers l'OUTSIDE, il faut maintenant s'occupper de la traversée inverse. A noter que les ports source et destination ainsi que adresses IP source et destination ont été interverties !

# iptables -A FORWARD -p TCP --sport 80 -j ACCEPT
   -A FORWARD: on ajoute une règle à la chaîne FORWARD
   -p TCP : la règle concerne le protocole TCP, nécessaire pour pouvoir utiliser l'argument --sport 80
   --sport 80 : source port 80, on spécifit le port source du paquet, qui est 80 (voir dernières traces)
   -j ACCEPT : on accepte de laisser le paquet

On accepte de laisser passer les trames en provenance d'un serveur web dans la chaîne FORWARD. Et voilà le résultat !

INSIDE :
192.168.0.2.1105 > 66.102.9.104.http
66.102.9.104.http > 192.168.0.2.1105
OUTSIDE:
82.46.73.52.3544 > 66.102.9.104.http
66.102.9.104.http > 82.46.73.52.3544
	

On voit que la translation d'adresse inverse est automatique. Le paquet traverse dans un sens et dans l'autre... Tout fonctionne ! Mais seulement pour le web....


Me contacter | ©2004-2005 Raum