Gateway IpTables – WAN / LAN / DMZ
Introduction:
Ce document vous présente la mise en place d’une passerelle afin de segmenter votre réseau entre une zone démilitarisé (DMZ), une zone client (LAN), et votre connexion internet (WAN). Mais avant la pratique, un peut de théorie
IpTables est un outil qui permet de configurer en ligne de commande le pare-feu Netfilter présent dans le noyau linux à partir de la version 2.4.
Les chaînes:
Quand un paquet arrive pour la première fois dans un pare-feu, il rencontre le niveau matériel, puis il est recueilli par le pilote de périphérique approprié au sein du noyau. Ensuite, le paquet enchaîne une succession d’étapes dans le noyau, avant d’être envoyé à l’application adéquate (localement), ou expédié à un autre hôte – ou quoi que ce soit d’autre.
D’abord, analysons un paquet destiné à la machine locale. Il enchaîne les étapes suivantes avant d’être réellement délivré à l’application qui le reçoit :
Comme vous pouvez le constater, il y a de nombreuses étapes à franchir. Un paquet peut être arrêté dans n’importe quelle chaîne d’iptables, et même ailleurs s’il est malformé. Pourtant, il est intéressant de se pencher sur le sort du paquet vu par iptables.
La chaîne INPUT
est systématiquement parcourue par les paquets souhaitant atteindre les processus locaux de la passerelle.
La chaîne OUTPUT
est parcourue par les paquets sortant de la passerelle.
La chaîne FORWARD
est systématiquement parcourue par les paquets qui sont redirigés, ils n’atteindront jamais la couche applicative de la passerelle.
Pour être plus clair. Si un paquet atteignant la première décision de routage n’est pas destiné à la machine locale, il sera orienté vers la chaîne FORWARD
. En revanche, s’il est destiné à une adresse IP
que la machine écoute, ce paquet sera envoyé vers la chaîne INPUT
, et donc à la machine locale.
Il est important de remarquer que même si des paquets sont destinés à la machine locale, leur adresse de destination peut être modifiée à l’intérieur de la chaîne PREROUTING
par une opération de NAT
. En effet, puisque ceci a lieu avant la première décision de routage, le paquet ne sera examiné qu’après un éventuel changement. A cause de cette particularité, le routage peut être altéré avant que la décision de routage ne soit prise. Notez bien que tous les paquets transiteront par l’un ou l’autre des chemins de ce dessin. Si vous réalisez du DNAT
sur un paquet pour le renvoyer sur le réseau duquel il provient, il continuera malgré tout sa route à travers les chaînes restantes jusqu’à ce qu’il retourne sur le réseau externe.
Les tables:
La table FILTER : sert principalement à filtrer les paquets c’est la table que vous utiliserez le plus. On peut établir une correspondance avec des paquets et les filtrer comme on le désire. C’est l’endroit prévu pour intervenir sur les paquets et analyser leur contenu, c’est-à-dire les détruire avec la cible DROP ( -j DROP) ou les accepter avec ACCEPT (-j ACCEPT) suivant leur contenu. Bien entendu, il est possible de réaliser préalablement du filtrage mais cette table a été spécialement conçue pour ça. Presque toutes les cibles sont utilisables dans celle-ci. Vous savez maintenant que c’est l’emplacement idéal pour effectuer votre filtrage principal.
La table NAT : devrait être utilisée seulement pour effectuer de la traduction d’adresse réseau (NAT
) sur différents paquets. Autrement dit, elle ne devrait servir qu’à traduire le champ de l’adresse source d’un paquet ou celui de l’adresse destination. Précisons à nouveau que seul le premier paquet d’un flux rencontrera cette chaîne. Ensuite, les autres paquets subiront automatiquement le même sort que le premier. Voici les cibles actuelles capables d’accomplir ce genre de choses :
- DNAT
- SNAT
- MASQUERADE
- REDIRECT
La cible DNAT est généralement utile dans le cas où vous détenez une adresse IP publique et que vous désirez rediriger les accès vers un pare-feu localisé sur un autre hôte (par exemple, dans une zone démilitarisée ou DMZ
). Concrètement, on change l’adresse de destination du paquet avant de le router à nouveau vers l’hôte désigné.
La cible SNAT est quant à elle employée pour changer l’adresse de source des paquets. La plupart du temps, vous dissimulerez votre réseau local ou votre DMZ
, etc. Un très bon exemple serait donné par un pare-feu pour lequel l’adresse externe est connue, mais qui nécessite de substituer les adresses IP du réseau local avec celle du pare-feu. Avec cette cible, le pare-feu effectuera automatiquement sur les paquets du SNAT dans un sens et du SNAT inverse dans l’autre, rendant possible les connexions d’un réseau local
sur Internet. A titre d’exemple, si votre réseau utilise la famille d’adresses 192.168.0.0/masque_réseau, les paquets envoyés sur Internet ne reviendront jamais, parce que l’IANA (institut de régulation des adresses) a considéré ce réseau (avec d’autres) comme privé, et a restreint son usage à des LAN
isolés d’Internet.
La cible MASQUERADE s’utilise exactement de la même façon que la cible SNAT, mais la cible MASQUERADE demande un peu plus de ressources pour s’exécuter. L’explication vient du fait que chaque fois qu’un paquet atteint la cible MASQUERADE, il vérifie automatiquement l’adresse IP à utiliser, au lieu de se comporter comme la cible SNAT qui se réfère simplement à l’unique adresse IP configurée. Par conséquent, la cible MASQUERADE permet de faire fonctionner un système d’adressage IP dynamique sous DHCP
, que votre FAI devrait vous procurer pour des connexions à Internet de type PPP
, PPPoE
ou SLIP
.
La table MANGLE:
La table Mangle permet de découper, nos paquets avant qu’ils entrent dans la couche réseau, afin que d’autres programmes de la couche Kernel puissent en faire quelque chose. Cette technique va permettre de différencier les paquets, on va donc pouvoir privilégier certains flux afin de garantir une optimisation de la bande passante, entendez bien là qu’on parle de QoS.
Seul les cibles suivante sont valide dans la table Mangle :
- TOS
- TTL
- MARK
- SECMARK
- CONNSECMARK
La cible TOS permet de définir et/ou modifier le champ de Type de Service
d’un paquet. C’est utile pour définir des stratégies réseau concernant le choix de routage des paquets. Sachez que, d’une part ceci n’a pas été perfectionné, d’autre part ce n’est pas vraiment implémenté sur Internet car la majorité des routeurs ne se préoccupent pas de ce champ, et quelquefois même, ils adoptent un comportement erroné. Bref, ne configurez pas ce champ sur les paquets qui naviguent sur Internet, sauf si vous souhaitez leur appliquer des décisions de routage, avec iproute2.
La cible TTL permet de modifier le champ durée de vie ou TTL
(Time To Live) d’un paquet. Il est possible par exemple de spécifier aux paquets d’avoir un champ TTL
spécifique. Ceci peut se justifier lorsque vous ne souhaitez pas être rejeté par certains Fournisseurs d’Accès à Internet (FAI) trop indiscrets. En effet, il existe des FAI qui désapprouvent les utilisateurs branchant plusieurs ordinateurs sur une même connexion, et de fait, quelques-uns de ces FAI sont connus pour vérifier si un même hôte génère différentes valeurs TTL
, supposant ainsi que plusieurs machines sont branchées sur la même connexion.
La cible MARK permet d’associer des valeurs de marquage
particulières aux paquets. Elles peuvent ensuite être identifiées par les programmes iproute2 pour appliquer un routage différent en fonction de l’existence ou de l’absence de telle ou telle marque
. On peut ainsi réaliser de la restriction de bande passante et de la gestion de priorité (Class Based Queuing).
La cible SECMARK peut être utilisée pour placer des marques dans un contexte de sécurité sur des paquets dans SELinux ou tout autre système de sécurité capable de gérer ces marques.
Et enfin la cible CONNSECMARK sert à copier un contexte de sécurité vers ou depuis un simple paquet ou vers une connexion complète. Elle est utilisée par SELinux ou autre système de sécurité pour affiner cette sécurité au niveau connexion.
La machine d’état ou le Traçage de connexion:
Iptables permet de garder en mémoire les paquets qui lui passe sous le nez, afin de savoir si la connexion à déjà était établie ou non. Les paquets peuvent êtres attribués à quatres états différents :
- NEW :
- ESTABLISHED
- RELATED
- INVALID
L’intégralité du traçage de connexion est effectué par une structure particulière à l’intérieur du noyau appelée conntrack. La structure conntrack peut soit être chargée comme un module, soit être interne au noyau. Il faut donc bien vérifier si conntrack est disponible, et dans le cas contraire le charger au début du script.
Le traçage de connexion est entièrement pris en charge dans la chaîne PREROUTING
, sauf pour les paquets générés en local, qui sont pris en charge dans la chaîne OUTPUT
. Ceci signifie qu’iptable effectue tous les calculs d’état dans la chaîne PREROUTING
. Si on envoie le premier paquet d’un flux, l’état est défini comme NEW dans la chaîne OUTPUT
, et quand on reçoit un paquet de réponse, l’état passe à ESTABLISHED, et ainsi de suite. Si le premier paquet n’est pas envoyé par nous-mêmes, l’état NEW est naturellement défini dans la chaîne PREROUTING
. Ainsi, tous les changements d’état et calculs sont réalisés dans les chaînes PREROUTING
et OUTPUT
de la table nat.
La syntaxe :
Avant d’attaquer le script, il faut comprendre comment écrire une règle iptables.
Syntaxe: iptables -t <table> -A <regles> -i <eth_entrée> -o <eth_sortie> -s <ip_source> -d <ip_destination> -p <protocole> –dport <port> -j <cible>
Un exemple de règle:
iptables -t filter -A INPUT -i eth0 -s 192.168.100.0/24 -p icmp -j ACCEPT
On peut donc le traduire par : Dans la table Filter
Bon c’est l’heure de la pause café la non ?
Passons aux choses sérieuses place à la Pratique !
Commençons par nous mettre dans le contexte, le rôle de la passerelle sera de faire le lien entre toutes les interfaces du réseau. Elle va redistribuer internet au deux sous-réseaux, et filtrer les connexions.
On pourrait commencer par ce demander quel filtre appliquer ? Voici un exemple de ce qu’on peut rechercher
- Renvoi d’internet dans le LAN et la DMZ
- Possibilité de ping la passerelle du LAN et de la DMZ mais pas d’internet
- Autoriser que quelques ports bien précis du Lan vers la DMZ
- Renvois du port 80 vers la DMZ pour les nouvelles connexions venant d’internet (en cas d’hébergement Web)
- Autoriser le SSH à partir d’une ip / interface bien précise.
Passons au script :
#!/bin/sh # Script "iptables.sh" # Fichier contenant les règles de filtrage "iptables" DMZ=eth0 WAN=eth3 LAN=eth1 _stop(){ # REMISE à ZERO des règles de filtrage iptables -F iptables -X iptables -t nat -F iptables -t nat -X iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT echo "0" > /proc/sys/net/ipv4/ip_forward echo "--------- Firewall désactivé ----------" #exit } _start(){ ###################################### INITIALISATION ################################# #Chargement des modules echo " + Initialisation des modules" modprobe ip_conntrack_ftp modprobe ip_nat_ftp modprobe ip_conntrack_irc modprobe ip_conntrack modprobe iptable_nat modprobe iptable_filter # Initialise la table Filter (par defaut tout les echanges sont refuses) echo " + Initialisation de la table Filter" iptables -t filter -F iptables -t filter -X iptables -t filter -P INPUT DROP iptables -t filter -P FORWARD DROP iptables -t filter -P OUTPUT DROP # Initialise la table NAT (par defaut tout les echanges sont actives) echo " + Initialisation de la table NAT" iptables -t nat -F iptables -t nat -X iptables -t nat -P PREROUTING ACCEPT iptables -t nat -P OUTPUT ACCEPT iptables -t nat -P POSTROUTING ACCEPT # Initialise la table Mangle (par defaut tout les echanges sont actives) echo " + Initialisation de la table MANGLE" iptables -t mangle -F iptables -t mangle -X iptables -t mangle -P PREROUTING ACCEPT iptables -t mangle -P INPUT ACCEPT iptables -t mangle -P FORWARD ACCEPT iptables -t mangle -P OUTPUT ACCEPT iptables -t mangle -P POSTROUTING ACCEPT ###################################### LoopBack ####################################### iptables -t filter -A OUTPUT -o lo -s 127.0.0.0/8 -d 127.0.0.0/8 -j ACCEPT iptables -t filter -A INPUT -i lo -s 127.0.0.0/8 -d 127.0.0.0/8 -j ACCEPT ###################################### ICMP / PING ##################################### # CLIENT iptables -t filter -A INPUT -i $LAN -s 192.168.200.0/24 -p icmp -j ACCEPT iptables -t filter -A OUTPUT -o $LAN -d 192.168.200.0/24 -p icmp -j ACCEPT ## DMZ iptables -t filter -A INPUT -i $DMZ -s 192.168.100.0/24 -p icmp -j ACCEPT iptables -t filter -A OUTPUT -o $DMZ -d 192.168.100.0/24 -p icmp -j ACCEPT ####################################### SSH ########################################## iptables -t filter -A INPUT -p tcp --dport 22 -j ACCEPT iptables -t filter -A OUTPUT -p tcp --sport 22 -j ACCEPT #################################### PARTAGE CONNEXION ############################### ##Activation du routage echo "1" > /proc/sys/net/ipv4/ip_forward ## Masquerading iptables -t nat -A POSTROUTING -s 192.168.200.0/24 -o $WAN -j MASQUERADE iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o $WAN -j MASQUERADE ## FORWARD du port 80 iptables -A FORWARD -i $WAN -p tcp --dport 80 -j ACCEPT ###################################################################################### # REGLES GENERAL CLIENT # ###################################################################################### #Garde les connexions actives vers l'exterieur iptables -A FORWARD -i $WAN -o $LAN -s 0.0.0.0/0 -d 192.168.200.0/24 -m state \\ --state RELATED,ESTABLISHED -j ACCEPT #Autorise la création de nouvelles connexions vers l'exterieur iptables -A FORWARD -i $LAN -o $WAN -s 192.168.200.0/24 -d 0.0.0.0/0 -m state \\ --state NEW,RELATED,ESTABLISHED -j ACCEPT ###################################################################################### # REGLES GENERAL DMZ # ###################################################################################### ###### DMZ EXT ###### #Garde les connexions actives vers l'exterieur depuis la DMZ iptables -A FORWARD -i $WAN -o $DMZ -s 0.0.0.0/0 -d 192.168.100.0/24 -m state \\ --state RELATED,ESTABLISHED -j ACCEPT #Autorise la création de nouvelles connexions vers l'exterieur depuis DMZ iptables -A FORWARD -i $DMZ -o $WAN -s 192.168.100.0/24 -d 0.0.0.0/0 -m state \\ --state NEW,RELATED,ESTABLISHED -j ACCEPT ##### DMZ CLIENT ##### #Autorise le transfert entre client > DMZ iptables -A FORWARD -i $LAN -o $DMZ -s 192.168.200.0/24 -d 192.168.100.0/24 -j ACC EPT iptables -A FORWARD -i $DMZ -o $LAN -s 192.168.100.0/24 -d 192.168.200.0/24 -j ACC EPT # iptables -t nat -A INPUT -i $DMZ -s 192.168.100.0/24 -d 192.168.200.0/24 -p tcp -- dport 80 -j ACCEPT # iptables -t nat -A OUTPUT -o $LAN -s 192.168.100.0/24 -d 192.168.200.0/24 -p tcp - -sport 80 -j ACCEPT echo "--------- Firewall activé ----------" exit } case "$1" in start) _start ;; stop) _stop ;; restart) _stop _start ;; *) echo "Usage: {start|stop|restart}" exit 1 esac
Voila qui est fait j’espère qu’il ne vous a pas fait trop peur, vous allez voir c’est assez simple. Commençons par le décortiquer :
#!/bin/sh # Script "iptables.sh" # Fichier contenant les règles de filtrage "iptables" DMZ=eth0 WAN=eth3 LAN=eth1 _stop(){ # REMISE à ZERO des règles de filtrage iptables -F iptables -X iptables -t nat -F iptables -t nat -X iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT echo "0" > /proc/sys/net/ipv4/ip_forward echo "--------- Firewall désactivé ----------" #exit }
Nous commençons par déclarer les variables, je ne peux que vous inviter à rentrer un maximum de variable afin de ne pas devoir refaire votre script à chaque modification d’interface ou de plage-IP.
Dans la section _stop() nous déclarons les commandes de réinitialisation d’Iptables, elles vident les règles et remette les règles par défaut sur ACCEPT, on désactive par la même occasion le routage.
_start(){ ###################################### INITIALISATION ################################# #Chargement des modules echo " + Initialisation des modules" modprobe ip_conntrack_ftp modprobe ip_nat_ftp modprobe ip_conntrack_irc modprobe ip_conntrack modprobe iptable_nat modprobe iptable_filter # Initialise la table Filter (par defaut tout les echanges sont refuses) echo " + Initialisation de la table Filter" iptables -t filter -F iptables -t filter -X iptables -t filter -P INPUT DROP iptables -t filter -P FORWARD DROP iptables -t filter -P OUTPUT DROP # Initialise la table NAT (par defaut tout les echanges sont actives) echo " + Initialisation de la table NAT" iptables -t nat -F iptables -t nat -X iptables -t nat -P PREROUTING ACCEPT iptables -t nat -P OUTPUT ACCEPT iptables -t nat -P POSTROUTING ACCEPT # Initialise la table Mangle (par defaut tout les echanges sont actives) echo " + Initialisation de la table MANGLE" iptables -t mangle -F iptables -t mangle -X iptables -t mangle -P PREROUTING ACCEPT iptables -t mangle -P INPUT ACCEPT iptables -t mangle -P FORWARD ACCEPT iptables -t mangle -P OUTPUT ACCEPT iptables -t mangle -P POSTROUTING ACCEPT
Les choses intéressante arrivent, le script s’exécute verticalement, c’est a dire qu’Iptables va appliquer les règles dans le sens de lecture de haut en bas, nous commençons par initialiser les règles afin d’être sur qu’il n’y ait pas de vielles règles qui traînent dans le cas d’une nouvelle exécution du script alors que des règles seraient déjà appliqués.
Puis on attribue la règle DROP par défaut sur les tables INPUT, FORWARD, OUTPUT
iptables -t filter -P INPUT DROP iptables -t filter -P FORWARD DROP iptables -t filter -P OUTPUT DROP
A ce stade là, pour votre passerelle c’est comme si elle n’a plus aucun câble de branché … même un ping localhost ne passe plus :p Essayez !!
On va donc commencer par autoriser la passerelle à pouvoir communiquer avec son interface Loopback (lo):
###################################### LoopBack ####################################### iptables -t filter -A OUTPUT -o lo -s 127.0.0.0/8 -d 127.0.0.0/8 -j ACCEPT iptables -t filter -A INPUT -i lo -s 127.0.0.0/8 -d 127.0.0.0/8 -j ACCEPT
Pour ne pas vous couper la connexion ssh il ne faut pas oublier d’ajouter dès le début une règle autorisant les flux SSH.
####################################### SSH ########################################## iptables -t filter -A INPUT -p tcp --dport 22 -j ACCEPT iptables -t filter -A OUTPUT -p tcp --sport 22 -j ACCEPT
A partir de là, vous devez normalement pouvoir ping votre propre interface, et établir une connexion SSH vers votre passerelle.
Le partage de la connexion :
Nous allons indiquer au noyau qu’on veut activer le routage de packets :
##Activation du routage echo "1" > /proc/sys/net/ipv4/ip_forward
Puis le Masquerading afin que la passerelle cache le reste du réseau. Pour l’éxterieur toutes les requettes proviendrons de la passerelle.
## Masquerading iptables -t nat -A POSTROUTING -s 192.168.200.0/24 -o $WAN -j MASQUERADE iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o $WAN -j MASQUERADE
Il n’y a plus qu’a autoriser le FORWARD du port 80 et votre passerelle sera en mesure de renvoyer internet vers vos réseaux.
iptables -A FORWARD -i $WAN -p tcp --dport 80 -j ACCEPT
Le réseau CLIENT :
Nous souhaitons que le réseau Client soit joignable de l’extérieur uniquement si la connexion a déjà été établie, et nous souhaitons que le réseau client puisse établir de nouvelles connexions vers l’extérieur.
###################################################################################### # REGLES GENERAL CLIENT # ###################################################################################### #Garde les connexions actives vers l’extérieur iptables -A FORWARD -i $WAN -o $LAN -s 0.0.0.0/0 -d 192.168.200.0/24 -m state \\ --state RELATED,ESTABLISHED -j ACCEPT #Autorise la création de nouvelles connexions vers l'exterieur iptables -A FORWARD -i $LAN -o $WAN -s 192.168.200.0/24 -d 0.0.0.0/0 -m state \\ --state NEW,RELATED,ESTABLISHED -j ACCEPT
En français :
Pour le FORWARD, ce qui rentre par $WAN, sort par $LAN, provenant de l’adresse ip 0.0.0.0/0 (ALL) à destination du réseau 192.168.200.0/24 J’autorise les connexion déjà établie ou en cour d’établissement.
Pour le FORWARD, ce qui rentre par $LAN, sort par $WAN, provenant de l’adresse ip 192.168.200.0/24 à destination du réseau 0.0.0.0/0, j’autorise les nouvelles connexions, les connexions déjà établies ou en cours d’établissements.
Quelques liens utiles:
http://olivieraj.free.fr/fr/linux/information/firewall/index.html
http://www.lea-linux.org/documentations/index.php/Reseau-secu-iptables
http://www.taltan.fr/post/2006/06/08/21-netfilter-scripts-de-configuration-iptables