Firewall avec Netfilter
I) Introduction :
Dans cette article, nous verrons la mise en place d’un firewall sous Linux (kernel 2.4) au travers de trois exemples. Le premier correspondra à une machine isolée ayant accès à Internet, le deuxième sera celui d’une machine faisant office de routeur/firewall pour un petit réseau domestique, enfin nous verrons la configuration de netfilter dans un réseau comprenant une zone démilitarisée (DMZ) en ajoutant une troisième patte à notre routeur.
Petit rappel, un firewall est un dispositif relié à au moins deux réseaux (exemple : un réseau local et internet) et permettant de filter les paquets le traversant en autorisant certains ou en refusant d’autres suivant certaines règles. Le firewall sous Linux s’appelle Netfilter. Il est composé de deux parties. La première est à compiler directement dans le kernel, j’ai ainsi pour préférence de ne rien compiler en modules à ce niveau car si un module venait à ne pas pouvoir être chargé, le firewall serait inopérant. La deuxième est constituée par la commande iptables. Cette commande permet d’indiquer les directives de filtrage. Pour terminer, une question de bon sens, il faut fermer tous les accès à un firewall puis ensuite authoriser l’accès aux services réseau désirés et non pas interdire uniquement les paquets jugés dangereux. Dans le premier cas, un oubli vous coutera le disfonctionnement d’un service tandis que dans l’autre cas, vous trainerez à vos pieds un risque potentiel pour votre sécurité si vous omettez une règle de filtrage particulière
II) Les commandes d’iptables :
Iptables possède trois tables :
- filter, la table par défaut qui possède les règles INPUT, OUTPUT, FORWARD.
- nat, la table de translation d’adresse réseau avec les règles PREROUTING (à l’arrivée du firewall) et POSTROUTING (à la sortie du firewall).
- mangle, que je connais trop peu pour en parler mais qui est rarement utilisée sert à la modification à la volée des en-tête des paquets.
Dans le firewall, le cheminement des paquets se fait comme suit :
INPUT : chaîne par laquelle passent tous les paquets arrivant par une interfaçe.
OUTPUT : chaîne par laquelle passent tous les paquets sortant sur une interfaçe.
FORWARD : passent ici les paquets qui doivent aller d’une interfaçe à une autre.
Comportements associés a ces chaines :
ACCEPT : Le paquet est autorisé.
REJECT : Le paquet est rejecté et on envoi un message d’erreur à l’emetteur.
DROP : On ignore le paquet.
LOG : Le paquet est loggé.
Options pour manipuler les chaînes :
N : Créé une nouvelle chaîne.
X : Supprime une chaîne vide.
P : Politique par défaut.
L : Liste les règles.
A : Ajoute une règle à une chaîne.
I : Insère une règle à une position donnée dans une chaîne.
R : Remplace une chaîne donnée par une autre.
D : Effaçe une règle d’une chaîne.
III) Exemple 1 : Machine isolée
#!/bin/bash # Créer une chaine qui bloque les nouvelles connections à part celles qui viennent de l’intérieur. iptables -A block -m state –state ESTABLISHED,RELATED -j ACCEPT iptables -A block -m state –state NEW -i ! ppp0 -j ACCEPT iptables -A block -j DROP
# Sauter sur cette chaine à partir des chaines INPUT et FORWARD. iptables -A INPUT -j block iptables -A FORWARD -j block
IV) Exemple 2 : Routeur/Firewall
Notez que certains ports supplémentaires sont ouverts car le routeur fait aussi office de serveur web, ftp et mail.
#!/bin/bash
#efface les regles existantes des trois tables
iptables -F
iptables -t nat -F
iptables -t mangle -F
#Effacement des chaines définies
iptables -X
#Politique par defaut (tout rejeter)
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
iptables -N lan-web
iptables -N lan-fw
iptables -N web-lan
iptables -N web-fw
iptables -N icmp-acc
iptables -N fw-lan
# la loopback du firewall peut émetre dans tous les sens :
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# les connections invalides sont refusées :
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A FORWARD -m state --state INVALID -j DROP
# les connections etablies ou assimilables sont acceptées en entrée comme en forward :
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -o eth0 -j ACCEPT
# Protection TCP Syn Flood :
iptables -A FORWARD -p tcp --syn -m limit --limit 1/second -j ACCEPT
iptables -A INPUT -p tcp --syn -m limit --limit 1/second -j ACCEPT
# Protection UDP Flood :
iptables -A FORWARD -p udp -m limit --limit 1/second -j ACCEPT
iptables -A INPUT -p udp -m limit --limit 1/second -j ACCEPT
# on trie les paquets suivant les interfaces :
iptables -A INPUT -i ppp0 -j web-fw
iptables -A INPUT -i eth0 -j lan-fw
iptables -A INPUT -j DROP
# on trie les paquets en fonction de leur cheminement dans nos chaines
iptables -A FORWARD -i eth0 -o ppp0 -j lan-web
iptables -A FORWARD -i ppp0 -o eth0 -j web-lan
# le firewall peut emettre comme il veut
iptables -A OUTPUT -j ACCEPT
# On autorise les paquets ICMP
iptables -A icmp-acc -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A icmp-acc -p icmp --icmp-type source-quench -j ACCEPT
iptables -A icmp-acc -p icmp --icmp-type time-exceeded -j ACCEPT
iptables -A icmp-acc -p icmp --icmp-type echo-request -m limit --limit 1/second -j ACCEPT
iptables -A icmp-acc -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A icmp-acc -j DROP
# Du web vers le lan :
iptables -A web-lan -j REJECT
# Du reseau local vers le web : on donne droit à tout
iptables -A lan-web -p icmp -j icmp-acc
iptables -A lan-web -j ACCEPT
##
# Règles pour les connections sur le firewall provenant du LAN:
##
iptables -A lan-fw -p tcp --dport ssh -j ACCEPT
iptables -A lan-fw -p tcp --dport domain -j ACCEPT
iptables -A lan-fw -p udp --dport domain -j ACCEPT
iptables -A lan-fw -p tcp --dport smtp -j ACCEPT
iptables -A lan-fw -p tcp --dport pop3 -j ACCEPT
iptables -A lan-fw -p udp --dport pop3 -j ACCEPT
iptables -A lan-fw -p tcp --dport 143 -j ACCEPT
iptables -A lan-fw -p udp --dport 143 -j ACCEPT
iptables -A lan-fw -p tcp --dport www -j ACCEPT
iptables -A lan-fw -p tcp --dport ftp -j ACCEPT
iptables -A lan-fw -p tcp --dport ftp-data -j ACCEPT
iptables -A lan-fw -p icmp -j icmp-acc
iptables -A lan-fw -j DROP
##
# Règles pour les connections sur le firewall de l'extérieur :
##
iptables -A web-fw -p tcp --dport ssh -j ACCEPT
iptables -A web-fw -p tcp --dport domain -j ACCEPT
iptables -A web-fw -p udp --dport domain -j ACCEPT
iptables -A web-fw -p tcp --dport smtp -j ACCEPT
iptables -A web-fw -p tcp --dport pop3 -j ACCEPT
iptables -A web-fw -p udp --dport pop3 -j ACCEPT
iptables -A web-fw -p tcp --dport 143 -j ACCEPT
iptables -A web-fw -p udp --dport 143 -j ACCEPT
iptables -A web-fw -p tcp --dport www -j ACCEPT
iptables -A web-fw -p tcp --dport ftp -j ACCEPT
iptables -A web-fw -p tcp --dport ftp-data -j ACCEPT
iptables -A web-fw -p icmp -j icmp-acc
iptables -A web-fw -j DROP
# Activation du NAT IPV4 :
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 0.0.0.0/0 -o ppp0 -j MASQUERADE
# On active le routage :
echo "1" > /proc/sys/net/ipv4/ip_forward
V) Exemple 3 : Cas d’une DMZ
Dans cet exemple, la machine sur laquelle se trouve le firewall jouera le rôle de passerelle vers internet, fera de la translation d’adresses, sera serveur pop3 et smtp et enfin serveur DNS. Dans la DMZ se trouve un serveur HTTP et FTP. De plus on veut permettre au réseau local de se connecter au firewall et au serveur web via le protocole ssh.
Le firewall possède les interfaçes réseau suivantes :
ppp0 : reliée temporairement à internet.
eth0 : reliée au réseau local (192.168.0.0/24).
eth1 : reliée à la DMZ (192.168.1.0/24).
#! /bin/sh
# /etc/firewall.sh
#
# Firewall
#
# ppp0 : interface reliee a internet
# eth0 : lan (ip : 192.168.0.1)
# eth1 : dmz (ip : 192.168.1.1
# ip du serveur http de la dmz : 192.168.1.2
#efface les regles existantes des trois tables
iptables -F
iptables -t nat -F
iptables -t mangle -F
#Effacement des chaines définies
iptables -X
#Politique par defaut (tout rejeter)
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
# Chaines définies pour trier les paquets :
# dmz designe la dmz
# lan mon reseau local
# web le web
# fw le firewall
iptables -N lan-web
iptables -N lan-dmz
iptables -N lan-fw
iptables -N dmz-lan
iptables -N dmz-web
iptables -N dmz-fw
iptables -N web-dmz
iptables -N web-fw
iptables -N web-lan
iptables -N icmp-acc
# la loopback du firewall peut émetre dans tous les sens :
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# les connections invalides sont refusées :
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A FORWARD -m state --state INVALID -j DROP
# les connections etablies ou assimilables sont acceptées en entrees comme en forward :
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
# on trie les paquets suivant les interfaces :
iptables -A INPUT -i ppp0 -j web-fw
iptables -A INPUT -i eth0 -j lan-fw
iptables -A INPUT -i eth1 -j dmz-fw
iptables -A INPUT -j DROP
# on trie les paquets en fonction de leur cheminement dans nos chaines
iptables -A FORWARD -i eth0 -o ppp0 -j lan-web
iptables -A FORWARD -i eth0 -o eth1 -j lan-dmz
iptables -A FORWARD -i eth1 -o ppp0 -j dmz-web
iptables -A FORWARD -i eth1 -o eth0 -j dmz-lan
iptables -A FORWARD -i ppp0 -o eth1 -j web-dmz
iptables -A FORWARD -i ppp0 -o eth0 -j web-lan
# Le firewall peut emettre comme il veut :
iptables -A OUTPUT -j ACCEPT
# On authorise les paquets ICMP
iptables -A icmp-acc -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A icmp-acc -p icmp --icmp-type source-quench -j ACCEPT
iptables -A icmp-acc -p icmp --icmp-type time-exceeded -j ACCEPT
iptables -A icmp-acc -p icmp --icmp-type echo-request -j ACCEPT
iptables -A icmp-acc -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A icmp-acc -j DROP
# Reseau interne vers la dmz
iptables -A lan-dmz -p tcp --dport smtp -j ACCEPT
iptables -A lan-dmz -p tcp --dport pop3 -j ACCEPT
iptables -A lan-dmz -p udp --dport domain -j ACCEPT
iptables -A lan-dmz -p tcp --dport domain -j ACCEPT
iptables -A lan-dmz -p tcp --dport www -j ACCEPT
iptables -A lan-dmz -p tcp --dport https -j ACCEPT
iptables -A lan-dmz -p tcp --dport ssh -j ACCEPT
iptables -A lan-dmz -p tcp --dport auth -j ACCEPT
iptables -A lan-dmz -p tcp --dport ftp -j ACCEPT
iptables -A lan-dmz -p icmp -j icmp-acc
iptables -A lan-dmz -j DROP
# Du web vers la dmz :
iptables -A web-dmz -p tcp --dport www -j ACCEPT
iptables -A web-dmz -p tcp --dport https -j ACCEPT
iptables -A web-dmz -p tcp --dport ftp -j ACCEPT
iptables -A web-dmz -p icmp -j icmp-acc
iptables -A web-dmz -j DROP
# Du reseau local vers le web : on donne droit à tout
iptables -A lan-web -j ACCEPT
iptables -A lan-web -p icmp -j icmp-acc
# De la dmz vers le reseau local : tous les droits :
iptables -A dmz-lan -j ACCEPT
iptables -A dmz-lan -p icmp -j icmp-acc
# De la dmz vers le web, tous les droits également :
iptables -A dmz-web -j ACCEPT
iptables -A dmz-web -p icmp -j icmp-acc
# Du web vers le lan :
iptables -A web-lan -j REJECT
# Règles pour les connections sur le firewall :
iptables -A web-fw -p icmp -j icmp-acc
iptables -A web-fw -j ACCEPT
iptables -A web-fw -p icmp -j icmp-acc
iptables -A dmz-fw -j ACCEPT
iptables -A lan-fw -p tcp --dport ssh -j ACCEPT
iptables -A lan-fw -p tcp --dport domain -j ACCEPT
iptables -A lan-fw -p udp --dport domain -j ACCEPT
iptables -A lan-fw -p tcp --dport smtp -j ACCEPT
iptables -A lan-fw -p tcp --dport pop3 -j ACCEPT
iptables -A lan-fw -p ICMP --icmp-type ping -j ACCEPT
iptables -A lan-fw -p ICMP --icmp-type pong -j ACCEPT
iptables -A lan-fw -j icmp-acc
iptables -A lan-fw -j DROP
# On active le routage :
echo "1" > /proc/sys/net/ipv4/ip_forward
# Enfin on termine par les règles de nat entrant comme sortant :
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
iptables -t nat -A PREROUTING -j DNAT -i ppp0 -p TCP --dport ftp --to-destination 192.168.1.2
iptables -t nat -A PREROUTING -j DNAT -i ppp0 -p TCP --dport www --to-destination 192.168.1.2
iptables -t nat -A PREROUTING -j DNAT -i ppp0 -p TCP --dport https --to-destination 192.168.1.2
VI) Gestion de la QOS avec iptables :
La gestion de la QOS sous iptables se fait en manipulant le champs TOS de l’en tête TCP. Sachez que bien que ça améliore la gestion de la bande passante, ce n’est pas aussi efficace qu’une vrai gestion de la QOS telle que celle offerte par le kernel. Les options que l’on donne au champs TOS sont les suivantes :
Minimize-Delay : Améliore la réactivité des connexions en réduisant le délai (ssh, telnet, ftp contrôle, tftp, flux DNS)
Maximize-Throughput : Améliore le débit au prix d’une possible détérioration de l’interactivité de la session. Les temps de latence ne sont pas importants (ftp-data,www, transfert de zone DNS)
Maximum-Reliability : Certitude que les données arrivent sans perte - Améliore la fiabilité (snmp, smtp)
Minimize monetary cost : minimise le délai, meilleure rentabilité (nntp, icmp)
Exemple :
iptables -A PREROUTING -t mangle -p tcp --sport ssh -j TOS --set-tos Minimize-Delay
iptables -A PREROUTING -t mangle -p tcp --sport ftp -j TOS --set-tos Minimize-Delay
iptables -A PREROUTING -t mangle -p tcp --sport www -j TOS --set-tos Minimize-Delay
iptables -A PREROUTING -t mangle -p tcp --sport ircd -j TOS --set-tos Minimize-Delay
# On donne un maximum de débit aux transferts ftp, peu importe la latence
iptables -A PREROUTING -t mangle -p tcp --sport ftp-data -j TOS --set-tos Maximize-Throughput
iptables -A PREROUTING -t mangle -p tcp --sport 53 -j TOS --set-tos Maximize-Throughput
VII) Arrêt du Firewall :
Script pour réinitialiser le firewall :
#!/bin/bash
# Script pour désactiver le firewall :
# On efface les règles définies :
iptables -t filter -F
iptables -t nat -F
iptables -t mangle -F
# Efface les chaines définies :
iptables -X
# Politique par défaut :
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT