Gateway IpTables – WAN / LAN / DMZ

images

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 PPPPPPoE 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" &gt; /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" &gt; /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 &gt; 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" &gt; /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" &gt; /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

 

Vus : 11008
Publié par OsEr : 15