Page précédente Accueil Page suivante


2. TP sur IPChains.

Auteur : David Mascle.

2.1. Présentation du TP.

Le but de ce TP est de comprendre l'écriture de règles pour les écluses ("Firewall") avec IPChains sous Linux.

2.1.1. Configuration du TP.

Pour ce TP, nous disposions de la configuration suivante :

Configuration matérielle
Configuration matérielle

Table de routage du Firewall station nommée "pass" :

Table de routage IP du noyau
Destination     Passerelle      Genmask         Indic   MSS Fenêtre irtt Iface
192.168.110.1   0.0.0.0         255.255.255.255 UH        0 0          0 eth1
193.55.130.181  0.0.0.0         255.255.255.255 UH        0 0          0 eth0
192.168.110.0   0.0.0.0         255.255.255.0   U         0 0          0 eth1
193.55.130.0    0.0.0.0         255.255.255.0   U         0 0          0 eth0
127.0.0.0       0.0.0.0         255.0.0.0       U         0 0          0 lo
0.0.0.0         193.55.130.1    0.0.0.0         UG        0 0          0 eth   

Table de routage de la station nommée "tp1" :

Table de routage IP du noyau
Destination     Passerelle      Genmask         Indic   MSS Fenêtre irtt Iface
192.168.110.2   0.0.0.0         255.255.255.255 UH        0 0          0 eth0
192.168.110.0   0.0.0.0         255.255.255.0   U         0 0          0 eth0
127.0.0.0       0.0.0.0         255.0.0.0       U         0 0          0 lo
0.0.0.0         192.168.110.1   0.0.0.0         UG        0 0          0 eth0  

Table de routage de la station nommée "tp2" :

Table de routage IP du noyau
Destination     Passerelle      Genmask         Indic   MSS Fenêtre irtt Iface
192.168.110.3   0.0.0.0         255.255.255.255 UH        0 0          0 eth0
192.168.110.0   0.0.0.0         255.255.255.0   U         0 0          0 eth0
127.0.0.0       0.0.0.0         255.0.0.0       U         0 0          0 lo
0.0.0.0         192.168.110.1   0.0.0.0         UG        0 0          0 eth0  

2.1.2. Objectifs du TP.

Le premier objectif de ce TP est de réaliser un essai d'écluse entre un réseau privé et un réseau public (Internet). Pour cela, nous allons nous intéresser au fonctionnement des règles d'IPChains pour mettre en place un Firewall. Nous allons aussi nous intéresser aux problèmes posés par l'utilisation du protocole FTP au travers d'un Firewall.

Le deuxième objectif de ce TP est d'auto-sécuriser un Firewall (protection anti-spoofing) et de mettre en place un ensemble de règles permettant l'utilisation de divers services sur le réseau privé au travers de ce Firewall (DNS, ICMP, HTTP, FTP, POP, SMTP...).

2.2. Description de la réalisation.

Nous allons commencer par voir le principe de fonctionnement d'IPChains. Cette application est un filtre de paquets fonctionnant au niveau du noyau Linux.

Le noyau dispose de trois listes de règles appelées des chaînes. Ces trois chaînes sont des filtres disposant de règles propres et qui fonctionnent en entrée (INPUT), en transmission (FORWARD) et en sortie (OUTPUT). Lorsqu'un paquet arrive, il est filtré à l'aide des règles de la chaîne INPUT. Si ce paquet est accepté, il est routé vers sa destination. Lorsque la destination est différente de la station hébergeant le Firewall, alors le paquet est filtré à l'aide de la chaîne FORWARD (ce qui permet notamment de réaliser du masquage d'adresse : "masquerading"). Et finalement le paquet est filtré par la chaîne OUTPUT.

Chaque chaîne peut fonctionner selon trois politiques différentes :

A l'aide des règles affectables à chaque chaîne, il est possible d'autoriser, de restreindre ou d'interdire l'accès à différents services réseaux. Et ainsi modifier la politique de filtrage des paquets de chaque chaîne. En faite, le filtrage de paquet fonctionne en analysant les entêtes des paquets. Si les données contenues dans l'entête d'un paquet correspondent à une règle alors la règle est appliquée (acceptation ou refus du paquet), sinon nous passons à la règle suivante tout pendant que toutes les règles de la liste affectée à chaque chaîne n'ont pas été testées.

Pour plus de détails sur IPChains vous pouvez consulter :

Vous pouvez retrouver les liens vers la documentation et le HowTo sur IPChains en consultant la page des références.

2.2.1. Un essai d'écluse entre réseau privé et public.

Notre but est d'autoriser les connexions sortantes HTTP depuis le réseau privé vers le réseau public (Internet). Pour résoudre ce problème, nous commençons par régler le problème inverse : c'est à dire autoriser tout sauf les connexions sortantes HTTP.

La première étape est de supprimer les règles affectées à chaque chaîne :

[root@pass /root]# ipchains -F 

Ensuite nous modifions la politique de chaque chaîne (mise dans l'état ACCEPT) :

[root@pass /root]# ipchains -P input ACCEPT
[root@pass /root]# ipchains -P forward ACCEPT
[root@pass /root]# ipchains -P output ACCEPT  

Il faut maintenant activer le masquage d'adresse (masquerading) :

[root@pass /root]# ipchains -A forward -s 192.168.110.0/255.255.255.0 -d 0.0.0.0/0.0.0.0 -j MASQ 

Pour vérifier l'état des différentes chaînes, tapez la commande suivante :

[root@pass /root]# ipchains -L 

Le résultat doit être le suivant :

Chain input (policy ACCEPT):
Chain forward (policy ACCEPT):
target     prot opt     source                destination           ports
MASQ       all  ------  192.168.110.0/24      anywhere              n/a
Chain output (policy ACCEPT):                                             

Nous interdisons maintenant en tcp : l'accès du port 80 (port HTTP) vers les ports dynamiques (1024 à 65535) en entrée et l'accès des ports dynamiques vers le port 80 en sortie.

[root@pass /root]# ipchains -A input -p tcp -s any/0 80 -d any/0 1024:65535 -j REJECT
[root@pass /root]# ipchains -A output -p tcp -s any/0 1024:65535 -d any/0 80 -j REJECT 

Le résultat doit être le suivant :

Chain input (policy ACCEPT):
target     prot opt     source                destination           ports
REJECT     tcp  ------  anywhere              anywhere              www ->   1024:65535
Chain forward (policy ACCEPT):
target     prot opt     source                destination           ports
MASQ       all  ------  192.168.110.0/24      anywhere              n/a
Chain output (policy ACCEPT):
target     prot opt     source                destination           ports
REJECT     tcp  ------  anywhere              anywhere              1024:65535 ->   www 

A partir de maintenant, il est impossible d'accéder depuis les stations du réseau privé (Firewall inclus) aux pages web (par HTTP) dont le serveur fonctionne sur le port 80.

Pour vérifier le rejet des connexions HTTP sortantes vous pouvez tapez la commande suivante :

[root@pass /root]# lynx http://www.info.unicaen.fr 

La connexion vers http://www.info.unicaen.fr est impossible.

Nous allons maintenant résoudre le problème inverse. C'est à dire interdire toutes les connexions sortantes sauf celles du protocole HTTP.

Attention : il faut ne pas oublier d'autoriser les connexions vers le service de DNS, sinon la résolution de nom sera impossible.

Tout d'abord, nous allons supprimer les règles des chaînes INPUT et OUTPUT. Nous conservons les règles de la chaîne FORWARD pour le masquerading.

[root@pass /root]# ipchains -F input
[root@pass /root]# ipchains -F output 

Ensuite nous modifions les politiques pour les chaînes INPUT (DENY), FORWARD (DENY) et OUTPUT (REJECT).

[root@pass /root]# ipchains -P input DENY
[root@pass /root]# ipchains -P forward DENY
[root@pass /root]# ipchains -P output REJECT 

Nous ajoutons les règles pour accéder au DNS (en UDP et en TCP au cas ou les réponses du serveur DNS dépassent 512 octets) :

[root@pass /root]# ipchains -A input -p udp -s any/0 53 -j ACCEPT
[root@pass /root]# ipchains -A output -p udp -d any/0 53 -j ACCEPT
[root@pass /root]# ipchains -A input -p tcp -s any/0 53 -j ACCEPT
[root@pass /root]# ipchains -A output -p tcp -d any/0 53 -j ACCEPT 

Nous autorisons aussi les connexions HTTP :

[root@pass /root]# ipchains -A input -p tcp -s any/0 www -d any/0 1024:65535 -j ACCEPT
[root@pass /root]# ipchains -A output -p tcp -s any/0 1024:65535 -d any/0 www -j ACCEPT 

Listons les règles d'IPChains :

[root@pass /root]# ipchains -L
Chain input (policy DENY):
target     prot opt     source                destination           ports
ACCEPT     udp  ------  anywhere              anywhere              domain ->   any
ACCEPT     tcp  ------  anywhere              anywhere              domain ->   any
ACCEPT     tcp  ------  anywhere              anywhere              www ->   1024:65535
Chain forward (policy DENY):
target     prot opt     source                destination           ports
MASQ       all  ------  192.168.110.0/24      anywhere              n/a
Chain output (policy REJECT):
target     prot opt     source                destination           ports
ACCEPT     udp  ------  anywhere              anywhere              any ->   domain
ACCEPT     tcp  ------  anywhere              anywhere              any ->   domain
ACCEPT     tcp  ------  anywhere             anywhere              1024:65535 ->   www  

Il est maintenant seulement possible à partir du réseau privé :

Ceci est une configuration de base qui ne prend pas en compte certains problèmes : absence de traitement des messages ICMP et absence de protection contre les principales failles de sécurité. Mais nous verrons dans la section 2.2.2 comment régler ces problèmes.

Intéressons nous pour le moment au problème plus complexe des connexions sortantes FTP.

Le FTP peut fonctionner selon deux modes :

Le mode actif pose les problèmes suivants : lorsqu'un serveur FTP souhaite envoyer des données vers un client, il tente d'ouvrir une connexion TCP supplémentaire sur ce client pour y faire transiter les données. Ce qui rend impossible le filtrage de ces connexions sans supprimer la connexion FTP faisant transiter les commandes du protocole.

Schéma de fonctionnement du FTP
Schéma de fonctionnement du FTP

La première solution est de faire fonctionner le FTP en mode passif, c'est à dire que ce n'est plus le serveur FTP qui va décider de l'ouverture et du contrôle d'un canal de données mais le client. Ce qui permet le filtrage de la connexion pour le canal de données sans supprimer la connexion pour le canal de commandes.

Cependant certains serveurs ou certains clients FTP n'accepte pas le mode passif. Dans ce cas, il existe une deuxième solution qui consiste à n'autoriser les connexions que vers les ports dynamiques (1024 à 65535). Tout en n'oubliant pas de rejeter les connexions TCP entre les ports 6000 à 6010 pour empêcher le piratage des ports X11 (pouvant permettre à un pirate de visualiser votre session X11 et de récupérer votre mot de passe par exemple).

Nous verrons dans la section suivante les règles nécessaires à l'utilisation du protocole FTP en mettant en place une auto-écluse.

2.2.2. Un essai d'auto-écluse.

Pour qu'un Firewall soit efficace, il faut le protéger contre certains problèmes de sécurité. C'est ce que nous allons faire maintenant.

Pour cela, nous allons :

Attention : en préalable à toutes les modifications futures, vous devez videz les différentes chaînes de leurs règles, changer les politiques des différentes chaînes et activer le masquerading pour la chaîne FORWARD comme décrit à la section 2.2.1.

L'ip-spoofing est une attaque qui permet à un hôte d'envoyer des paquets qui prétendent venir d'un autre hôte. Le but de cette attaque est d'abuser les filtres de paquets (car ils se fient aux adresses IP sources des paquets pour traiter les paquets). Cela permet à des pirates de se rendre anonyme et ainsi d'attaquer des serveurs sans être repérer.

Pour se protéger de l'ip-spoofing avec IPChains, il faut interdire l'accès à tous les hôtes se connectant par une autre interface que eth1 (interface du réseau privé sur le Firewall) avec une adresse IP du réseau privé. Cette règle est la suivante :

[root@pass /root]# ipchains -A input -i ! eth1 -s 192.168.0.0/24 -d 0.0.0.0/0 -j DENY 

Attention : cette solution consistant à utiliser IPChains pour se prévenir de l'ip-spoofing fonctionne, mais n'est pas la meilleure. En fait, la lutte contre l'ip-spoofing doit être réalisée au niveau du code de routage (en vérifiant l'adresse source à chaque lancement du serveur hébergeant le Firewall) et non pas par le Firewall. Le document Linux IPChains HowTo fournit un script permettant de le faire.

# This is the best method: turn on Source Address Verification and get           
       # spoof protection on all current and future interfaces.                  
       if [ -e /proc/sys/net/ipv4/conf/all/rp_filter ]; then                     
         echo -n "Setting up IP spoofing protection..."                          
         for f in /proc/sys/net/ipv4/conf/*/rp_filter; do                        
             echo 1 > $f                                                         
         done                                                                    
         echo "done."                                                            
       else                                                                      
         echo PROBLEMS SETTING UP IP SPOOFING PROTECTION.  BE WORRIED.           
         echo "CONTROL-D will exit from this shell and continue system startup." 
         echo                                                                    
         # Start a single user shell on the console                              
         /sbin/sulogin $CONSOLE                                                  
       fi                                                                        

Nous allons maintenant sécuriser le DNS.

La première étape consiste à éditer le fichier /etc/resolv.conf :

Il faut maintenant relancer le serveur de nom de domaine en tapant la commande suivante :

[root@pass /root]# /etc/rc.d/init.d/named restart 

Ensuite nous ajoutons les règles IPChains suivantes pour autoriser les connexions DNS seulement vers saunet.unicaen.fr :

[root@pass /root]# ipchains -A input -p udp -s 193.55.121.60 53 -d any/0 -j ACCEPT
[root@pass /root]# ipchains -A output -p udp -s any/0 -d 193.55.121.60 53 -j ACCEPT 

Note : dans le cas présent nous autorisons que les connexions DNS en UDP comme demandé dans le TP, mais comme précisé à la section 2.2.1., il peut être nécessaire d'autoriser les connexions en TCP pour les réponses du serveur DNS dépassant 512 octets.

Passons au règles pour les messages ICMP. Nous allons autoriser les messages de type 0 (pong), 3 (destination unreachable) et 8 (ping). Attention : il ne faut surtout pas autoriser les messages ICMP de type 5 (redirection) qui peuvent être utilisés par les pirates pour manipuler le routage des paquets. Voici les règles pour ICMP :

[root@pass /root]# ipchains -A input -p icmp --icmp-type 0 -j ACCEPT
[root@pass /root]# ipchains -A input -p icmp --icmp-type 3 -j ACCEPT
[root@pass /root]# ipchains -A input -p icmp --icmp-type 8 -j ACCEPT
[root@pass /root]# ipchains -A output -p icmp --icmp-type 0 -j ACCEPT
[root@pass /root]# ipchains -A output -p icmp --icmp-type 3 -j ACCEPT
[root@pass /root]# ipchains -A output -p icmp --icmp-type 8 -j ACCEPT 

Note : l'attaque connue sous le nom de "Ping Of Death" consistant à l'envoi de paquets ICMP illégalement grands faisant déborder les buffers de la pile TCP du récepteur et entraînant de gros dégâts est maintenant impossible sous Linux.

Maintenant, nous allons mettre en place les règles permettant l'utilisation des services HTTP, FTP, POP et SMTP.

Nous devons commencer par protéger les ports X11(ports 6000 à 6010) :

[root@pass /root]# ipchains -A input -p tcp -s any/0 6000:6010 -d any/0 1024:65535 -j REJECT
[root@pass /root]# ipchains -A output -p tcp -s any/0 1024:65535 -d any/0 6000:6010 -j REJECT 

Nous autorisons le service HTTP (port 80) :

[root@pass /root]# ipchains -A input -p tcp -s any/0 www -d any/0 1024:65535 -j ACCEPT
[root@pass /root]# ipchains -A output -p tcp -s any/0 1024:65535 -d any/0 www -j ACCEPT 

Nous autorisons le service FTP en mode actif plus passif (port 21) :

[root@pass /root]# ipchains -A input -p tcp -s any/0 21 -d any/0 1024:65535 -j ACCEPT
[root@pass /root]# ipchains -A output -p tcp -s any/0 1024:65535 -d any/0 21 -j ACCEPT
[root@pass /root]# ipchains -A input -p tcp -s any/0 1024:65535 -d any/0 1024:65535 -j ACCEPT
[root@pass /root]# ipchains -A output -p tcp -s any/0 1024:65535 -d any/0 1024:65535 -j ACCEPT 

Nous autorisons le service POP (port 110) :

[root@pass /root]# ipchains -A input -p tcp -s any/0 110 -d any/0 1024:65535 -j ACCEPT
[root@pass /root]# ipchains -A output -p tcp -s any/0 1024:65535 -s any/0 110 -j ACCEPT 

Nous autorisons le service SMTP (port 25) :

[root@pass /root]# ipchains -A input -p tcp -s any/0 25 -d any/0 1024:65535 -j ACCEPT
[root@pass /root]# ipchains -A output -p tcp -s any/0 1024:65535 -d any/0 25 -j ACCEPT 

Pour ajouter un nouveau service, vous devez :

Consultons l'état des chaînes d'IPChains :

[root@pass /root]# ipchains -L
Chain input (policy DENY):
target     prot opt     source                destination           ports
ACCEPT     udp  ------  saunet.unicaen.fr     anywhere              domain ->   any
ACCEPT     icmp ------  anywhere              anywhere              echo-reply
ACCEPT     icmp ------  anywhere              anywhere              destination-unreachable
ACCEPT     icmp ------  anywhere              anywhere              echo-request
REJECT     tcp  ------  anywhere              anywhere              6000:6010 ->   1024:65535
ACCEPT     tcp  ------  anywhere              anywhere              www ->   1024:65535
ACCEPT     tcp  ------  anywhere              anywhere              ftp ->   1024:65535
ACCEPT     tcp  ------  anywhere              anywhere              1024:65535 ->   1024:65535
ACCEPT     tcp  ------  anywhere              anywhere              pop3 ->   1024:65535
ACCEPT     tcp  ------  anywhere              anywhere              smtp ->   1024:65535
DENY       all  ------  192.168.0.0/24        anywhere              n/a
Chain forward (policy DENY):
target     prot opt     source                destination           ports
MASQ       all  ------  192.168.110.0/24      anywhere              n/a
Chain output (policy REJECT):
target     prot opt     source                destination           ports
ACCEPT     udp  ------  anywhere              saunet.unicaen.fr     any ->   domain
ACCEPT     icmp ------  anywhere              anywhere              echo-reply
ACCEPT     icmp ------  anywhere              anywhere              destination-unreachable
ACCEPT     icmp ------  anywhere              anywhere              echo-request
REJECT     tcp  ------  anywhere              anywhere              1024:65535 ->   6000:6010
ACCEPT     tcp  ------  anywhere              anywhere              1024:65535 ->   www
ACCEPT     tcp  ------  anywhere              anywhere              1024:65535 ->   ftp
ACCEPT     tcp  ------  anywhere              anywhere              1024:65535 ->   1024:65535
ACCEPT     tcp  ------  anywhere              anywhere              1024:65535 ->   pop3
ACCEPT     tcp  ------  anywhere              anywhere              1024 ->   smtp             

Que permet notre Firewall ?

Attention : si vous souhaitez utiliser un Firewall Linux pour protéger un réseau hétérogène, vous devez vous informer des failles de sécurité inhérentes à ces environnements pour ajouter des règles empêchant ces failles. Il existe des exemples connus sous Windows avec les chevaux de Troie : Netbus (ports 12345-12346) et Back Orifice (port 31337) qui permettent à un pirate de prendre le contrôle de votre station. La première étape avant d'autoriser de nouveaux services sur un Firewall est de s'informer d'éventuelles failles de sécurité en consultant les newsgroups, les listes de diffusions et les sites webs sur la sécurité réseau (quelques références vous sont fournies en annexes).

Journalisation : si vous ajoutez l'option "-l" ou "--log" à une règle IPChains, lorsque celle-ci est activée alors il y a journalisation de l'événement à l'aide du daemon syslogd et affichage d'un message sur la console. Les messages journalisés sont de niveau noyau (stockés la plupart du temps dans le fichier /var/log/kern.log). Bien sûr, il n'est pas utile de journaliser toutes les règles. Il faut plutôt journaliser les règles aboutissant à une interdiction tels que l'ip-spoofing. Ensuite, il suffit de faire un script se chargeant d'analyser les fichiers de logs et qui préviendra l'administrateur système (envoi d'un email par exemple) dans le cas ou une attaque a été journalisée. Cela permettra à l'administrateur système de prendre des mesures en conséquence.

Si vous avez utilisé IPChains, vous avez du vous rendre compte que l'écriture de règles est assez fastidieuse. C'est pourquoi il existe différente application graphique permettant d'écrire ces règles :

Vous trouverez les liens vers ces applications sur la page des références.

Pour vous faciliter le travail il est aussi possible d'enregistrer vos règles dans un fichier à l'aide de la commande :

[root@pass /root]# ipchains-save > rules.txt 

Puis de les recharger dans IPChains à l'aide la commande :

[root@pass /root]# ipchains-restore < rules.txt 

Note : cette commande peut servir aussi à l'activation des règles lors du démarrage du Firewall.


Page précédente Accueil Page suivante