Paramètrer son firewall Gnu/Linux avec Iptables et Netfilter

La plupart des nouveaux utilisateurs de systèmes Gnu/Linux partent du postulat qu’utiliser Linux est bien plus sûr qu’un Windows, et que de fait, il n’est pas forcément nécessaire d’avoir un firewall, ou encore de passer du temps à paramétrer son système. Ils ont évidement tort, considérer Linux comme plus secure que Windows est une erreur, et ne pas fine-tuner son OS en est une autre. Il existe pourtant un module qui fournit à Linux l’intégralité des fonctions de pare-feu: Netfilter. Il intercepte et manipule les paquets IP avant et après le routage. Pour configurer Netfilter en espace utilisateur, on utilise Iptables. Je dois souvent proposer aux administrateurs et utilisateurs une explication sommaire sur les configurations possibles d’un firewall que j’estime saines. Ce billet reprend quelques-une des informations que je met en avant dans certains rapports d’audit. Nous discutons souvent avec des administrateurs qui ne maîtrisent Iptables qu’à l’aide de tutos trouvés ça et là (forum / wiki) sur Internet et de vagues souvenirs d’école d’ingénieur ou de la faculté.

Cet article n’a pas la prétention d’être parfaitement exhaustif, mais je pense qu’il constitue une première approche saine de compréhension et de travail. Correctement utilisé, il peut permettre à certains administrateurs d’éviter de faire cette tête lors de la prochaine restitution de leur QSA ou société de sécurité informatique.

 

g1NOCAw

Introduction

IPtables est le nom communément utilisé pour désigner les outils en espace utilisateur et le framework en espace noyau Netfilter permettant de filtrer l’activité réseau sous GNU/Linux. Construit de façon modulaire, cet outil permet de réaliser facilement des pare-feux puissants et intelligents.

Le principe directeur d’IPtables est de faire cheminer chaque paquet par une « table » composée de « chaînes » filtrantes. Par défaut, les paquets passent dans la table « filter », qui contient trois chaînes prédéfinies: les paquets entrants empruntent la chaîne INPUT, les sortants OUTPUT, et les paquets devant être routés passent par la chaîne FORWARD. Chacune de ces chaînes a une politique par défaut, présidant à la destinée du paquet qui la parcourt.

Il est possible de créer de nouvelles chaînes à volonté, mais celles-ci ne pourront pas avoir de politique par défaut; si un paquet les traverse entièrement, il sera renvoyé à la chaîne qu’il avait précédemment parcouru. Chaque chaîne est une succession de rêgles, auxquelles il est possible d’ajouter une « cible » indiquant une action à effectuer sur le paquet. Tant qu’un paquet ne correspond pas à une règle, il continue sa progression le long de la chaîne; dans le cas contraire, le paquet sera traité en fonction de la « cible » définie.

La grande force d’IPtables réside dans sa modularité; ainsi, en chargeant d’autres modules, d’autres tables peuvent être crées, comme la table « nat » gérant la traduction d’adresse, ou « mangle » pour la modification des paquets. Il est également possible de traquer l’état des différentes connections (statefullness), permettant de filter les paquets suivant leur contexte.

Sortons couvert

Avant de commencer l’écriture d’un pare-feu, il est judicieux de sécuriser au maximum la couche réseau du système d’exploitation. Le noyau Linux est hautement configurable, et plusieurs options accessibles via le système de fichier /proc permettent une sécurité accrue:

    • /proc/sys/net/ipv4/conf/all/rp_filter
      Cette option permet d’activer la protection anti-spoofing du noyau. Ainsi, la plupart des paquets suspects seront directement éliminés avant même de passer nos rêgles de filtrage.
    • /proc/sys/net/ipv4/conf/all/accept_source_route
      Ce paramètre est à désactiver. Un attaquant peut utiliser le source routing pour générer du trafic venant prétendument du réseau local, mais qui sera rerouté par le chemin par lequel il était arrivé, c’est à dire le réseau de l’attaquant.
    • /proc/sys/net/ipv4/tcp_syncookies
      Les SYN cookies permettent de lutter contre une attaque de type SYN flood, où un attaquant sature le réseau avec des connections incomplètes. Cette technique permet de continuer à accepter les connections légitimes en cas d’attaque.
    • /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
    • /proc/sys/net/ipv4/conf/all/accept_redirects
    • /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
      Ces options relatives au protocole ICMP sont à sécuriser pour éviter d’être la victime ou participant involontaire de certaines attaques de type déni de service.

La procédure d’initialisation de notre firewall commencera donc par les lignes suivantes:

Rêgles de base

La stratégie de base d’un firewall sûr est de commencer par bloquer tout le trafic, puis d’autoriser au cas pas cas les usages légitimes du réseau. Cette approche repose sur le principe qu’il vaut mieux, en cas d’erreur, bloquer du trafic légitimes, plutôt que de laisser passer une attaque.

Ceci est accompli très facilement en initialisant nos chaînes iptables avec la politique DROP. Ainsi, en l’absence de rêgles plus complexe, le comportement par défaut sera de bloquer silencieusement tous les paquets.

À partir de cette base saine, nous pouvons dès lors commencer à autoriser le trafic légitime, comme l’interface loopback (locale), le réseau local, et les connections que nous initions nous même vers l’extérieur.

