Firewall à partir de Netfilter
Réflexion préalable à l’installation - méthodologie
Un firewall filtre les flux de données informatiques. S’il est bien configuré, il ne laisse passer que les flux autorisés. Ainsi, il peut jouer son rôle correctement, c’est à dire :
- limiter au maximum les accès aux applications et aux failles potentielles d’un système
- logguer les tentatives d’accès non autorisés.
Les fonctionnalités de proxy et/ou relai permettent de :
- de vérifier les protocoles utilisés (http sur le port 80)
- accélérer les connexions (utilisation de cache web et dns)
- logguer les accès web/mail
Cartographie des flux
Avant de mettre en place un firewall, il faut établir une cartographie des flux qui vont le traverser. Voici la méthodologie proposée :
- établir la liste des serveurs
- établir la liste des applications et ports ouverts par serveur
- établir la liste des applications autorisées à l’extérieur (Internet)
- définir des groupes d’accès si besoin est
A partir de ces éléments, il faut établir un tableau récapitulatif des flux qui sera un document de référence pour l’installation du FW et pour son évolution.
Remarque : Pour établir la cartographie des flux, il peut être utile de regarder les ports ouverts d’un serveur. C’est possible de l’extérieur avec un scanner de ports comme nmap ou directement sur les serveurs en utilisant la commande netstat pour les serveurs unix/linux et le logiciel Active Ports pour les serveurs Windows.
Choix de la typologie du firewall
Typologie matérielle
Un firewall peut être limité par deux facteurs :
- le nombre de connexions autorisées (mémoire vive)
- le débit qui le traverse (carte réseau)
L’importance de chaque facteur dépend de la typologie du firewall :
- si le firewall est une passerelle vers Internet, les débits sont généralement faibles et les connexions nombreuses.
- si le firewall protège des applications internes, les débits sont très importants (le firewall devient vite un goulot d’étranglement) et il ne faut pas hésiter à passer au Gigabit.
Typologie bridge ou non
Les firewalls Linux peuvent être configurés en mode « bridge » ce qui veut dire qu’ils seront « transparents » sur le réseau . Ceci a deux avantages principaux :
- on peut mettre rapidement metter en place le FW dans une architecture en production (il est possible de protéger des serveurs qui sont dans la même plage d'adresse que les clients)
- la continuité de flux est assurée si l’on retire le FW du réseau (avec toutefois la sécurité en moins !)
Un troisième avantage est que le firewall est difficile à détecter si on ne lui attribue pas d’adresse IP. Cependant, il est alors impossible de l’administrer à distance.
Linux propose un mode semi-bridge et un mode bridge. Le mode semi-bridge est plus facile à installer (Une simple ligne dans un script suffit). Le mode bridge est plus facile à administrer (car il ne faut plus s’occuper des tables de routage).
L’écriture du (des) script(s) du firewall dépendra de la configuration bridge choisie.
Les modules FW
Cette partie propose un exemple expliqué de script Firewall. Il faut connaître les commandes iptables. L’exemple proposé se base sur une configuration bridge.
Le Firewall Linux est un simple script qu’il faut écrire. Nous proposons une séparation en 4 ou 5 fichiers pour faciliter l’administration du firewall. Le tableau suivant résume la fonction de chaque fichier :
/etc/fw/rc.firewall | Fichier principal qui inclut tous les autres fichiers. |
/etc/fw/noyau | Définit les paramètres du noyau (bridge, taille de la table de connexions, …) |
/etc/fw/groupe | Contient les adresses ip des groupes d’accès définis pour la cartographie des flux (optionnel) |
/etc/fw/acces | Définit les variables serveurs et les règles d’accès du firewall |
/etc/fw/logs | Définit des règles pour logguer ou ne pas logguer des flux précis |
Remarque : il faut s’assurer que chaque fichier ait les droits en exécution.
/etc/fw/rc.firewall
Définition des variables
- APPEL noyau : Configuration du noyau linux
<licode>. /etc/fw/noyau</licode>
- Définitions de variables générales – APPEL groupe
<licode>
- Definition des interfaces
LOOPBACK="lo" IF_LAN="eth0" IF_DMZ="ethl" IF_NAT="eth2" </licode>
<licode>
- Adresses IP des interfaces
IP_LAN="192.168.10.xxx" IP_DMZ="192.168.10.xxx" IP_NAT="192.168.12.xxx"
- Niveau de log (1=alert;6=info) et prefixe pour logs
IPTABLES="/usr/sbin/iptables" #parfois /sbin/iptables LOG_LEVEL=6 PRE="FW :" FW="nom_du_fw" </licode>
Le préfixe PRE est utilisé par le script logfw pour parser les logs.
Le nom du firewall est utilisé lors de l’envoi de mails aux administrateurs.
- Définition des groupes
Les variables de groupes sont appelées dès le départ et peuvent être ensuite utilisées dans tout le script.
<licode>. /etc/fw/groupe</licode>
- Initialisation des chaînes principales
<licode>
- Initialisation de toutes les regles
$IPTABLES -F $IPTABLES –X $IPTABLES –t NAT –F $IPTABLES –t NAT -X $IPTABLES -F -t mangle $IPTABLES -t mangle –X
- Definition des politiques des chaines INPUT, OUTPUT, FORWARD
$IPTABLES -P INPUT DROP $IPTABLES -P OUTPUT DROP $IPTABLES -P FORWARD DROP </licode>
Les trois lignes précédentes permettent de ne rien laisser passer par défaut.
Règles de vérification générale (check)
- Vérification des drapeaux et filtre DOS (check_flags)
Pour vérifier la validité des drapeaux TCP (scans furtifs), on définit une chaîne check_flags : <licode>
- check_flags - validite des drapeaux TCP
$IPTABLES -N check_flags $IPTABLES -F check_flags
- XMAS
$IPTABLES -A check_flags -p tcp --tcp-flags ALL FIN,URG,PSH -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "$PRE XMAS " $IPTABLES -A check_flags -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
- SYN/RST
$IPTABLES -A check_flags -p tcp --tcp-flags SYN,RST SYN,RST -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "$PRE SYN,RST " $IPTABLES -A check_flags -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
- SYN/FIN
$IPTABLES -A check_flags -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "$PRE SYN, FIN " $IPTABLES -A check_flags -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
- Sans drapeau
$IPTABLES -A check_flags -p tcp --tcp-flags ALL NONE -m limit --limit 5/minute -j LOG --log-level $LOG_LEVEL --log-prefix "$PRE Sans Drapeau " $IPTABLES -A check_flags -p tcp --tcp-flags ALL NONE -j DROP
- NEW sans SYN TCP
$IPTABLES -A check_flags -p tcp --tcp-flags SYN NONE -m state --state NEW -j DROP
- Filtre DoS
$IPTABLES -A check_flags -p tcp --tcp-flags ALL RST -m limit --limit 20/second -j RETURN $IPTABLES -A check_flags -p tcp --tcp-flags ALL FIN -m limit --limit 20/second -j RETURN $IPTABLES -A check_flags -p tcp --tcp-flags ALL SYN -m limit --limit 20/second -j RETURN $IPTABLES -A check_flags -p tcp --tcp-flags ALL ACK -j RETURN $IPTABLES -A check_flags -p tcp --tcp-flags ALL ACK,FIN -j RETURN </licode>
Remarque : En fonction des architectures réseaux et du nombre de connexions, il se peut que le filtre DoS soit trop restrictif. Il faut alors augmenter les paramètres de limites.
- Contrôle des connexions
Netfilter est un firewall qui gère les états de connexions (statefull firewall). On autorise toutes les connexions établies, le filtre devant être implémenté à l’établissement des connexions.
<licode>
- check_state - controle des etats
$IPTABLES -N check_state $IPTABLES -F check_state
$IPTABLES -A check_state -m state --state INVALID -m limit --limit 5/s -j LOG --log-level $LOG_LEVEL --log-prefix "$PRE INVALID " $IPTABLES -A check_state -m state --state INVALID -j DROP $IPTABLES -A check_state -m state --state ESTABLISHED -j ACCEPT $IPTABLES -A check_state -m state --state RELATED -j ACCEPT </licode>
Remarque : Iptables gère quatre états avec l’option –m state --state :
- NEW : Etablissement de connexions
- INVALID : Mauvaise implémentation des protocoles ethernet
- ESTABLISHED : Connexion établie
- RELATED : Connexion liée à une autre (ex : ftp, erreurs icmp)
- La chaîne check
La sous chaîne « check » reprend les sous chaînes précédentes et est lancé en début des chaînes principales INPUT, OUTPUT et FORWARD.
<licode>
- Check reprend les chaînes de vérification
$IPTABLES –N check $IPTABLES –F check $IPTABLES –A check –j check_flags $IPTABLES –A check –j check_state
- Verifications prealables
$IPTABLES -A INPUT -j check $IPTABLES -A OUTPUT -j check $IPTABLES -A FORWARD -j check </licode>
Remarque : on peut aussi créer une règle check_iana qui vérifie la validité de certaines adresses ip. Le tableau suivant donne les adresses qui ne devraient pas être utilisées sur Internet. Il reprend le Draft de Bill Manning sur la gestion des blocks d’adresses enregistrés à l’IANA.
0.0.0.0/8 | Bloc d’adresses qui possède de nombreuses particularités |
127.0.0.0/8 | Adresses de loopback |
192.0.2.0/24 | Adresses TEST-NET |
10.0.0.0/8 | Adresses privées |
RFC 1918 | 172.16.0.0/12 |
Adresses privées | RFC 1918 |
192.168.0.0/16 | Adresses privées RFC 1918 |
169.254.0.0/16 | Adresses utilisées quand le serveur DHCP n’est pas trouvé |
192.88.99.0/24 | 6to4 Relay anycast prefix RFC 3068 |
224.0.0.0 à 239.255.255.255 | Classe D RFC 1166 |
240.0.0.0 à 255.255.255.255 | Classe E RFC 1166 |
APPEL logs : affinage des règles
Le fichier logs a 2 objectifs :
- limiter la pollution des logs par du trafic récurrent résiduel (broadcast, NT, ….)
- donner la possibilité d’analyser tout trafic avec des cibles LOG
<licode>. /etc/fw/logs</licode>
Remarque : Le script /etc/fw/logs est lancé après les règles checks. Les paquets qui ne respectent pas les règles de tcp/ip seront donc tous DROPés et LOGgés.
APPEL acces : Définition des accès
<licode>. /etc/fw/acces</licode>
Définition des translations d’adresses
Des explications sont données au paragraphes 2.x.
<licode>
- Règles nat
echo "nat" $IPTABLES -t nat -A POSTROUTING -o $IF_EXT -s $LAN_NET -j SNAT --to $IP_EXT $IPTABLES -t nat -A POSTROUTING -o $IF_EXT -s $LYON_NET -j SNAT --to $IP_EXT $IPTABLES -t nat -A POSTROUTING -o $IF_EXT -s $TLSE_NET -j SNAT --to $IP_EXT
- $IPTABLES -t nat -A PREROUTING -i $IF_EXT -s 192.168.110.3 -d $IP_EXT -p tcp --dport 25 -j DNAT --to 192.168.111.12
- $IPTABLES -t nat -A PREROUTING -i $IF_LAN -d $IP_LAN -p tcp --dport 25 -j DNAT --to 192.168.110.3
</licode>
Définition des routes
Des explications sont données dans le paragraphe 2.2.
<licode>
- Précision des routes
echo "routes" ip route add 192.168.112.0/24 via 192.168.111.1 dev $IF_LAN </licode>
Loopback, log du reste et mail au redémarrage
- Prise en compte de l’interface loopback
<licode> $IPTABLES –A INPUT –i $LOOPBACK –j ACCEPT $IPTABLES –A OUTPUT –o $LOOPBACK –j ACCEPT </licode>
- Log des paquets qui n’ont fait l’objet d’aucune règle et qui ne passeront pas
<licode>
- Logguer tout ce qui est rejeté
$IPTABLES -A INPUT -j LOG --log-level $LOG_LEVEL --log-prefix "$PRE DROPPED " $IPTABLES -A OUTPUT -j LOG --log-level $LOG_LEVEL --log-prefix "$PRE DROPPED " $IPTABLES -A FORWARD -j LOG --log-level $LOG_LEVEL --log-prefix "$PRE DROPPED " </licode>
- Mail de redémarrage (FIXME)
Le routage (/etc/fw/rc.firewall)
Exemples d’utilisation d’iproute2
#ip route add 192.168.111.0/24 dev eth0 #ip route del 192.168.111.0/24 #ip route add 192.168.112.0/24 via 192.168.111.1 dev eth0 #ip route add default via 192.168.100.111 dev eth1 #ip route show
Configuration Bridge
Le fonctionnalité bridge permet :
- d’insérer un firewall dans une architecture réseau existante
- de laisser passer tous les paquets si on retire le FW, ce qui assure une continuité de service.
Semi-bridge
Cette configuration permet de séparer un réseau local en assurant le transfert des paquets arp d’une interface à une autre. L’inconvénient du semi-bridge est qu’il faut configurer les routes pour toutes les machines de part et d’autre du serveur.
Bridge
La commande brctl (cf document d’installation) permet de configurer le noyau pour résoudre le problème de routage du semi-bridge. Ceci permet de créer une interface br0 qui regroupe les interface classiques comme eth0 et eth1. A moins de patcher le noyau, on ne peut plus savoir ce qui arrive par une carte réseau ou par une autre.
La translation d’adresses (NAT) (/etc/fw/rc.firewall)
La translation d’adresses a plusieurs utilisations pratiques:
- la plus utilisée (SNAT) est d’utiliser une même adresse de sortie vers Internet pour un certains nombre d’ordinateurs. Cela résout les problèmes de pénurie d’adresse ip.
- Le DNAT permet de rediriger un flux vers un serveur précis
L’exemple suivant attribue l’adresse $IP_PUB à chaque personne du groupe GR_1 quand elle sort du réseau :
for IP in GR_1 ; do $IPTABLES –t nat –A POSTROUTING –o $IF_EXT –s $NET$IP –j SNAT --to $IP_PUB done
Remarque 1 : On créer un fichier des accès séparé (/etc/fw/nat) si le nombre de translations d’adresses le justifie.
Remarque 2 : L’utilisation de l’option –o n’est pas possible avec le mode bridge.
Les paramètres noyau (/etc/fw/noyau)
Paramètres de sécurité
rp_filter est un paramètre qui permet de refuser les paquets qui viennent arrivent sur une interface réseau, alors qu’il devraient arriver par une autre selon leur adresse source et la table de routage.
<licode> for i in /proc/sys/net/ipv4/conf/*/rp_filter; do
echo "1" > $i
done </licode>
Les cookies syn sont un mécanisme pour réduire la portée des attaques DOS de type syn-flood. Ce mécanisme comporte une faille jusqu’au noyau 2.4.14, ensuite il faut l’activer :
<licode> if [ -e /proc/sys/net/ipv4/tcp_syncookies ]; then
echo "0" > /proc/sys/net/ipv4/tcp_syncookies (noyau <= 2.4.14) echo "1" > /proc/sys/net/ipv4/tcp_syncookies (noyau > 2.4.14)
else
echo "syn_cookies n'est pas compile!"
fi </licode>
Les icmp redirects sont utilisés par les routeurs pour changer certaines routes. C’est inutile pour les routes statiques que nous avons définies :
<licode> for i in /proc/sys/net/ipv4/conf/*/accept_redirects; do
echo "0" > $i
done </licode>
La réponse à un ping de broadcast doit être interdite : <licode>echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts</licode>
Les timestamps peuvent être utilisés à mauvais escient : <licode>echo 0 > /proc/sys/net/ipv4/tcp_timestamps</licode>
Pour servir de passerelle : <licode>echo 1 > /proc/sys/net/ipv4/ip_forward</licode>
Paramètres de performance
- Il est possible de paramétrer la taille maximale de la table de connexions. La valeur par défaut de ce paramètre dépend de la RAM du serveur (128MB: 8192, 256MB: 16384). Il est intéressant de noter qu’une entrée dans la table prend 350o de mémoire vive.
Si le noyau n’a pas été recompilé, il faut lancer le module de gestion des connexions avant de changer ce paramètre : <licode> modprobe ip_conntrack echo "nbre_de connexions_max" > /proc/sys/net/ipv4/ip_conntrack_max </licode>
Configuration semi-bridge
<licode> echo "1" > /proc/sys/net/ipv4/conf/eth_X/proxy_arp echo "1" > /proc/sys/net/ipv4/conf/eth_Y/proxy_arp </licode>
La définition de groupes d’accès (/etc/fw/groupe)
- Ce fichier contient la liste d’adresses ip correspondant aux groupes définis préalablement pendant la cartographie des flux. Pour améliorer la lisibilité et raccourcir les listes d’adresses ip , on peut définir une varaiable reprenant le début de chaque adresse ip. Seule la seconde partie des adresses sera à mettre dans les listes.
<licode file=/etc/fw/groupe> NET="192.168" GR_1="10.1 10.3 10.5" GR_2="11.1 11.3 11.4" </licode>
Il est aussi possible de définir des groupes contenant d’autres groupes : <licode>GR_12="$GR_1 $GR2"</licode>
Remarque : Ce fichier ne sert que si les droits d’accès différent entre les utilisateurs.
Flux résiduels et analyse (/etc/fw/logs)
Les logs de firewall peuvent être affinés à partir du fichier /etc/fw/logs. Ce fichier permet :
- d’écrire des règles temporaires
- ne pas logguer les trafics « pollueurs »
- logguer certains trafics particuliers.
Par défaut les enregistrements vont dans le fichier "/var/log/messages" Avec rsylogd, il est facile de faire arriver les fichiers dans le fichier de son choix.
Règles de debuggage
<licode file=/etc/fw/logs>
- Règles de debuggage
- $IPTABLES -A INPUT -s 192.168.111.0/24 -j ACCEPT
</licode>
Flux résiduels
- En pratique, il existe toujours du trafic résiduel lien à un mauvais paramétrage de machines. Ce trafic génère des logs qui cachent les alertes importantes. Pour stopper ces logs il suffit de « DROPper » les paquets pollueurs.
Par exemple, nous pouvons éliminer les demandes DHCP et les broadcasts NT sur le port 138 : <licode file=/etc/fw/logs>
- no log input
$IPTABLES -A INPUT -i $IF_LAN -p udp -d 255.255.255.255 --sport 68 --dport 67 -j DROP $IPTABLES -A INPUT -i $IF_LAN -p udp -d 255.255.255.255 --sport 138 --dport 138 -j DROP
- no log output
- no log forward
$IPTABLES -A FORWARD -i $IF_LAN -p udp -d 255.255.255.255 --sport 68 --dport 67 -j DROP $IPTABLES -A FORWARD -i $IF_LAN -p udp -d 255.255.255.255 --sport 138 --dport 138 -j DROP </licode>
Analyse particulière
Il peut être intéressant de logguer des flux particuliers, suite par exemple, à la demande d’un administrateur distant ayant reçu des alertes. L’exemple suivant loggue les connexions d’une adresse ip considérée comme dangereuse.
$IPTABLES –A FORWARD –s ip_dangereuse –m state --state NEW –j LOG –-log-level $LOG_LEVEL --log-prefix "$PRE connexion ip-dangereuse "
Le filtre: les règles d’accès (/etc/fw/accès)
Ce fichier commence par la déclaration des variables serveur :
<licode> PROXY_WEB="192.168.10.5" DNS="192.168.100.1 192.168.100.2" </licode>
Il faut définir les accès aux firewall (chaînes INPUT et OUTPUT) :
On peut par exemple autoriser les accès ssh pour le groupe 1 sur l’interface interne et les requêtes DNS du firewall :
<licode> for IP in $GR_1; do
$IPTABLES –A INPUT –s $NET$IP –d $IP_LAN –p tcp --sport 1024: --dport 22 –m state --state NEW –j ACCEPT
done for IP in $DNS; do
$IPTABLES –A OUTPUT –s $IP_EXT –d $IP –p udp --dport 53 –m state --state NEW –j ACCEPT
done </licode>
Il faut ensuite traduire la carte des flux qui traversent le firewall (chaîne FORWARD):
L’exemple suivant autorise l’accès ftp partout pour les personnes du groupe 2 :
<licode> for IP in $GR_2; do
$IPTABLES –A FORWARD –s $NET$IP –p tcp --sport 1024: --dport 21 –m state --state NEW –j ACCEPT
done </licode>
bloquer les bruteforces avec l'extension recent
http://www.netfilter.org/documentation/HOWTO/fr/netfilter-extensions-HOWTO-3.html#ss3.16 <licode file=/etc/fw/acces> $IPTABLES -A INPUT -i $IF_EXT -p tcp --dport 21 -m recent --update --seconds 60 --hitcount 5 --name FTP -j LOG --log-prefix "FTP brute force " $IPTABLES -A INPUT -i $IF_EXT -p tcp --dport 21 -m recent --update --seconds 60 --hitcount 5 --name FTP -j DROP $IPTABLES -A INPUT -i $IF_EXT -p tcp --dport 21 -m recent --set --name FTP $IPTABLES -A INPUT -i $IF_EXT -p tcp --dport 21 -m state --state NEW -j ACCEPT </licode>
Si une adresse IP se connecte sur le serveur FTP, elle est mise dans la liste "FTP".
Si l'adresse tente de se connecter plus de 5 fois en 60s, la connexion est logguée puis bloquée.
Configurer un firewall en mode bridge ou semi-bridge
Pour les firewall configurés en bridge, le fichier /etc/route.conf n’est pas suffisant pour la configuration des routes. Il faut alors utiliser iproute2 et commenter toutes les lignes de /etc/route.conf par des #.
#ip route del ip/mask permet de désactiver les routes existantes une à une #ip route add default via ip_gateway dev ethx permet de définir la passerelle par défaut #ip route add ip/mask dev ethx permet de définir les routes classiques. #ip route –n affiche la table de routage.
Pour que la route soit bien définie au démarrage, il faut que le script /etc/conf.d/net fasse appel au au script de route.
Pour que le firewall fasse passer les paquets d’une interface à une autre, en d’autres termes qu’il "route" les paquets, il faut activer le « forwarding ip ». Le plus simple est d’écrire dans /etc/fw/noyau une ligne du type : <licode file=/etc/fw/noyau> echo "1" > /proc/sys/net/ipv4/ip_forward </licode>
Configuration semi-bridge
Pour la configuration semi-bridge, il faut indiquer la route pour chaque serveur dans le fichier /etc/fw/route.
Configuration bridge
Un document d’installation se trouve à la page http://linux-net.osdl.org/index.php/Bridge
Il faut installer l’outil de configuration brctl.
Package Gentoo: bridge-utils
Créer l’interface «pont » :
#brctl addbr br0
Ajouter les interfaces désirées au pont
#brctl addif br0 eth1 #brctl addif br0 eth2
S’assurer que les cartes eth1 et eth2 n’ont pas d’adresses assignées. Pour cela, il suffit qu’elles ne soient pas configurées démarrage ou de taper la commande.
#ifconfig ethx 0.
Activer le pont
#ip link set eth1 up #ip link set eth2 up #ip link set br0 up
Pour attribuer une adresse au pont, ce qui peut être nécessaire si on veut l’administrer à distance, cela se fait comme pour toute interface réseau habituelle :
#ip addr add x.x.x.x/24 brd + dev br0 où x.x.x.x est l’adresse de l’interface #ip route add default via y.y.y.y où y.y.y.y est l’adresse de la passerelle.
Remarque : Pour que la configuration bridge soit lancée à chaque démarrage, il suffit d’écrire ces lignes de script dans le fichier /etc/fw/route.
Annexes
Filtrage des flux ICMP
http://www.networksorcery.com/enp/protocol/icmp.htm
http://en.wikipedia.org/wiki/Internet_Control_Message_Protocol
http://www.securityfocus.com/print/infocus/1183
http://www.spirit.com/Network/net0700.html
http://www.sys-security.com/archive/papers/ICMP_Scanning_v3.0.pdf
Copyright
© 2006 Christophe de Livois
Vous avez l'autorisation de copier, distribuer et/ou modifier ce document suivant les termes de la GNU Free Documentation License, Version 1.2 ou n'importe quelle version ultérieure publiée par la Free Software Foundation; sans section invariante, sans page de garde, sans entête et sans page finale. Pour plus d'informations consulter le site de l'APRIL. |