Pour plus de souplesse, nous allons écrire nos règles sous forme de script bash. Petite mesure de prudence si vous êtes loggué sur votre machine à distance (ssh), soyez bien sûr de ne pas vous bloquer l’accès.
Créons le script.
nano /etc/init.d/firewall
Et on y écrit.
#!/bin/sh
On efface les règles précédentes pour partir sur de bonnes bases.
iptables -t filter -F iptables -t filter -X
On bloque par défaut tout le trafic (si vous êtes en ssh, bien entendu, n’exécutez pas encore le script !).
iptables -t filter -P INPUT DROP iptables -t filter -P FORWARD DROP iptables -t filter -P OUTPUT DROP
On ne ferme pas les connexions déjà établies.
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
Nous indiquons avec les paramètres -m et --state de ne pas fermer les connexions qui sont déjà établies.
On autorise le loopback (on ne va pas se bloquer nous-mêmes !).
iptables -t filter -A INPUT -i lo -j ACCEPT iptables -t filter -A OUTPUT -o lo -j ACCEPT
Note : lo signifie localhost (le serveur lui-même).
Tout est bloqué, il ne nous reste plus qu’à ouvrir les ports utilisés.
Ouvrir les ports utilisés
À partir de maintenant, observons plus en détail les paramètres de iptables.
-t : vaudra par défaut « filter » -A : servira à indiquer le sens du trafic : INPUT (entrant) ou OUTPUT (sortant) -p : indique le protocole (TCP ou UDP en principe) --dport et --sport : respectivement port destination et port source (comme nous sommes le serveur, nous utiliserons principalement dport) -j : comment traiter le paquet (nous nous servirons d'ACCEPT et de DROP pour respectivement accepter et refuser le paquet).
Plus nous serons précis, plus nous serons sécurisés. Renseigner ces quelques options est donc le minimum.
Ainsi, une règle simple aura la forme suivante.
iptables -t filter -A INPUT/OUTPUT -p protocole --dport port_a_ouvrir -j ACCEPT
Notez enfin que si vous voulez un échange, il faut toujours ouvrir le port dans les deux sens (INPUT et OUTPUT)... logique.
Exemple si l’on a un serveur web (port 80).
iptables -t filter -A OUTPUT -p tcp --dport 80 -j ACCEPT iptables -t filter -A INPUT -p tcp --dport 80 -j ACCEPT
Il ne vous reste qu’à spécifier toutes les règles nécessaires. Voici un petit tableau pour vous aider (il s’agit de données par défaut).
service
port d’écoute
protocole
ssh
22
tcp
web/HTTP
80
tcp
FTP
20 et 21
tcp
mail/SMTP
25
tcp
mail/POP3
110
tcp
mail/IMAP
143
tcp
DNS
53
tcp et udp
Cas particulier du ping
Le ping est basé sur un protocole particulier (ICMP) qui n’a pas de port prédéfini. Mais il faut absolument autoriser le ping car c’est la méthode la plus couramment utilisée pour savoir si votre serveur est en vie. Voici donc les règles.
iptables -t filter -A INPUT -p icmp -j ACCEPT iptables -t filter -A OUTPUT -p icmp -j ACCEPT
Outre que c’est l’outil de base de tout système de sécurité, Iptables permet des manipulations plus poussées que filtrer des ports. Je vais vous montrer quelques exemples.
Ce genre d’attaque vise à surcharger la machine de requête. Il est possible de s’en prémunir pas mal directement au niveau du firewall.
iptables -A FORWARD -p tcp --syn -m limit --limit 1/second -j ACCEPT
Le flags TCP --syn engendre des demandes de connexions, et le but de cette règle est donc de les limiter à une par seconde (champs limit).
Il est cependant déconseillé de monter au-delà de la seconde (sous peine de gêner le contrôle de flux et la récupération d’erreur de TCP).
On peut faire de même avec les protocoles UDP et ICMP.
iptables -A FORWARD -p udp -m limit --limit 1/second -j ACCEPT iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/second -j ACCEPT
Notez cependant que ce type d’attaque permet de faire tomber le serveur, mais pas d’en prendre l’accès.
On peut aussi limiter un tant soit peu le scan de ports (qui consiste à tester tous vos ports afin de détecter ceux qui sont ouverts). Pour cela, une règle de ce genre irait.
iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT
C’est un peu le même principe que ci-dessus. Sachant qu’une connexion TCP en bon et due forme requiert trois paquets avec trois flags différents, on voit tout de suite la finesse de cette règle qui peut travailler paquet par paquet. Pour plus d’infos sur les flags TCP, cf Wikipédia.
Notez que cette règle basique n’est pas très efficace, c’est une protection de base.
Si vous repérez dans les logs ou autre une adresse IP suspecte, vous pouvez la bannir aisément au niveau du firewall via la commande :
iptables -A INPUT -s adresse_ip -j DROP
Notez cependant qu’il n’est pas conseillé de bannir les IP à tour de bras.
Ci-dessous, je vous montre un exemple de script basique autorisant le minimum pour un serveur HTTP, FTP, SSH, MAIL et résolution de DNS. Je vous encourage à lire des docs et des tutos plus complets si vous voulez aller plus loin dans le paramétrage de votre firewall.
Créer un nouveau fichier nommé /etc/init.d/firewall .
nano /etc/init.d/firewall
Et ajouter le script ci-dessous dedans.
#!/bin/sh ### BEGIN INIT INFO # Provides: firewall # Required-Start: $network $syslog # Required-Stop: $network $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: firewall iptables # Description: Script firewall de configuration des regles iptables ### END INIT INFO case "$1" in 'start') echo "\nChargement des regles du firewall..\n" # Vider les tables actuelles iptables -t filter -F echo "Vidage des tables : [OK]" # Vider les regles personnelles iptables -t filter -X echo "Vidage des regles : [OK]" # Interdire toute connexion entrante iptables -t filter -P INPUT DROP iptables -t filter -P FORWARD DROP echo "Interdire toute connexion entrante : [OK]" # Interdire toute connexion sortante iptables -t filter -P OUTPUT DROP echo "Interdire toute connexion sortante : [OK]" # Chargement des modules modprobe ip_conntrack_ftp echo "Chargement des modules : [OK]" # Ne pas casser les connexions etablies iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT echo "Ne pas casser les connexions etablies : [OK]" # Autoriser loopback (connexions localhost) iptables -t filter -A INPUT -i lo -j ACCEPT iptables -t filter -A OUTPUT -o lo -j ACCEPT echo "Autoriser loopback : [OK]" # Autoriser ICMP (Ping) iptables -t filter -A INPUT -p icmp -j ACCEPT iptables -t filter -A OUTPUT -p icmp -j ACCEPT echo "Autoriser ping : [OK]" # IP a blacklister # iptables -A INPUT -s ADRESSE_IP -j DROP echo "Mise a jour des IP blacklistees : [OK]" # Limiter le Syn-Flood a 1 seconde (protocoles TCP, UDP et ICMP) iptables -A FORWARD -p tcp --syn -m limit --limit 1/second -j ACCEPT iptables -A FORWARD -p udp -m limit --limit 1/second -j ACCEPT iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/second -j ACCEPT echo "Limiter le Syn-Flood : [OK]" # Limiter le scan de ports iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT echo "Limiter le scan de ports : [OK]" # Bloquer le Spoofing iptables -N SPOOFED iptables -A SPOOFED -s 127.0.0.0/8 -j DROP iptables -A SPOOFED -s 169.254.0.0/12 -j DROP iptables -A SPOOFED -s 172.16.0.0/12 -j DROP iptables -A SPOOFED -s 192.168.0.0/16 -j DROP iptables -A SPOOFED -s 10.0.0.0/8 -j DROP echo "Bloquer le Spoofing : [OK]" # Forcer la verification des paquets SYN iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP echo "Bloquer les paquets non SYN : [OK]" # forcer la verification des paquets fragmentes iptables -A INPUT -f -j DROP echo "Bloquer les paquets fragmentes : [OK]" # Supprimer les paquets mal formes XMAS iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP echo "Bloquer les paquets XMAS : [OK]" # Supprimer les paquets mal formes NULL iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP echo "Bloquer les paquets NULL : [OK]" # Supprimer les paquets non valides iptables -A INPUT -m state --state INVALID -j DROP echo "Bloquer les paquets non valides : [OK]" # Autoriser SSH iptables -t filter -A INPUT -p tcp --dport 22 -j ACCEPT iptables -t filter -A OUTPUT -p tcp --dport 22 -j ACCEPT echo "Autoriser SSH : [OK]" # Autoriser HTTP iptables -t filter -A OUTPUT -p tcp --dport 80 -j ACCEPT iptables -t filter -A INPUT -p tcp --dport 80 -j ACCEPT echo "Autoriser HTTP : [OK]" # Autoriser HTTPS iptables -t filter -A OUTPUT -p tcp --dport 443 -j ACCEPT iptables -t filter -A INPUT -p tcp --dport 443 -j ACCEPT echo "Autoriser HTTPS : [OK]" # Autoriser FTP iptables -t raw -A PREROUTING -p tcp --dport 21 -j CT --helper ftp iptables -t filter -A OUTPUT -p tcp --dport 20:21 -j ACCEPT iptables -t filter -A INPUT -p tcp --dport 20:21 -j ACCEPT iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT echo "Autoriser FTP : [OK]" # Autoriser DNS iptables -t filter -A OUTPUT -p tcp --dport 53 -j ACCEPT iptables -t filter -A OUTPUT -p udp --dport 53 -j ACCEPT iptables -t filter -A INPUT -p tcp --dport 53 -j ACCEPT iptables -t filter -A INPUT -p udp --dport 53 -j ACCEPT echo "Autoriser DNS : [OK]" # Autoriser NTP iptables -t filter -A OUTPUT -p udp --dport 123 -j ACCEPT echo "Autoriser NTP : [OK]" # Autoriser SMTP iptables -t filter -A INPUT -p tcp --dport 25 -j ACCEPT iptables -t filter -A OUTPUT -p tcp --dport 25 -j ACCEPT echo "Autoriser SMTP : [OK]" # Autoriser POP3 iptables -t filter -A INPUT -p tcp --dport 110 -j ACCEPT iptables -t filter -A OUTPUT -p tcp --dport 110 -j ACCEPT echo "Autoriser POP3 : [OK]" # Autoriser IMAP iptables -t filter -A INPUT -p tcp --dport 143 -j ACCEPT iptables -t filter -A OUTPUT -p tcp --dport 143 -j ACCEPT echo "Autoriser IMAP : [OK]" echo "\nConfiguration iptables termine\n" RETVAL=$? ;; 'stop') echo "\nRegles par defaut du firewall..\n" # Vider les tables actuelles iptables -t filter -F echo "Vidage des tables : [OK]" # Vider les regles personnelles iptables -t filter -X echo "Vidage des regles : [OK]" # Autoriser toute connexion entrante iptables -t filter -P INPUT ACCEPT iptables -t filter -P FORWARD ACCEPT echo "Autoriser toute connexion entrante : [OK]" # Autoriser toute connexion sortante iptables -t filter -P OUTPUT ACCEPT echo "Autoriser toute connexion sortante : [OK]" echo "\nConfiguration iptables termine\n" RETVAL=$? ;; 'status') echo "" iptables -L -n --line-numbers echo "" RETVAL=$? ;; *) echo "\nUsage: $0 { start | stop | status }\n" RETVAL=1 ;; esac exit $RETVAL
Rendez le script exécutable.
chmod +x /etc/init.d/firewall
Puis executez le avec la commande suivante.
/etc/init.d/firewall start
Pour finir nous allons créer un service pour executer le script firewall au démarrage du système.
Créer un nouveau fichier nommé /etc/systemd/system/firewall.service .
nano /etc/systemd/system/firewall.service
Et ajouter le script ci-dessous dedans.
[Unit] Description=Firewall Requires=network-online.target After=network-online.target [Service] User=root Type=oneshot RemainAfterExit=yes ExecStart=/etc/init.d/firewall.sh start ExecStop=/etc/init.d/firewall.sh stop [Install] WantedBy=multi-user.target
Notifier systemd qu'un nouveau fichier firewall.service existe en exécutant la commande suivante.
systemctl daemon-reload
Pour que le service soit lancé au démarrage du système.
systemctl enable firewall.service
Et pour démarrer le service.
systemctl start firewall.service