Sommaire |
Contact : chez apinc point org duracell chez apinc point org
révision par Jice <chez lea-linux point org jice chez lea-linux point org>
révision par Fred <chez lea-linux point org fred chez lea-linux point org>
révision par Jiel <chez lea-linux point org jiel chez lea-linux point org>
Cet article présente de façon pratique la mise en place d'un firewall / proxy sur une machine GNU/Linux tournant avec un noyau 2.4 (au moins).
Pour des informations plus théoriques sur les firewall/proxies, vous pouvez lire l'article firewall.
IpTables est une solution complète de firewall (noyau 2.4) remplaçant ipchains (noyau 2.2) tournant sous le système GNU/Linux. IpTables permet de faire du firewalling stateful (à états), de la translation de port et d'adresse, du filtrage au niveau 2 et beaucoup d'autres choses que nous n'allons pas aborder comme le "Mangle" ou modification des paquets à la volée (atchoum).
IpTables est fiable et dispose de très nombreuses options qui permettent de faire du filtrage très fin.
Une précision: on parle souvent de « iptables » par abus de langage, alors que le nom du logiciel est « Netfilter ». Netfilter est le module qui fournit à GNU/Linux les fonctions de pare-feu, de partage de connexions internet (NAT) et d'historisation du trafic réseau. iptables est en fait juste l'outil qui permet à un administrateur de configurer Netfilter en mode utilisateur. iptables-restore et iptables-save sont deux commandes associées qui permettent de sauvegarder/restaurer la configuration Netfilter.
NetFilter est sous licence libre GPL,
IpTables est installé en standard sur de nombreuses distributions GNU/Linux récentes (kernel 2.4.x. ou supérieur).
IpTables a besoin au minimum d'un noyau 2.4 compilé avec des options spéciales. Ceci ne pose pas de problèmes avec les noyaux 2.4 génériques des principales distributions.
Si vous désirez re-compiler votre kernel, il faut spécifier les options nécessaires au fonctionnement d'iptables.
Les options suivantes doivent êtres activées en module (M) ou dans le kernel (Y) :
CONFIG_PACKET
CONFIG_NETFILTER
CONFIG_IP_NF_CONNTRACK
CONFIG_IP_NF_FTP
CONFIG_IP_NF_IRC
CONFIG_IP_NF_IPTABLES
CONFIG_IP_NF_FILTER
CONFIG_IP_NF_NAT
CONFIG_IP_NF_MATCH_STATE
CONFIG_IP_NF_TARGET_LOG
CONFIG_IP_NF_MATCH_LIMIT
CONFIG_IP_NF_TARGET_MASQUERADE
et éventuellement :
CONFIG_IP_NF_COMPAT_IPCHAINS pour garder la compatibilité avec ipchains.
CONFIG_IP_NF_COMPAT_IPFWADM pour garder la compatibilité avec ipfwadm.
CONFIG_IP_NF_TARGET_REDIRECT indispensable, pour les proxies transparents par exemple.
CONFIG_IP_NF_MATCH_MAC permet de matcher avec les adresses MAC.
Ne pas oublier le support réseau et TCP/IP et compiler le kernel comme d'habitude :
make dep && make clean && make bzImage && make modules && make modules_install
Récupérer le package netfilter et l'installer comme d'habitude avec apt-get, urpmi, emerge...
Notons que sur les versions inférieures a Red Hat 7.1, il faut compiler un kernel 2.4 car iptables ne supporte pas les kernels 2.2.x. La compilation de iptables est complexe. Le mieux est de lire le fichier INSTALL du package des sources.
Dans le cas ou les options iptables du kernel ont été compilées en modules, il est nécessaire de charger ces modules avant de pouvoir utiliser iptables :
# modprobe ip_tables
selon les besoins, on peut éventuellement charger les modules suivants :
# modprobe ip_nat_ftp
# modprobe ip_nat_irc
# modprobe iptable_filter
# modprobe iptable_mangle
# modprobe iptable_nat
Si on a besoin de pouvoir rediriger (forward) les paquets IP arrivant sur un interface réseau (connectée par exemple à Internet) vers une autre interface réseau (connectée par exemple au réseau local), il sera nécessaire, dans la plupart des cas, d'exécuter cette commande :
# echo 1 > /proc/sys/net/ipv4/ip_forward
afin de l'indiquer au noyau.
Nota Bene : tous les modprobe semblent inutiles car le kernel les charge automatiquement si l'on se sert de l'une des fonctionnalités d'iptables.
A noter : Les règles sont évaluées dans l'ordre, par défaut la table FILTER est vide et donc accepte tout. Aucune règle de translation d'adresse n'est présente par défaut.
IpTables n'est pas livré avec une interface graphique ; les commandes et les règles sont passées en ligne de commande. Le mieux est d'écrire des scripts (à rajouter dans /etc/rc.d/init.d) qui permettent d'appliquer toutes les règles d'un seul coup, dès le démarrage du GNU/Linux.
-A --append : Ajoute la règle à la fin de la chaîne spécifiée
Exemple :
# iptables -A INPUT ...
-D --delete : Permet de supprimer une chaîne. On peut l'utiliser de 2 manières, soit en spécifiant le numéros de la chaîne a supprimer, soit en spécifiant la règle à retirer.
Exemples :
# iptables -D INPUT --dport 80 -j DROP
# iptables -D INPUT 1
-R --replace : Permet de remplacer la chaîne spécifiée.
Exemple :
# iptables -R INPUT 1 -s 192.168.0.1 -j DROP
-I --insert : Permet d'ajouter une chaîne dans un endroit spécifié de la chaîne.
Exemple :
# iptables -I INPUT 1 --dport 80 -j ACCEPT
Si aucun chiffre n'est spécifié à la suite (#iptables -I INPUT --dport 80 -j ACCEPT), la règle est ajoutée au début de la chaîne spécifiée
-L --list : Permet d'afficher les règles.
Exemples :
# iptables -L # Affiche toutes les règles des chaînes de FILTER
# iptables -L INPUT # Affiche toutes les règles de INPUT (FILTER)
-F --flush : Permet de vider toutes les règles d'une chaîne.
Exemple :
# iptables -F INPUT
-N --new-chain : Permet de créer une nouvelle chaîne.
Exemple :
# iptables -N LOG_DROP
-X --delete-chain : Permet d'effacer une chaîne.
Exemple :
# iptables -X LOG_DROP
-P --policy : Permet de spécifier au noyau la politique par défaut d'une chaîne DENY, ACCEPT, REJECT, DROP ...
Exemple :
# iptables -P INPUT DROP
Remarques :
Le "!" peut être utilisé pour certaines commandes afin de spécifier le contraire (on peut le traduire par "sauf"). Par exemple une commande qui doit refuser tout trafic TCP sauf ce qui provient de l'adresse IP 10.42.42.42 sera traduite par la commande suivante :
Exemple :
# iptables -A INPUT -p tcp --source ! 10.42.42.42 -j DROP
Les adresses IP peuvent optionnellement être spécifiées avec le masque associé sous la forme [adresse ip]/[masque].
-j (jump) : Défini l'action à prendre si un paquet répond aux critères de cette règle: ACCEPT, LOG, DROP...
Exemple :
# iptables -A INPUT -p icmp -j DROP
-p --protocol : Spécifier un protocole : tcp, udp, icmp, all (tous)
Exemple :
# iptables -A INPUT -p icmp -j DROP
-s --source : Spécifier une adresse source à matcher
Exemple :
# iptables -A INPUT -p tcp -s 192.168.42.42 -j ACCEPT
-d --destination : Spécifier une adresse destination
Exemple :
# iptables -A FORWARD -p tcp -d 10.1.0.1 -j ACCEPT
-i --in-interface : Spécifier une interface d'entrée
Exemple :
# iptables -A INPUT -p icmp -i eth0 -j DROP
-o --out-interface : Spécifier une interface de sortie
Exemple :
# iptables -A OUTPUT -p icmp -o eth0 -j DROP
-f --fragment : Paquet fragmenté
Exemple :
# iptables -A INPUT -p icmp -f -j DROP
--sport --source-port : Spécifier le port source ou une plage de ports, fonctionne aussi en udp, -m multiport permet de
spécifier plusieurs ports à matcher.
Exemples :
# iptables -A INPUT -p tcp --sport 80 -j ACCEPT
# iptables -A INPUT -p udp --sport 80 -j DROP
# iptables -A OUTPUT -p tcp -m multiport --sport 3128,21,1000 -j DROP
# iptables -A OUTPUT -p tcp --sport 1024:2042 -j ACCEPT
--dport --destination-port : Spécifier le port destination ou une plage de ports, fonctionne aussi en udp, -m multiport
permet de spécifier plusieurs ports a matcher.
Exemples :
# iptables -A INPUT -p tcp --dport 110 -j DROP
# iptables -A INPUT -p udp --dport 110 -j DROP
# iptables -A INPUT -p tcp -m multiport --dport 110,4242,119 -j DROP
# iptables -A INPUT -p tcp --sport 4925:4633 -j ACCEPT
--tcp-flags : Spécifier un flag tcp à matcher : SYN ACK FIN RST URG PSH ALL NONE
Exemple :
# iptables -A INPUT -p tcp --dport 42 --tcp-flags SYN,ACK -j ACCEPT
--icmp-type : Spécifier un type de paquet icmp à matcher
Exemple :
# iptables -A INPUT -p icmp --icmp-type 8 -j DROP
--mac-source : Spécifier l'adresse MAC à matcher
Exemple :
# iptables -A INPUT --mac-source 42.42.AA.42.42.AA -j DROP
En cas d'erreur, il peut-être nécessaire de spécifier le module mac, exemple :
# iptables -A INPUT -m mac --mac-source 42.42.AA.42.42.AA -j DROP
--state : Permet de spécifier l'état du paquet à matcher parmi les états suivants :
ESTABLISHED : paquet associé à une connexion déjà établie
NEW : paquet demandant une nouvelle connexion
INVALID : paquet associé à une connexion inconnue
RELATED : Nouvelle connexion mais liée, idéal pour les connexions FTP
Exemples :
# iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
Spécificités NAT :
--to-destination : Utilisé en target pour le DNAT, permet de spécifier l'adresse de destination de la translation, on peut également spécifier un port s'il est différent du port source.
Exemples :
# iptables -t nat -A PREROUTING -d 42.12.42.12 -p tcp --dport 110 -j DNAT --to-destination 192.168.1.2:6110
# iptables -t nat -A PREROUTING -d ! 42.12.42.12 -p tcp --dport 80 -j DNAT --to-destination 192.168.2.1:3128
--to-source : Utilisé pour en target pour le SNAT, permet de spécifier l'adresse source de la translation.
Spécificités pour les LOGS :
--log-level : Level, niveau de log
Exemple : Cf. chapitre 3
--log-prefix : Permet de spécifier un préfixe pour les logs.
Exemple : Cf. chapitre 3
Les exemples qui suivent supposent que vous êtes reliés à internet par modem via l'interface ppp0 (mais en remplaçant ppp0 par eth0 - par exemple, on peut adapter les exemples pour d'autres type de liaisons) et que votre réseau local est 192.168.1.0/24 (classe C).
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
iptables -N LOG_DROP
iptables -A LOG_DROP -j LOG --log-prefix '[IPTABLES DROP] : '
iptables -A LOG_DROP -j DROP
iptables -A FORWARD -j LOG_DROP
iptables -A INPUT -j LOG_DROP
iptables -A OUTPUT -j LOG_DROP
Enfin (pour loguer le trafic autorisé), recommencer en remplaçant -j DROP, par -j ACCEPT et a la place de -j LOG_DROP il faut mettre -j LOG_ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT
iptables -A OUTPUT -d 192.168.1.0/24 -j ACCEPT
iptables -A FORWARD -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -i ppp0 --protocol udp --source-port 53 -j ACCEPT
iptables -A OUTPUT -o ppp0 --protocol udp --destination-port 53 -j ACCEPT
iptables -A INPUT -i ppp0 --protocol tcp --source-port 53 -j ACCEPT
iptables -A OUTPUT -o ppp0 --protocol tcp --destination-port 53 -j ACCEPT
iptables -A INPUT -i ppp0 --protocol tcp --source-port 80 -m state --state ESTABLISHED -j LOG_ACCEPTLa première ligne pour accepter ce qui entre sur notre interface ppp0 sur le port 80 (le port http) si c'est une connexion déjà établie, la seconde pour accepter ce qui sort sur ppp0 sur le port 80 si c'est une nouvelle connexion ou si c'est une connexion déjà établie.
iptables -A OUTPUT -o ppp0 --protocol tcp --destination-port 80 -m state --state NEW,ESTABLISHED -j LOG_ACCEPT
Pour autoriser le ssh, il faut préciser le port 22; pour autoriser l'irc, le port 6667 (ou celui que vous utilisez pour vous connecter à votre serveur); pour le smtp (envoi d'emails), le port 25; pour le pop3 (réception d'emails), le port 110; pour le imap (réception d'emails), les ports 143 et 220 (imap3) ; pour le cvs, le port 2401 ; pour le https, le port 443. De manière générale, le numéros de port se trouvent dans /etc/services.
modprobe ip_conntrack_ftpEnsuite, il faut taper les commandes suivantes :
# éventuellement : modprobe ip_nat_ftp
iptables -A INPUT -i ppp0 -p tcp --sport 21 -m state --state ESTABLISHED -j ACCEPTCela pour que la connexion puisse s'établir. Ensuite (et c'est la qu'on a besoin de ip_conntrack_ftp) :
iptables -A OUTPUT -o ppp0 -p tcp --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -i ppp0 -p tcp --sport 20 -m state --state ESTABLISHED,RELATED -j ACCEPTPour que serveur puisse établir la connexion pour les données (en mode actif). Et enfin :
iptables -A OUTPUT -o ppp0 -p tcp --dport 20 -m state --state ESTABLISHED -j ACCEPT
iptables -A INPUT -i ppp0 -p tcp --sport 1024:65535 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPTPour que le serveur puisse établir la connexion pour les données (en mode passif). Ici aussi ip_conntrack_ftp est nécessaire.
iptables -A OUTPUT -o ppp0 -p tcp --sport 1024:65535 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -F FORWARDet enfin, cacher les machines forward-ées par le firewall :
iptables -A FORWARD -j ACCEPT
iptables -A POSTROUTING -t nat -o ppp0 -j MASQUERADESur chaque machine devant être cachée par le firewall (ou devant partager la connexion avec la machine qui est connectée à internet), il faut ajouter une route par defaut :
route add default gw 192.168.1.1Si la machine connectée à internet a comme ip : 192.168.1.1. Il suffit avec une redhat/mandrake d'éditer :
/etc/sysconfig/networket d'ajouter dedans :
GATEWAY=192.168.1.1puis de redémarer le réseau :
/etc/rc.d/init.d/network restart
Nous allons mettre en place un firewall / proxy.
Pour cet exemple, le firewall aura la connexion à Internet (interface eth2) et disposera de 2 pattes sur des réseaux privés (eth0 et eth1) :
_____ eth1 .-> ---+------+------+---
_/ \_ ____ / [PC1] [PC2] [PC3]
( ) eth2 | |<--' réseau local 198.168.2.0
( INTERNET )<---->|Fire|
(_ _) ppp0 |wall|
\______/ |____|<--. DMZ serveurs 198.168.1.0
eth0\ [WEB] [NEWS] [FTP]
'-> ---+------+------+---
ASCIIArt (c) Jice
La classe d'adresse IP 192.168.2.0 correspond au réseau interne sur l'interface eth1.
La classe d'adresse IP 192.168.1.0 correspond a la DMZ sur l'interface eth0.
L'interface de la connexion Internet est ppp0 sur l'interface eth2.
Nous allons écrire un script qui permettra de charger automatiquement au démarrage de la machine ou sur demande les règles du firewall qui seront stockées dans le fichier /etc/firewall.sh.
Le script de démarrage sera nommé /etc/init.d/firewall. Bien sûr, on n'oubliera pas d'exécuter un chmod +x sur les 2 scripts que nous allons créer au long de ce chapitre.
Go !
Fichier de chargement /etc/init.d/firewall :
|
#!/bin/bash . /etc/init.d/functions RETVAL=0 # Fonction pour le lancement du firewall # Fonction pour arrêter le firewall (on flush) case $1 in exit |
C'est tout simple non ?
Et maintenant : /etc/flush_iptables.sh.
|
#!/bin/sh # # # # iptables -X # Message de fin |
Bon, on va enfin commencer les choses sérieuses : le script du firewall :)
Le script sera commenté au fur et à mesure, afin de décrire chaque étape.
|
#!/bin/sh # script /etc/firewall.sh # Firewall d'exemple a but pédagogique # Activation du forwarding echo 1 > /proc/sys/net/ipv4/ip_forward # Alors la, on va appliquer quelques astuces # Je veux pas de spoofing if [ -e /proc/sys/net/ipv4/conf/all/rp_filter ] # pas de icmp echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all # On va utiliser iptables. Si on l'a compilé en module modprobe ip_tables # on va charger quelques modules supplémentaires pour modprobe ip_nat_ftp # Pour faire bien, on va vider toutes les règles iptables -F # On va rajouter 2 nouvelles chaînes. # La on logue et on refuse le paquet, # ici, on logue et on accepte le paquet, # On veut faire un firewall efficace, iptables -P INPUT DROP # Pour éviter les problèmes, on va tout accepter sur iptables -A INPUT -i lo -j ACCEPT # Bon, la partie initialisation et préparation est iptables -A OUTPUT -o ppp0 -m state \ # Maintenant, on va faire en sorte que le iptables -t nat -A PREROUTING -i eth1 -p tcp \ # Bon, c'est pas trop compliqué ! Maintenant iptables -t nat -A PREROUTING -d 42.42.42.42 \ # C'est bien tout ça ! mais le problème c'est # On va quand même accepter les connexions ssh iptables -A INPUT -i eth1 -s 192.168.2.42 -m state \ # On veut que le LAN connecté à l'interface iptables -A FORWARD -i eth1 -o ppp0 -j ACCEPT # Maintenant on donne le droit au LAN de iptables -A FORWARD -i eth1 -o eth0 -p tcp \ # Maintenant il n'y a plus qu'à dire au firewall iptables -A FORWARD -i ppp0 -o eth0 -p tcp \ # Maintenant il ne reste plus grand chose à faire ! # Il faut permettre à l'ensemble du LAN de dialoguer iptables -t nat -A POSTROUTING \ # Il faut également que le serveur web de la DMZ iptables -t nat -A POSTROUTING \ # Toutes les règles qui n'ont pas passé les iptables -A FORWARD -j LOG_DROP # Pour faire zoli # c'est enfin fini |
Et voilà ! le firewall de compèt' est prêt et fonctionnel.
Ceci était bien évidemment un exemple, vous pouvez dès à présent préparer votre propre firewall personnalisé !
Vous pouvez l'adapter à vos besoins, votre connexion vers internet (par ADSL par exemple), etc.
© 12/11/2001 Arnaud de Bermingham
| | La documentation de cette page est laissée dans le domaine public. |
Le partage de connexion facile.
Tester votre firewall là.
Cliquez sur 'ShieldsUP!', puis sur l'un des boutons : 'Test My Shields !" et "Probe My Ports !". Ça vaut pas un bon nmap fait par un ami, mais ça permet de voir ou on en est.