Sécuriser Debian 9 avec Iptables

Généralités

Iptables est un utilitaire avec une interface en ligne de commande permettant de configurer le firewall (pare-feu) Netfilter intégré dans le noyau Linux.

Il permet de filtrer, rediriger et contrôler le trafic réseau (entrant, sortant, local).

Installation

Il suffit d’installer le paquet.

apt install iptables

Déclaration des règles

Fonctionnement

Le trafic est traité selon des tables (filter, nat, mangle, raw).
Chaque table contient des chaînes (chains).
Une chaîne est composée de règles, qui sont évaluées séquentiellement.
Chaque règle applique une action (target) : ACCEPT, DROP, REJECT, LOG, DNAT, SNAT, etc.

Exemple de schéma :

Paquet réseau → Chaîne → Liste de règles → Action finale

Tables principales

TableUsage principalChaînes principales
filterFiltrage classique des paquetsINPUT, OUTPUT, FORWARD
natTraduction d’adressesPREROUTING, POSTROUTING, OUTPUT, CHAIN
mangleModification des paquetsPREROUTING, OUTPUT, FORWARD, INPUT
rawConfiguration avancéePREROUTING, OUTPUT

Notes :

filter : utilisée pour accepter ou bloquer les paquets.
nat : utilisée surtout pour les serveurs qui font du routage/NAT.
mangle : permet de marquer ou modifier certains champs des paquets avant routage.
raw : permet de configurer certains paquets pour qu’ils ne passent pas par le suivi de connexion

INPUT → paquets entrants destinés au serveur local.
OUTPUT → paquets sortants générés par le serveur local.
FORWARD → paquets qui transitent par le serveur (routeur/NAT).
PREROUTING → règles appliquées avant le routage, utile pour NAT et marquage.
POSTROUTING → règles appliquées après le routage, souvent pour SNAT/MASQUERADE.

Actions principales

Action / TargetDescription
ACCEPTAccepter le paquet et le laisser passer.
DROPBloquer le paquet silencieusement (pas de réponse).
REJECTBloquer le paquet et envoyer un message d’erreur au client.
LOGJournaliser le paquet dans syslog (ne le bloque pas).
RETURNArrêter de traiter la chaîne courante et revenir à la chaîne précédente.
SNAT(dans nat) Modifier l’adresse source (Source NAT).
DNAT(dans nat) Modifier l’adresse de destination (Destination NAT).
MASQUERADE(dans nat) Variante de SNAT pour IP dynamique (ex. Internet partagé).
MARK(dans mangle) Marquer le paquet pour traitement ultérieur (QoS, routage).

Exemple simple de pare-feu

Pour plus de souplesse, nous allons écrire nos règles sous forme de script bash.

Créons le script.

nano /etc/init.d/firewall

Et on y écrit.

#!/bin/bash

On efface toutes les règles précédentes pour partir sur de bonnes bases.

# Vider les règles existantes : Table filter (règles classiques)
iptables -t filter -F
iptables -t filter -X

On bloque par défaut tout le trafic.

# Politique par défaut : tout bloquer (entrant, sortant, transité)
iptables -t filter -P INPUT DROP
iptables -t filter -P OUTPUT DROP
iptables -t filter -P FORWARD DROP

On ne ferme pas les connexions déjà établies ou liées.

# Autoriser les connexions établies ou liées (entrant, sortant)
iptables -t filter -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t filter -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

On autorise les connexions locales (on ne va pas se bloquer nous-mêmes !).

# Autoriser les connexions locales (loopback)
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 des ports

À partir de maintenant, observons plus en détail les paramètres de iptables.

-t : sert à sélectionner la table (par défaut : filter)
-A : sert à indiquer le sens du trafic (INPUT (entrant) ou OUTPUT (sortant))
-p : sert à spécifier le protocole (TCP ou UDP en principe)
–sport et –dport : servent à spécifier les ports source ou destination (nous utiliserons principalement –dport)
-j : sert à indiquer l’action à appliquer (nous nous servirons de 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 règles 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 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

ou (sans -t filter)

iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

Les deux commandes fonctionnent exactement de la même manière, car par défaut, si tu ne précises pas de table, iptables utilise la table filter, qui est la table principale.

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).

serviceport d’écouteprotocole
SSH22tcp
HTTP80tcp
FTP20 et 21tcp
SMTP25tcp
POP3110tcp
IMAP143tcp
DNS53tcp 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 -A INPUT -p icmp -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT

Allez un peu plus loin

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.

Flood ou déni de service

Ce genre d’attaque vise à surcharger la machine de requête. Il est possible de s’en prémunir directement au niveau du firewall.

iptables -A INPUT -p tcp --syn -m limit --limit 15/second -j ACCEPT

Le flags TCP –syn engendre des demandes de connexions, et le but de cette règle est donc de les limiter à 10 par seconde (champs limit).

Il est cependant déconseillé de descendre en dessous de certaines limites (sous peine de bloquer des utilisateurs légitimes).
Il est aussi déconseillé de monter au dessus de certaines limites (sous peine de réduire la protection contre les SYN flood).

On peut faire de même avec les protocoles UDP et ICMP.

iptables -A INPUT -p udp -m limit --limit 30/second -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/second -j ACCEPT

Notez cependant que ce type d’attaque permet de faire tomber le serveur, mais pas d’en prendre l’accès.

Scan de ports

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 INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 5/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.

Notez que cette règle basique n’est pas très efficace, c’est une protection de base.

Bannir une IP

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.

Exemple de script

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

RETVAL=0