Dans la suite de cet exemple, la variable $LAN correspond à l’interface réseau reliée au réseau local, et $LAN_ADDR à l’adresse IP de cette interface. $LAN_NET et $LAN_BCAST correspondent à l’adresse et au masque de sous réseau utilisés par le réseau local. De la même façon, $INET correspond à l’interface réseau reliée à internet et $INET_ADDR à son adresse IP.

 

Avec ces quelques règles, nous disposons d’une protection basique mais efficace; nous pouvons accéder à Internet, sans toutefois nous exposer. Notre machine rejette tout paquet non sollicité et est donc invisible aux yeux d’un attaquant.

Paquet indésirable

Enregistrer les paquets rejetés peut être intéressant pour plusieurs raisons; en cas d’attaque, cela permet de collecter des informations sur la nature de l’attaque et éventuellement l’attaquant. Au quotidien, cela permet de pouvoir au besoin détecter un usage légitime bloqué afin de l’autoriser.

Pour cela, nous allons ajouter en destination finale de toutes les chaînes une cible LOG, afin d’utiliser les journaux systèmes.

$LOG_LEVEL représente le niveau de sévérité de l’enregistrement dans le journal du système. Le niveau « info » est recommandé, le bloquage d’un paquet étant un évènement courant. Le préfixe $PRE permettra de retrouver facilement les enregistrements spécifiques aux paquets bloqués dans le journaux grâces à des outils comme grep ou sed.

Plaisir partagé

Si notre machine doit servir de bouclier à un réseau local, il faut pouvoir également partager la connection aux machines protégées. IPtables permet de partager une connection très simplement, en utilisant le module « nat ».

Grâce à cette fonction, les machines que nous protégeons peuvent accéder à internet, mais ne peuvent pas héberger de services. En effet, nous filtrons toutes les connections extérieures. IPtables permet cependant de rediriger facilement le traffic arrivant sur un des ports réseau de notre machine vers la machine appropriée de notre réseau local, en utilisant la chaîne PREROUTING.

« Je suis très ouvert »

L’exemple que nous avons développé dans la première partie est simple mais limité – suffisant pour un ordinateur personnel ou une station de travail, mais complètement inadapté à un serveur. En effet, il n’est pas possible d’accéder à un quelconque service réseau hébergé sur la machine protégée. Nous allons donc voir comment accepter du trafic sur un ou plusieurs ports réseau.

Nous allons pour cela utiliser la fonctionnalité stateful d’IPtables, (module « state ») afin de n’accepter que les connections légitimes:

Grâce à cette fonction, il est désormais trivial d’ouvrir un port: il suffit d’utiliser la ligne port_allow tcp 80 pour autoriser l’accès à un serveur HTTP, ou bien port_allow tcp 22 pour SSH.

Cependant, il est parfois utile de prévoir des protections supplémentaires. Par exemple, beaucoup d’administrateurs parcourant leur journaux systèmes y trouveront des traces d’attaque de type « force brute » contre leur serveur SSH. Comment y remédier? Certains optent pour une authentification uniquement cryptographique, d’autres déménagent leur serveur SSH sur un port moins fréquenté. En utilisant IPtables, il est possible de remédier à ces attaques sans devoir changer la configuration du serveur SSH.

Ceinture de chasteté

Comment endiguer une attaque de type « force brute » ? Dans ce genre d’agression, l’attaquant se connecte au serveur un grand nombre de fois, en essayant chaque fois des codes d’accès différents. Il n’est pas possible de différencier cette attaque d’une connection légitime par le contenu du trafic, mais en revanche la fréquence des connections est particulièrement révélatrice. En limitant la fréquence des connections sur un port réseau, on peut ainsi rendre une attaque « force brute » complètement inneficace. Nous utiliserons pour cela le module « recent ».

En remplaçant port_allow tcp 22 par protect_bruteforce 22, notre serveur SSH sera à l’abri de ces attaques. Le module « recent » permet de créer d’autres dispositifs intéressants. Voyons par exemple comment dissimuler un service, en n’ouvrant son port que si la bonne combinaison de ports réseau est contactée.

Toc toc qui est là?

Pour ce faire, nous allons créer de nouvelles chaînes; chaque fois que l’un des ports de déblocage sera contacté, nous avancerons d’une chaîne vers l’ouverture du port dissimulé:

Nous pouvons maintenant astucieusement dissimuler notre serveur SSH derrière la combinaison de 4 ports 665, 201314, 66 et 520 de la façon suivante: protect_portknocking 22 10 665 201314 66 520

J’espère que cet article vous aura permis de découvrir des aspects d’IPtables avec lesquels vous n’étiez pas familiers, et partant, vous aura permis d’en finir avec les comportements à risque. Sortons couverts. Encore une fois, l’article n’est pas exhaustif, vous pouvez le compléter à loisir.

Partagez cet article !

    One thought on “Paramètrer son firewall Gnu/Linux avec Iptables et Netfilter

    1. Eset dit :

      Sur notre serveur, on a justement un système du genre, sans en réveler la topographie, un pare-feu filtre la route dunet aux serveurs, nat, masquerade etc.

      Dans la partie « sortons couvert », vous parlez de configuration réseaux réduisant le risque d’attaque, qu’en est-elle au niveau des performances ?

      On a essayé d’utiliser un IDS l’année passée, ce n’est même pas la peine, ça pompe énormément de CPU »et ça ralentit énormément le passage des paquets…

    Laisser un commentaire

    Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *