Avertissement :
La version originale de cet article a été publiée sur IBM developerWorks
et est la propriété de Westtech Information Services. Ce document est une
traduction de la mise à jour de la version originale de l'article
réalisée par l'équipe de documentation Gentoo et contient quelques
améliorations proposées par l'équipe de documentation de Gentoo Linux.
Ce document n'est pas activement maintenu.
|
Pare-feu avec suivi de connexion sous Linux 2.4
1.
À propos de ce guide
À qui s'adresse ce guide ?
Ce guide vous montre comment utiliser NetFilter pour configurer un puissant
pare-feu avec suivi de connexion (en anglais, « firewall stateful »).
Tout ce dont vous aurez besoin est d'un système Linux existant utilisant une
version 2.4 ou supérieure du noyau Linux. Un portable, PC de bureau, routeur ou
serveur avec un Linux 2.4 ou plus fera l'affaire.
Vous devez être assez familier avec le vocabulaire réseau, comme les adresses
IP, les ports source et destination, TCP, UDP ou ICMP, etc. Après avoir suivi
ce guide jusqu'au bout, vous aurez compris le fonctionnement d'un firewall
stateful sous Linux. De nombreux exemples de configurations vous seront
également exposés.
À propos de l'auteur
Pour toute question technique sur le contenu de ce guide, contactez l'auteur,
Daniel Robbins, à l'adresse suivante :
drobbins@gentoo.org.
Résidant à Albuquerque, dans le Nouveau Mexique, Daniel Robbins a été le PDG de
Gentoo Technologies, Inc., le créateur de Gentoo Linux, un système
d'exploitation Linux moderne pour PC et du système Portage, un gestionnaire de
ports nouvelle génération pour Linux. Il a également été un des auteurs
contributeurs pour les livres Caldera OpenLinux Unleashed, SuSE Linux Unleashed,
et Samba Unleashed, parus aux éditions Macmillan. Daniel a été au contact de
l'informatique depuis l'école élémentaire quand il fut confronté au langage de
programmation Logo ainsi qu'à une dose potentiellement dangereuse de Pac Man.
Cela explique sans doute pourquoi il a depuis été employé en tant que Chef
Infographiste chez SONY Electronic Publishing/Psygnosis. Daniel aime passer son
temps libre avec sa femme, Mary et sa fille, Hadassah.
2.
Premières étapes
Le but du jeu
Dans ce guide, nous allons bâtir un pare-feu avec suivi de connexion pour
Linux. Notre firewall va s'exécuter sur un ordinateur portable, de bureau,
serveur ou routeur sous Linux ; son but principal est d'autoriser
seulement certains types de trafic réseau à le traverser. Pour augmenter la
sécurité, nous allons configurer le firewall pour ignorer ou rejeter le trafic
qui ne nous intéresse pas ainsi que le trafic potentiellement dangereux pour la
sécurité.
Les outils nécessaires
Avant de commencer à bâtir le pare-feu, il faut faire deux choses. Tout
d'abord, il faut s'assurer que la commande iptables est disponible sur
la machine. Pour cela, en tant que super-utilisateur, tapez iptables et
vérifiez ce que vous répond le shell. Si la commande n'existe pas, alors il
faut l'installer. Voilà comment faire :
Exemple de code 2.1 : Installation de iptables |
# emerge iptables
|
Configuration du noyau
Une fois installée, la commande iptables est disponible, ainsi que la
page de manuel qui lui correspond (man iptables). Ensuite, il faut nous
assurer que les fonctionnalités nécessaires sont bien activées dans le noyau.
Ce guide suppose que vous compilez vos propres noyaux. Dans le répertoire
/usr/src/linux, tapez make menuconfig ou make
xconfig ; nous allons choisir certaines fonctionnalités pour notre
noyau.
Dans la section "Networking options" (dans le menu "Networking->Networking
Options" pour le noyau 2.6), assurez-vous d'activer au moins les options
suivantes :
Exemple de code 2.2 : Fonctionnalités noyaux nécessaires |
<*> Packet socket
[*] Network packet filtering (replaces ipchains)
<*> Unix domain sockets
[*] TCP/IP networking
[*] IP: advanced router
[*] IP: policy routing
[*] IP: use netfilter MARK value as routing key
[*] IP: fast network address translation
[*] IP: use TOS value as routing key
|
Ensuite, dans le menu "IP: Netfilter Configuration ->", activez toutes les
options, afin d'avoir toutes les fonctionnalités NetFilter disponibles pour
votre pare-feu. Elles ne sont pas toutes nécessaires, mais vous pourrez ainsi
mener quelques expériences avec ces options plus tard.
Il y a une fonctionnalité dans la section "Networking options" que vous ne
devriez pas activer : la notification explicite de congestion.
Laissez cette option décochée.
Exemple de code 2.3 : L'option à désactiver |
[ ] IP: TCP Explicit Congestion Notification support
|
Si cette option est activée, votre machine Linux ne sera pas capable de
supporter des communications réseau avec environ 8% de l'Internet. Quand l'ECN
est activée, certains paquets envoyés par votre machine Linux auront le bit ECN
à 1. En pratique, ce bit engendre des comportements bizarres sur certains
routeurs Internet, aussi vaut-il mieux garder l'ECN désactivée.
Maintenant que le noyau est configuré correctement, compilez-le, installez-le et
rebootez. Nous pouvons maintenant nous amuser avec NetFilter :)
Premiers pas
Pour construire un pare-feu, la commande iptables sera votre meilleure
alliée. Elle permet d'interagir avec les règles de filtrage de paquets au
niveau du noyau. Nous utiliserons la commande iptables pour créer de
nouvelles règles, afficher les règles existantes, en supprimer et choisir la
politique de filtrage par défaut. Ce qui signifie que la création d'un pare-feu
se résume à entrer une série de commandes iptables, comme par exemple
(ATTENTION, ne pas la taper tout de suite !)
Exemple de code 2.4 : Choisir la politique par défaut DROP |
# iptables -P INPUT DROP
|
Si vous voulez créer un pare-feu quasiment parfait et que vous entrez
cette commande, vous serez absolument bien protégé contre toutes formes
d'attaques malicieuses. En effet, cette commande ordonne au noyau d'ignorer
tous les paquets réseau entrants. Cependant, même si ce firewall est
extrêmement sécurisé, il est également un peu mauvais. Mais avant de continuer,
essayons de comprendre comment cette commande peut faire ce qu'elle fait.
Modifier la politique par défaut
La commande iptables -P est utilisée pour selectionner la politique par
défaut pour une chaîne de filtrage de paquets. Dans cet exemple, iptables
-P est utilisé pour changer la politique par défaut de la chaîne INPUT, une
chaîne préinstallée qui est appliquée à chaque paquet entrant. En sélectionnant
la potique par défaut DROP, on indique au noyau que chaque paquet qui atteint la
fin de la chaîne INPUT doit être « droppé » (c'est-à-dire ignoré, supprimé de la
mémoire). Et comme nous n'avons pas encore ajouté de règles dans la chaîne
INPUT, tous les paquets atteignent la fin de la chaîne et donc tous les paquets
sont ignorés.
Encore une fois, à elle seule, cette commande est totalement inutile.
Cependant, elle montre une bonne stratégie pour la construction d'un pare-feu.
On commence par ignorer tous les paquets par défaut, puis on ouvre au fur et à
mesure les ports dont on a besoin. Cela garantit que le pare-feu est aussi
sécurisé que possible.
3.
Definir ses règles
Une (petite) amélioration
Dans cet exemple, nous supposons que nous construisons un pare-feu pour une
machine avec deux interfaces réseau, nommées eth0 et eth1. L'interface eth0 est
connectée sur notre LAN, tandis que eth1 est branchée sur notre routeur DSL
qui mène vers Internet. Dans une telle situation, nous améliorerons notre
pare-feu ultime en rajoutant une ligne :
Exemple de code 3.1 : Améliorons notre pare-feu ultime |
# iptables -P INPUT DROP
# iptables -A INPUT -i ! eth1 -j ACCEPT
|
Cette ligne supplémentaire iptables -A ajoute une nouvelle règle de
filtrage de paquets à la fin de la chaîne INPUT. Après avoir ajouté cette
règle, la chaîne INPUT consiste en une règle unique et une règle DROP par
défaut. Maintenant, voyons ce que fait notre pare-feu désormais à moitié
terminé.
Le long de la chaîne INPUT...
Quand un paquet arrive sur l'une des interfaces (lo, eth0 ou eth1), le code de
NetFilter l'envoie sur la chaîne INPUT et vérifie s'il correspond à la première
règle. Si c'est le cas, il est accepté et le traitement de ce paquet est
terminé. Sinon, la règle par défaut de INPUT est appliquée et le paquet est
effacé (DROP).
Voilà pour le point de vue conceptuel. Plus concrètement, la première règle
correspond à tous les paquets arrivant sur les interfaces eth0 et lo, et les
laisse passer. Tous les paquets arrivant sur l'interface eth1 sont droppés.
Donc, si nous activons ce firewall sur notre machine, il pourra interagir avec
notre LAN, mais ne pourra pas communiquer avec Internet. Voyons comment
autoriser le trafic Internet, et ce de deux manières différentes.
Pare-feu traditionnels
Évidemment, pour que notre firewall serve à quelque chose, il nous faut
sélectionner quels paquets seront autorisés à atteindre notre machine en
passant par Internet. Il y a deux approches pour faire cela : l'une
utilise des règles statiques, tandis que l'autre utilise des règles dynamiques,
avec suivi de connexion.
Prenons pour exemple le cas du téléchargement de pages Web. Si nous voulons que
notre machine soit capable de recevoir les paquets correspondants au
téléchargement, nous pouvons ajouter une règle statique qui sera toujours vraie
pour les paquets HTTP entrants, quelle que soit leur origine :
Exemple de code 3.2 : Acceptons tous les paquets HTTP entrants |
# iptables -A INPUT --sport 80 -j ACCEPT
|
Comme tout le trafic Web standard provient d'un serveur avec port source 80,
cette règle permet effectivement à votre machine de télécharger des pages Web.
Cependant, cette approche traditionnelle, bien qu'acceptable dans certains cas,
engendre de nombreux problèmes.
Problèmes des pare-feu traditionnels
Voilà le premier problème : bien que la plupart du trafic Web ait pour
origine un port 80, ce n'est quelquefois pas vrai. Donc, cette règle marche,
mais seulement la plupart du temps. Par exemple, vous avez peut-être déjà vu
une URL du genre "http://www.foo.com:81". Cette URL pointe vers un serveur Web
hébergé sur un serveur écoutant sur le port 81 plutôt que le port 80 par
défaut, et est donc inaccessible derrière notre pare-feu. Prendre en compte
toutes les exceptions de ce genre va vite faire de notre firewall sécurisé un
sac de n¿uds et remplira notre chaîne INPUT avec un tas de règles pour gérer
chaque cas particulier.
Cependant, le problème majeur de ce genre de règle est lié à la sécurité.
Évidemment, il est vrai que seulement le trafic avec un port source 80 sera
autorisé à passer notre pare-feu, mais le port source d'un paquet est un
élément facilement manipulable par un attaquant. Par exemple, si un intrus
connaît la façon dont notre pare-feu est conçu, il peut le contourner
simplement en s'assurant que toutes ses connexions entrantes viennent d'un port
80 de l'une de ses machines ! Puisque cette règle statique est trop facile
à contourner, il nous faut une approche plus sécurisée et dynamique.
Heureusement, iptables et le noyau 2.4 et supérieurs incluent tout ce dont nous
avons besoin pour construire un pare-feu dynamique avec suivi de connexion.
4.
Pare-feu dynamique avec suivi de connexion
Quelques mots sur le suivi de connexion
Plutôt que de creuser des trous dans notre pare-feu en se basant sur des
caractéristiques statiques des protocoles, on peut utiliser les nouvelles
fonctionnalités de suivi de connexion de Linux pour baser les décisions du
pare-feu sur l'état dynamique des paquets par rapport à la connexion.
Conntrack fonctionne en associant chaque paquet avec une et une seule
communication bidirectionnelle, ou connexion.
Par exemple, imaginons ce qui se passe lorsque vous utilisez telnet ou ssh pour
vous connecter sur une machine distante. Si vous regarder le trafic réseau au
niveau des paquets, tout ce que vous verrez sera un tas de paquets passant
d'une machine sur l'autre. Cependant, à un niveau d'abstraction plus élevé, cet
échange de paquets est en fait une communication bidirectionnelle entre votre
machine locale et la machine distante. Les pare-fxu traditionnels ne font que
regarder chaque paquet indépendamment les uns des autres, sans se soucier
qu'ils fassent en réalité partie d'un tout, d'une connexion.
Conntrack en détails
C'est là que la technologie de suivi de connexion entre en jeu. La
fonctionnalité conntrack de Linux peut voir les connexions de haut
niveau lorsqu'elles ont lieu, reconnaissant votre session SSH comme une seule
entité logique. Conntrack peut aussi reconnaître les échanges de paquets UDP et
ICMP comme des connexions logiques, même si UDP et ICMP sont sans connexion par
nature ; cela est très utile puisque cela permet d'utiliser conntrack pour
gérer des échanges de paquets ICMP et UDP.
Si vous avez déjà redémarré avec votre nouveau noyau avec NetFilter activé,
vous pouvez voir une liste des connexions réseau actives auxquelles votre
machine participe en entrant cat /proc/net/ip_conntrack. Même sans
pare-feu configuré, conntrack fonctionne en arrière-plan, en gardant trace des
connexions établies ou reçues par votre machine.
État de connexion NEW
Conntrack ne fait pas que reconnaître les connexions, il classe également
chaque paquet qu'il voit dans l'un des quatres états de connexion. Le premier
état dont nous allons parler est appelé NEW (nouveau). Quand vous tapez ssh
hote.distant.com, le premier paquet ou la première rafale de paquets qui
sortent de votre machine et sont destinés à hote.distant.com sont dans l'état
NEW. Cependant, dès que vous aurez reçu ne serait ce qu'un seul paquet de
hote.distant.com, tous les futurs paquets que vous enverrez à hote.distant.com
dans cette connexion ne seront plus considérés comme des packets NEW. Pour
résumer, un paquet est considéré NEW lorsqu'il sert à établir une nouvelle
connexion, et qu'aucun trafic n'a été reçu de l'hôte distant en retour (dans
le cadre de cette connexion précise, évidemment).
J'ai décrit les paquets NEW sortants, mais il est également tout à fait
possible (et normal) d'avoir des paquets NEW entrants. Les paquets NEW entrants
viennent généralement d'une machine distante et servent à établir une connexion
avec vous. Le(s) premier(s) paquet(s) que votre serveur Web reçoit pour une
requête HTTP sont considérés comme des paquets NEW entrants ; cependant,
une fois que vous aurez répondu à un seul de ces paquets, tous les autres
paquets que vous recevrez ne seront plus considérés dans l'état NEW.
Etat de connexion ESTABLISHED
Une fois qu'une connexion a vu du trafic dans les deux sens, tous les nouveaux
paquets de cette connexion sont considérés dans l'état ESTABLISHED (établi). La
distinction entre les états NEW et ESTABLISHED est très importante, comme nous
le verrons dans un instant.
Etat de connexion RELATED
Le troisième état de connexion est appelé RELATED (en rapport avec). Les
paquets RELATED sont ceux qui établissent une nouvelle connexion, mais qui sont
en rapport avec une connexion déjà existante. L'état RELATED peut être utilisé
pour filtrer des connexions qui font partie d'un protocole multi-connexion,
comme FTP, ainsi que les paquets d'erreur en rapport avec des connexions
existantes (comme les paquets d'erreur ICMP).
Etat de connexion INVALID
Pour terminer, il existe aussi les paquets INVALID : ce sont ceux qui ne
peuvent être classés dans aucune des trois précédentes catégories. Il est
important de noter qu'un paquet considéré comme INVALID n'est pas
automatiquement ignoré ; c'est à vous de choisir les règles appropriées et
d'ajuster les politiques pour que ces paquets soient gérés de la manière que
vous préférez.
Ajout d'une règle stateful
Bien, maintenant que nous avons compris le suivi de connexion, il est temps de
jeter un ¿il à une simple règle supplémentaire qui va transformer notre
pare-feu non-fonctionnel en quelque chose de plutôt utile.
Exemple de code 4.1 : Ajout d'une règle stateful |
# iptables -P INPUT DROP
# iptables -A INPUT -i ! eth1 -j ACCEPT
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
Fonctionnement de cette règle
Cette simple règle, insérée à la fin de votre chaîne INPUT existante, va nous
permettre d'établir des connexions avec des machines distantes. Elle fonctionne
comme ceci : disons que l'on veuille faire du ssh vers hote.distant.com.
Après avoir lancé ssh hote.distant.com, notre machine envoie un paquet
pour établir la connexion. Ce paquet particulier est dans l'état NEW, et notre
pare-feu le laisse passer, puisque nous bloquons seulement les paquets qui
entrent dans notre firewall, pas ceux qui en sortent.
Quand nous recevons une réponse de hote.distant.com, ce paquet passe par notre
chaîne INPUT. Il ne correspond pas à la première règle (puisqu'il arrive de
eth1), donc il passe à la seconde et dernière règle. S'il correspond à cette
règle, il sera accepté, et sinon, il arrivera à la fin de la chaîne INPUT et la
politique par défaut lui sera appliquée (DROP). Alors, ce paquet entrant
sera-t-il accepté ou droppé ?
Réponse : accepté. Quand le noyau examine ce paquet entrant, il reconnaît
en premier qu'il fait partie d'une connexion existante. Ensuite, le noyau doit
décider s'il s'agit d'un paquet NEW ou ESTABLISHED. Puisqu'il s'agit d'un
paquet entrant, il vérifie si cette connexion a déjà eu du trafic sortant et
trouve que c'est le cas (le paquet NEW initial que nous avons envoyé). Ensuite,
le paquet entrant est classé ESTABLISHED, comme le seront tous les futurs
paquets reçus ou envoyés qui seront associés avec cette connexion.
Paquets NEW entrants
Maintenant, considérons ce qui ce passe si quelqu'un sur une machine distante
essaie de se connecter en ssh chez nous. Le premier paquet que nous recevons
est marqué NEW et ne correspond pas à la règle 1, donc il passe à la règle 2.
Puisque ce paquet n'est pas dans l'état ESTABLISHED ou RELATED, il arrive à la
fin de la chaîne INPUT et la politique par défaut, DROP, est appliquée. Notre
demande d'établissement de connexion ssh entrante est donc ignorée sans même
une réponse (ou un paquet TCP reset) de notre part.
Un pare-feu proche de la perfection
Alors, quel genre de pare-feu avons-nous jusqu'à présent ? Un excellent
choix pour un portable ou un poste de travail si vous voulez que personne ne
puisse se connecter depuis Internet vers vous, mais avec lequel vous pouvez
quand même vous connecter à des sites sur Internet. Vous pourrez utiliser
Netscape, Konqueror, ftp, ping, faire des recherches DNS, et bien plus. Toutes
les connexions dont vous êtes l'initiateur pourront passer votre firewall.
Cependant, les connexions non sollicitées qui viennent depuis Internet seront
ignorées, à moins d'être en relation avec une connexion existante que vous avez
initiée. Tant que vous ne devez pas fournir un service réseau vers
l'extérieur, c'est un pare-feu pratiquement parfait.
Un script de pare-feu simple
Voilà un script simple qui peut être utilisé pour configurer notre premier
firewall de station de travail :
Exemple de code 4.2 : Un script de pare-feu simple |
#!/bin/bash
if [ "$1" = "start" ]
then
echo "Démarrage du firewall..."
iptables -P INPUT DROP
iptables -A INPUT -i ! eth1 -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
elif [ "$1" = "stop" ]
then
echo "Arrêt du firewall..."
iptables -F INPUT
iptables -P INPUT ACCEPT
fi
|
Utilisation du script
En utilisant ce script, vous pouvez désactiver le pare-feu en tapant
./firewall stop et le relancer en tapant ./firewall start. Pour
désactiver le firewall, on supprime les règles de la chaîne INPUT en faisant
iptables -F INPUT, puis reprenons la politique par défaut de INPUT en
ACCEPT avec la commande iptables -P INPUT ACCEPT. Maintenant, voyons
tout un tas d'améliorations que nous pouvons faire sur notre pare-feu. Après
avoir expliqué chaque amélioration, je présenterai un script avancé pour un
poste de travail. Ensuite, nous commencerons à modifier notre pare-feu pour des
serveurs.
5.
Améliorations du suivi de connexion
Désactication explicite de l'ECN
J'ai parlé plus haut de l'importance de désactiver l'ECN (explicit congestion
notification) pour que les communications Internet fonctionnent correctement.
Même si vous avez désactivé l'ECN dans le noyau en suivant ma suggestion, il
est possible que vous l'oubliez dans le futur. Ou, comme c'est possible, vous
allez passer votre script de pare-feu à quelqu'un qui a activé l'ECN. Pour ces
raisons, c'est une bonne idée d'utiliser l'interface /proc pour
désactiver explicitement l'ECN, comme ceci :
Exemple de code 5.1 : Désactivation explicite de l'ECN |
if [ -e /proc/sys/net/ipv4/tcp_ecn ]
then
echo 0 > /proc/sys/net/ipv4/tcp_ecn
fi
|
Forwarding
Si vous utilisez votre machine Linux comme un routeur, alors vous voudrez
activer l'IP forwarding, ce qui donnera la permission au noyau de transmettre
des paquets de l'interface eth0 à eth1, et inversement. Dans notre exemple de
configuration, oú eth0 est connecté à notre LAN, et eth1 à Internet, activer
l'IP forwarding est une étape nécessaire pour permettre à notre LAN de se
connecter à Internet en passant par notre machine Linux. Pour activer l'IP
forwarding, utilisez cette ligne :
Exemple de code 5.2 : Forwarding |
# echo 1 > /proc/sys/net/ipv4/ip_forward
|
Gestion des rejets
Jusqu'à présent, nous avons ignoré tout le trafic non sollicité venant
d'Internet. Bien que celà soit un moyen efficace pour contrer l'activité réseau
non désirable, cela engendre également quelques inconvénients. Le plus gros
problème avec cette approche est qu'il est facile pour un intrus de détecter
que nous utilisons un pare-feu puisque notre machine ne répond pas avec les
réponses standards TCP reset et ICMP port-unreachable, c'est-à-dire les
réponses qu'une machine normale devrait renvoyer pour indiquer une tentative
de connexion échouée vers un service non existant.
Plutôt que de laisser des intrus potentiels savoir que nous utilisons un
pare-feu (ce qui peut leur laisser penser que nous fournissons des services
précieux auquels ils ne peuvent pas accéder), il serait à notre avantage de
faire croire que nous n'utilisons pas de firewall. En ajoutant ces deux règles
à la fin de la chaîne INPUT, on peut facilement accomplir cette tâche :
Exemple de code 5.3 : Gestion des rejets |
# iptables -A INPUT -p tcp -i eth1 -j REJECT --reject-with tcp-reset
# iptables -A INPUT -p udp -i eth1 -j REJECT --reject-with
icmp-port-unreachable
|
La première règle s'occupe de rejeter correctement les connexions TCP, alors
que la seconde s'occupe de l'UDP. Avec ces deux règles, il devient difficile
pour un intrus de détecter que nous sommes derrière un pare-feu ; avec de
la chance, l'intrus se détournera de notre machine pour chercher d'autres
cibles potentiellement plus intéressantes.
En plus de rendre notre firewall plus discret, ces règles éliminent
aussi le délai lors de la connexion à certains serveurs FTP et IRC. Ce délai
est dû au serveur qui tente de faire une requête ident sur votre machine (en
se connectant sur le port 113), qui échoue après un timeout d'environ 15
secondes. Maintenant, notre firewall va renvoyer un TCP reset et la requête
ident va échouer immédiatement plutôt que de réssayer pendant 15 secondes
(alors que vous attendez patiemment une réponse du serveur).
Protection contre le Spoof
Dans plusieurs distributions, quand une interface réseau est activée, plusieurs
vieilles règles ipchains sont également ajoutées au système. Ces règles
spéciales avaient été ajoutées par les créateurs de la distribution pour
contrer un problème appelé spoofing dans lequel les adresses sources des
paquets ont été trafiqués pour contenir une valeur invalide (c'est une des
choses que les script kiddies font). Bien que l'on pourrait créer des règles
iptables similaires pour bloquer ces paquets spoofés, il y a une manière de
faire plus facile. De nos jours, le noyau a la fonctionnalité intégrée
d'ignorer les paquets spoofés ; il suffit de l'activer par le biais de
l'interface /proc. Voilà comment :
Exemple de code 5.4 : Protection contre le spoofing |
for x in lo eth0 eth1
do
echo 1 > /proc/sys/net/ipv4/conf/${x}/rp_filter
done
|
Ce script shell va indiquer au noyau d'ignorer tous les paquets spoofés sur les
interfaces lo, eth0 et eth1. Vous pouvez soit ajouter ces lignes à votre script
de firewall, soit dans le script qui active vos interfaces lo, eth0 et eth1.
Masquerading
Le NAT (network address translation) et l'IP masquerading, bien que non
directement en rapport avec les pare-feu, sont souvent utilisés en complément.
Nous allons voir deux configurations répandues de NAT/Masquerading que vous
pourrez devoir utiliser. La première règle servira dans les situations où vous
utilisez un lien non permanent vers Internet (ppp0) avec une adresse IP
dynamique.
Exemple de code 5.5 : Masquerading |
# iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
|
Si vous êtes dans cette situation, vous voudrez également convertir mes scripts
de firewall pour que les références à "eth1" (le routeur DSL dans notre
exemple) soient changées en "ppp0". Et il est tout à fait possible d'ajouter
des règles qui font références à "ppp0" alors que cette interface n'existe pas
encore. Dès que ppp0 est activée, tout fonctionnera à merveille. Vérifiez
quannd même que vous avez activé l'IP forwarding.
SNAT
Si vous utilisez une ligne DSL pour vous connecter à Internet, vous avez
probablement une des deux configurations suivantes. Dans la première, votre
routeur DSL ou modem a sa propre adresse IP et s'occupe de la translation
d'adresse pour vous. Si vous êtes dans cette situation, vous n'avez pas besoin
de faire du NAT puisque votre routeur DSL le fait déjà.
Cependant, si vous voulez avoir plus de contrôle sur vos fonctionnalités NAT,
vous pouvez eventuellement, si votre fournisseur d'accès le permet, configurer
votre routeur DSL en mode "bridge" (pont). Dans ce mode, votre pare-feu
devient un élément officiel du réseau de votre fournisseur d'accès et le
routeur DSL s'occupe de relayer le trafic de et vers votre machine Linux de
manière transparente. Il n'a plus besoin d'une adresse IP ; à la place,
eth1 (dans notre exemple) en a une. Si quelqu'un envoie un ping à votre adresse
IP depuis Internet, il recevra une réponse de votre machine Linux et pas de
votre routeur.
Avec ce genre de configuration, vous devrez utiliser SNAT (source NAT) plutôt
que le Masquerading. Voici la ligne que vous devriez rajouter à votre
firewall :
Exemple de code 5.6 : SNAT |
# iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to 1.2.3.4
|
Dans cet exemple, remplacez eth1 par l'interface Ethernet connectée sur votre
routeur DSL ainsi que 1.2.3.4 par votre adresse IP statique (l'IP de votre
interface Ethernet). Encore une fois, n'oubliez pas l'IP forwarding.
Problèmes avec le NAT
Heureusement pour nous, le NAT et le masquerading s'entendent bien sur notre
pare-feu. Quand vous écrivez vos règles de firewall, ignorez simplement que
vous utilisez du NAT. Vos règles doivent accepter, ignorer ou rejeter les
paquets en se basant sur leur "véritables" adresses source et destination. Le
code de filtrage du pare-feu prend en compte l'adresse source d'origine et
l'adresse de destination finale. C'est tant mieux pour nous, puisque cela
permet à notre firewall de fonctionner correctement même si on désactive
temporairement le NAT ou le masquerading.
Comprendre les tables
Dans les exemples de NAT/masquerading précédents, on a ajouté des règles à une
chaîne, mais nous avons également fait des choses un peu différemment.
Remarquez l'option "-t". L'option "-t" permet de choisir la table à laquelle
appartient notre chaîne. Quand cette option n'est pas spécifiée, la table par
défaut est la table "filter". Par conséquent, toutes les commandes précédentes
sans rapport avec le NAT ont modifié la chaîne INPUT qui fait partie de la
table "filter". La table "filter" contient toutes les règles associées à
l'acceptation/rejet de paquets, tandis que la table "nat" (comme vous pouvez le
deviner) contient les règles concernant la translation d'adresse. Il existe
d'autres chaînes iptables qui sont décrites en détail dans la page de manuel
iptables, ainsi que dans les HOWTO de Rusty Russel (cf. dans la section Ressources plus bas pour les liens).
Notre script amélioré
Maintenant que nous avons vu tout un tas d'améliorations possibles, il est
temps de voir un second script plus souple d'activation/désactivation du
firewall :
Exemple de code 5.7 : Notre script amélioré |
#!/bin/bash
UPLINK="eth1"
ROUTER="yes"
NAT="1.2.3.4"
INTERFACES="lo eth0 eth1"
if [ "$1" = "start" ]
then
echo "Demarrage du firewall..."
iptables -P INPUT DROP
iptables -A INPUT -i ! ${UPLINK} -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp -i ${UPLINK} -j REJECT --reject-with tcp-reset
iptables -A INPUT -p udp -i ${UPLINK} -j REJECT --reject-with icmp-port-unreachable
if [ -e /proc/sys/net/ipv4/tcp_ecn ]
then
echo 0 > /proc/sys/net/ipv4/tcp_ecn
fi
for x in ${INTERFACES}
do
echo 1 > /proc/sys/net/ipv4/conf/${x}/rp_filter
done
if [ "$ROUTER" = "yes" ]
then
echo 1 > /proc/sys/net/ipv4/ip_forward
if [ "$NAT" = "dynamic" ]
then
echo "Activation du masquerading (IP dynamique)..."
iptables -t nat -A POSTROUTING -o ${UPLINK} -j MASQUERADE
elif [ "$NAT" != "" ]
then
echo "Activation SNAT (IP statique)..."
iptables -t nat -A POSTROUTING -o ${UPLINK} -j SNAT --to ${UPIP}
fi
fi
elif [ "$1" = "stop" ]
then
echo "Arret du firewall..."
iptables -F INPUT
iptables -P INPUT ACCEPT
iptables -t nat -F POSTROUTING
fi
|
6.
Serveurs avec suivi de connexion
Voir ses règles
Avant de commencer à modifier notre pare-feu pour pouvoir l'utiliser sur un
serveur, je dois vous montrer comment afficher les règles actives sur votre
pare-feu. Pour voir les règles dans la chaîne INPUT de la table filter,
tapez :
Exemple de code 6.1 : Voir les règles |
# iptables -v -L INPUT
|
L'option -v nous donne une sortie verbeuse afin que l'on puisse voir le nombre
total de paquets et d'octets transférés par règle. On peut aussi voir la chaîne
POSTROUTING de la table nat avec la commande suivante :
Exemple de code 6.2 : Voir les règles de la chaîne POSTROUTING de la table nat |
# iptables -t nat -v -L POSTROUTING
Chain POSTROUTING (policy ACCEPT 399 packets, 48418 bytes)
pkts bytes target prot opt in out source destination
2728 170K SNAT all -- any eth1 anywhere anywhere
to:215.218.215.2
|
Prêts pour le service
À l'heure actuelle, notre firewallare-feu ne permet pas au public de se
connecter aux services sur notre machine, car elle accepte seulement les
paquets entrants dans l'état ESTABLISHED ou RELATED. Comme il ignore tous les
paquets NEW entrants, toutes les tentatives de connexion sont systématiquement
rejetées. Cependant, en autorisant sélectivement certains paquets à traverser
notre pare-feu, on peut permettre au public de se connecter aux services que
nous offrons.
HTTP avec suivi
Bien que l'on veuille accepter quelques connexions entrantes, on ne souhaite
tout de même pas les accepter toutes. Il est préférable de partir d'une
politique "rejet par défaut" (comme nous l'avons configuré actuellement) et
d'ouvrir l'accès aux seuls services que l'on souhaite rendre publics. Par
exemple, si nous avons un serveur Web, nous allons autoriser les paquets NEW
vers notre machine, mais seulement s'ils sont destinés au port 80 (HTTP). C'est
tout ce qu'il suffit de faire. Dès que nous autorisons le paquet NEW à passer,
on autorise l'établissement de connexion. Une fois la connexion établie, la
règle existante qui autorise les paquets entrants ESTABLISHED et RELATED entre
en scène, laissant se dérouler la connexion HTTP sans accrocs.
Exemple d'HTTP avec suivi
Jetons un ¿il au c¿ur de notre pare-feu et à la nouvelle règle qui
autorise les connexion HTTP entrantes :
Exemple de code 6.3 : Exemple d'HTTP avec suivi |
iptables -P INPUT DROP
iptables -A INPUT -i ! ${UPLINK} -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport http -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp -i ${UPLINK} -j REJECT --reject-with tcp-reset
iptables -A INPUT -p udp -i ${UPLINK} -j REJECT --reject-with icmp-port-unreachable
|
Cette nouvelle règle autorise les paquets TCP NEW entrants destinés au port 80
(HTTP) de notre machine à entrer. Remarquez la place de cette règle. Il est
important qu'elle soit placée avant notre règle REJECT. Comme iptables
applique seulement la première règle qui correspond, la mettre derrière les
lignes REJECT serait sans effets.
Notre script de pare-feu avancé
Maintenant, voyons notre dernier script de pare-feu qui peut être utilisé sur
un portable, station de travail, routeur ou serveur (ou une quelconque
combinaison !)
Exemple de code 6.4 : Notre script de pare-feu avancé |
#!/bin/bash
UPLINK="eth1"
ROUTER="yes"
NAT="1.2.3.4"
INTERFACES="lo eth0 eth1"
SERVICES="http ftp smtp ssh rsync"
if [ "$1" = "start" ]
then
echo "Démarrage du firewall..."
iptables -P INPUT DROP
iptables -A INPUT -i ! ${UPLINK} -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
for x in ${SERVICES}
do
iptables -A INPUT -p tcp --dport ${x} -m state --state NEW -j ACCEPT
done
iptables -A INPUT -p tcp -i ${UPLINK} -j REJECT --reject-with tcp-reset
iptables -A INPUT -p udp -i ${UPLINK} -j REJECT --reject-with icmp-port-unreachable
if [ -e /proc/sys/net/ipv4/tcp_ecn ]
then
echo 0 > /proc/sys/net/ipv4/tcp_ecn
fi
for x in ${INTERFACES}
do
echo 1 > /proc/sys/net/ipv4/conf/${x}/rp_filter
done
if [ "$ROUTER" = "yes" ]
then
echo 1 > /proc/sys/net/ipv4/ip_forward
if [ "$NAT" = "dynamic" ]
then
echo "Activation du masquerading (ip dynamique)..."
iptables -t nat -A POSTROUTING -o ${UPLINK} -j MASQUERADE
elif [ "$NAT" != "" ]
then
echo "Activation du SNAT (ip statique)..."
iptables -t nat -A POSTROUTING -o ${UPLINK} -j SNAT --to ${UPIP}
fi
fi
elif [ "$1" = "stop" ]
then
echo "Arrêt du firewall..."
iptables -F INPUT
iptables -P INPUT ACCEPT
iptables -t nat -F POSTROUTING
fi
|
7.
Construire un meilleur pare-feu pour serveur
Améliorations
Il est souvent possible de rendre son pare-feu toujours un peu mieux.
Bien sûr, la signification de mieux dépend de vos besoins spécifiques.
Notre script existant peu combler exactement les vôtres, ou peut-être que
quelques retouches seront nécessaires. Cette section est sensée servir de livre
à idées pour vous montrer plusieurs moyens d'améliorer notre pare-feu.
Techniques de log
Jusqu'à présent, nous n'avons pas vu comment logger des événements. Il y a une
cible spéciale appelée LOG que vous pouvez utiliser. Associée à LOG, il y a une
option spéciale appelée --log-prefix qui permet de choisir le texte qui
apparaîtra devant le descriptif du paquet dans les logs du système. Voilà un
exemple de règle LOG :
Exemple de code 7.1 : Exemple de règle LOG |
# iptables -A INPUT -j LOG --log-prefix "Anomalie INPUT:"
|
Vous ne voudrez certainement pas ajouter cette règle en premier dans votre
chaîne INPUT, car elle entraînerait qu'une entrée dans les logs soit créée pour
chaque paquet que vous recevez ! À la place, placez cette règle assez bas
dans la chaîne INPUT pour logguer uniquement les paquets bizarres et autres
anomalies.
Une remarque importante sur la cible LOG. Normalement, quand une règle
correspond à un paquet, ce paquet est soit accepté, rejeté ou ignoré, et les
règles suivantes ne sont pas vérifiées. Cependant, quand une règle LOG
correspond, ce paquet est loggué. Il n'est ni accepté, ni rejeté, ni ignoré. À
la place, le paquet est confronté à la règle suivante, ou bien la règle par
défaut est appliquée s'il n'y a pas de règle suivante.
La cible LOG peut également être combinée avec le module "limit" (décrit dans
la page de manuel iptables) pour éviter d'avoir trop d'entrées dupliquées.
Voilà un exemple :
Exemple de code 7.2 : Limiter la taille des logs |
# iptables -A INPUT -m state --state INVALID -m limit --limit 5/minute -j LOG --log-prefix "Etat INVALID:"
|
Créer vos propres chaînes
iptables vous permet de créer vos propres chaînes qui peuvent être
ensuite spécifiée comme cibles dans vos règles. Pour en apprendre plus à ce
sujet, étudiez le Packet filtering HOWTO hebergé sur le site du projet
netfilter/iptables (http://www.netfilter.org/).
Politique de restriction d'usages
Les pare-feu offrent une grande puissance à ceux qui veulent restreindre les
usages d'un réseau dans une entreprise ou un réseau académique. Vous pouvez
contrôler quels paquets votre machine relaie en ajoutant des règles dans la
chaîne FORWARD. En ajoutant des règles à la chaîne OUTPUT, vous pouvez
également contrôler ce qui arrive aux paquets générés localement, par les
utilisateurs sur la machine Linux elle-même. iptables a aussi l'incroyable
capacité de filtrer les paquets générés localement en fonction de leur
propriétaire (UID ou GID). Pour plus d'informations à ce sujet, cherchez
"owner" (propriétaire) dans la page de manuel iptables.
Autres angles de la sécurité
Dans notre exemple de pare-feu, nous avons supposé que tout le trafic du LAN
interne est digne de confiance et que seul le trafic Internet devait être
filtré avec soin. Selon votre réseau interne, cela peut être ou ne pas être le
cas. Rien ne vous empêche de configurer votre firewall pour vous protéger
également du coté du LAN. Envisagez les autres angles de votre réseau que vous
voulez protéger. Il peut être aussi approprié de configurer deux zones de
sécurité différentes dans votre LAN, chacune avec sa propre politique de
sécurité.
8.
Ressources
tcpdump
Dans cette section, je vous indique des ressources variées que vous trouverez
certainement utiles pour vous aider à mettre au point votre pare-feu.
Commençons par un outil important...
tcpdump est un outil essentiel pour
l'exploration bas niveau des echanges de paquets et pour vérifier que votre
pare-feu fonctionne correctement. Si vous ne l'avez pas, installez-le. Si vous
l'avez, commencez à l'utiliser.
netfilter.kernelnotes.org
Visitez le site web du projet netfilter/iptables
(http://www.netfilter.org). Il fournit un grand nombre de
ressources, y compris les sources de iptables et une FAQ
netfilter. De plus le Rusty's
Remarkably Guides est excellent. Il décit les concepts de base des
réseaux et ajoute des guides netfilter (iptables), NAT et un « netfilter
hacking HOWTO » pour les développeurs.
La page de manuel iptables
Heureusement, de nombreuses ressources sont disponibles en ligne à propos de
Netfilter ; cependant, n'oubliez pas les bases. La page de manuel iptables
est très détaillée et est un excellent exemple de ce à quoi une page de manuel
devrait ressembler. C'est une lecture passionnante.
Guide du routage et du contrôle de trafic avancé
Le Advanced Linux Routing and
Traffic Control HOWTO est disponible (également en
français). Il contient tout un chapitre sur l'utilisation d'iptables pour
le marquage de paquets, puis sur l'utilisation des fonctionnalités de routage
de Linux pour router les paquets en fonction de ces marques.
Note :
Ce guide contient des références vers la fonction de contrôle de trafic
(qualité de service) de Linux (accessible via la commande tc). Cette
nouvelle fonctionnalité, bien que très puissante, est très peu documentée, et
essayer de cerner tous les aspects du contrôle de trafic peut être une tâche
très frustrante pour le moment.
|
Listes de diffusion
Les utilisateurs qui ont des questions sur l'utilisation, l'installation ou la
configuration de Netfilter/iptables, ou qui veulent aider les autres
utilisateurs en partageant leurs experience et connaissances, peuvent contacter
la mailing-list
des utilisateurs de Netfilter.
Les développeurs Netfilter/iptables qui ont des questions, suggestions ou
contributions pour le developpement de Netfilter/iptables peuvent contacter
la mailing-list
des développeurs de Netfilter.
Vous pouvez aussi parcourir les archives sur ces URL.
« Building Internet Firewalls, Second Edition »
En juin 2000, O'Reilly a publié un excellent livre : Building Internet Firewalls,
Second Edition. C'est un bon manuel de référence, en particulier dans les
cas où vous voulez configurer votre pare-feu pour accepter (ou rejeter) un
protocole peu connu avec lequel vous n'êtes pas familier.
Voilà, c'était la liste de nos ressources et ce guide est terminé. J'espère
qu'il vous a été utile et j'attends vos remarques.
Vos remarques
Nous acceptons volontier vos remarques sur ce tutoriel. De plus, n'hésitez pas
à contacter l'auteur, Daniel Robbins, à l'adresse
Daniel Robbins.
|