case "$1" in

  'start')
    echo -e "\nChargement des regles du firewall…\n"

    # Vider toutes les règles actuelles de la table filter
    iptables -t filter -F
    iptables -t filter -X
    echo "Vidage des regles de la table filter : [OK]"

    # Vider toutes les règles actuelles de la table nat
    iptables -t nat -F
    iptables -t nat -X
    echo "Vidage des regles de la table nat : [OK]"

    # Vider toutes les règles actuelles de la table mangle
    iptables -t mangle -F
    iptables -t mangle -X
    echo "Vidage des regles de la table mangle : [OK]"

    # Vider toutes les règles actuelles de la table raw
    iptables -t raw -F
    iptables -t raw -X
    echo "Vidage des regles de la table raw : [OK]"

    # Interdire toutes les connexions entrantes et transitants
    iptables -P INPUT DROP
    iptables -P FORWARD DROP
    echo "Interdire toutes les connexions entrantes et transitants : [OK]"

    # Interdire toutes les connexions sortantes
    iptables -P OUTPUT DROP
    echo "Interdire toutes les connexions sortantes : [OK]"

    # Chargement du module ip_conntrack_ftp pour gérer correctement les connexions FTP
    modprobe ip_conntrack_ftp
    echo "Chargement du module : [OK]"

    # Autoriser les connexions établies ou liées
    iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    echo "Autoriser les connexions etablies ou liees : [OK]"

    # Autoriser les connexions localhost (loopback)
    iptables -A INPUT -i lo -j ACCEPT
    iptables -A OUTPUT -i lo -j ACCEPT
    echo "Autoriser loopback : [OK]"

    # Autoriser ICMP (Ping)
    iptables -A INPUT -p icmp -j ACCEPT
    iptables -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 (TCP, UDP et ICMP)
    iptables -A INPUT -p tcp --syn -m limit --limit 15/second -j ACCEPT
    iptables -A INPUT -p udp -m limit --limit 30/second -j ACCEPT
    iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/second -j ACCEPT
    echo "Limiter le Syn-Flood : [OK]"

    # Limiter le scan de ports
    iptables -A INPUT -p tcp --tcp-flags RST RST -m limit --limit 5/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
    iptables -A INPUT -j SPOOFED
    iptables -A FORWARD -j SPOOFED
    echo "Bloquer le Spoofing : [OK]"

    # Forcer la vérification des paquets SYN
    iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
    echo "Bloquer les paquets non SYN : [OK]"

    # Forcer la vérification des paquets fragmentés
    iptables -A INPUT -f -j DROP
    echo "Bloquer les paquets fragmentes : [OK]"

    # Supprimer les paquets mal formés XMAS
    iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
    echo "Bloquer les paquets XMAS : [OK]"

    # Supprimer les paquets mal formés 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 -A INPUT -p tcp --dport 22 -j ACCEPT
    iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
    echo "Autoriser SSH : [OK]"

    # Autoriser HTTP
    iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
    iptables -A INPUT -p tcp --dport 80 -j ACCEPT
    echo "Autoriser HTTP : [OK]"

    # Autoriser HTTPS
    iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
    iptables -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 -A OUTPUT -p tcp --dport 20:21 -j ACCEPT
    iptables -A INPUT -p tcp --dport 20:21 -j ACCEPT
    echo "Autoriser FTP : [OK]"

    # Autoriser DNS
    iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
    iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
    echo "Autoriser DNS : [OK]"

    # Autoriser NTP
    iptables -A OUTPUT -p udp --dport 123 -j ACCEPT
    echo "Autoriser NTP : [OK]"

    # Autoriser SMTP
    iptables -A INPUT -p tcp --dport 25 -j ACCEPT
    iptables -A OUTPUT -p tcp --dport 25 -j ACCEPT
    echo "Autoriser SMTP : [OK]"

    # Autoriser POP3
    iptables -A INPUT -p tcp --dport 110 -j ACCEPT
    iptables -A OUTPUT -p tcp --dport 110 -j ACCEPT
    echo "Autoriser POP3 : [OK]"

    # Autoriser IMAP
    iptables -A INPUT -p tcp --dport 143 -j ACCEPT
    iptables -A OUTPUT -p tcp --dport 143 -j ACCEPT
    echo "Autoriser IMAP : [OK]"

    echo -e "\nConfiguration iptables terminee\n"
    RETVAL=$?
    ;;

  'stop')
    echo -e "\nRegles par defaut du firewall..\n"

    # Vider toutes les règles
    iptables -t filter -F
    iptables -t filter -X
    echo "Vidage des regles de la table filter : [OK]"

    iptables -t nat -F
    iptables -t nat -X
    echo "Vidage des regles de la table nat : [OK]"

    iptables -t mangle -F
    iptables -t mangle -X
    echo "Vidage des regles de la table mangle : [OK]"

    iptables -t raw -F
    iptables -t raw -X
    echo "Vidage des regles de la table raw : [OK]"

    # Politique par défaut ACCEPT
    iptables -P INPUT ACCEPT
    iptables -P FORWARD ACCEPT
    iptables -P OUTPUT ACCEPT
    echo "Autoriser toutes les connexions : [OK]"

    echo -e "\nConfiguration iptables terminee\n"
    RETVAL=$?
    ;;

  'status')
    echo ""
    iptables -L -n --line-numbers
    echo ""
    RETVAL=$?
    ;;

  *)
    echo -e "\nUsage: $0 { start | stop | status }\n"
    RETVAL=1
    ;;
esac

exit $RETVAL