magentix

Développeur backend indépendant Web, e-commerce, Open-Source, low-tech, indie-web, slow-web, SSG, accessibility, PHP, Python

Billets : Les règles iptables pour sécuriser au maximum un serveur Web


Les règles iptables pour sécuriser au maximum un serveur Web

Par Matthieu le 06/01/2020

Pour sécuriser un serveur Web, j'applique systèmatiquement le même comportement : bloquer l'ensemble du traffic sur tous les ports, sauf 80 (http) et 443 (https). Seuls quelques IPs sont autorisés à accéder au reste. Voici comment le mettre en place avec iptables.


Sur un serveur accessible à distance, les scans de port et les tentatives de connexion SSH sont légions. La solution la plus radicale est de tout bloquer, sauf les ports dont le serveur a besoin pour le ou les services qu'il propose.

Attention : il est indispensable pour un serveur distant (serveur dédié par exemple) d'autoriser l'accès SSH (port 22 par défaut) à plusieurs IPs fixes : la votre et des IPs de secours. Si vous ne disposez pas d'IP fixe ne bloquez pas l'accès à SSH et proposez le service sur un autre port que 22.

Configuration

On vérifie dans un premier temps qu'iptables est bien en place sur le serveur, si ce n'est pas le cas, on procède à l'installation. On installe également iptables-persistent (qui dépend de netfilter-persistent) afin que les règles soient conservées après un redémarrage du serveur :

sudo apt-get install iptables iptables-persistent netfilter-persistent

Pour contrôler les règles en place, on utilise les commandes suivantes (iptables pour IPv4, ip6tables pour IPv6) :

sudo iptables -L
sudo ip6tables -L

Par défaut, le pare-feu accepte toutes les connexions.

Note : nous appliquons dans cet article uniquement des règles sur le traffic entrant (INPUT).

Règles du pare-feu

Le plus simple est d'écrire les règles souhaitées dans un fichier spécifique :

sudo nano /etc/iptables.custom.rules

Afin de bloquer le traffic sur l'ensemble des ports exceptés les 80, 443 et 22, nous utilisons les règles suivantes :

*filter

# Allow unlimited traffic on loopback
-A INPUT -i lo -j ACCEPT

# Allow ESTABLISHED and RELATED packets
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Allow traffic on specified ports (ex: web server)
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT # Comment for reject SSH connection

# Allow all for specified IPs (whitelist)
-A INPUT -s 123.123.123.123 -j ACCEPT
-A INPUT -s 456.456.456.456 -j ACCEPT

# Reject traffic other than for the rules mentioned above
-A INPUT -j DROP

COMMIT

N'oubliez pas de remplacer la whitelist par vos IPs.

# Allow all for specified IPs
-A INPUT -s 123.123.123.123 -j ACCEPT # Votre IP Fixe 1
-A INPUT -s 456.456.456.456 -j ACCEPT # Votre IP Fixe 2
# ...

IPv6

Si le serveur dispose d'une adresse IPv6, les règles iptables ne s'appliquent pas à ce trafic : il reste entièrement ouvert. Il est donc nécessaire d'écrire les mêmes règles pour IPv6 dans un second fichier :

sudo nano /etc/ip6tables.custom.rules
*filter

# Allow unlimited traffic on loopback
-A INPUT -i lo -j ACCEPT

# Allow ESTABLISHED and RELATED packets
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Allow ICMPv6 (required for IPv6 to work properly)
-A INPUT -p ipv6-icmp -j ACCEPT

# Allow traffic on specified ports (ex: web server)
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT # Comment for reject SSH connection

# Allow all for specified IPs (whitelist)
-A INPUT -s 2001:db8::1 -j ACCEPT
-A INPUT -s 2001:db8::2 -j ACCEPT

# Reject traffic other than for the rules mentioned above
-A INPUT -j DROP

COMMIT

Là aussi, remplacez la whitelist par vos IPv6 fixes (ou supprimez ces lignes si vous n'en disposez pas).

Application

Une fois les règles écrites, il ne reste plus qu'à les appliquer :

sudo iptables-restore < /etc/iptables.custom.rules
sudo ip6tables-restore < /etc/ip6tables.custom.rules

On vérifie que les règles sont bien appliquées :

sudo iptables -L
sudo ip6tables -L

Les règles appliquées sont perdues au redémarrage du serveur. Pour les rendre persistantes, on les sauvegarde avec netfilter-persistent :

sudo netfilter-persistent save

Les règles sont enregistrées dans /etc/iptables/rules.v4 et /etc/iptables/rules.v6, puis rechargées automatiquement à chaque démarrage.

Explications

Loopback

-A INPUT -i lo -j ACCEPT

Cette règle correspond au trafic loopback qui permet aux services de la machine de communiquer entre elles.

State

-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

On autorise ici les connexions déjà établies.

Ports autorisés

-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT

On établie la liste de tous les ports pour lesquels on autorise le traffic. Vous pouvez adapter cette liste selon le type de service proposé par le serveur.

ICMPv6

-A INPUT -p ipv6-icmp -j ACCEPT

Contrairement à IPv4, IPv6 ne peut pas fonctionner sans ICMP : la découverte des voisins (équivalent d'ARP), l'attribution d'adresse et la gestion de la taille des paquets en dépendent. Cette règle, présente uniquement dans les règles IPv6, est indispensable sous peine de perdre la connectivité IPv6 du serveur.

Whitelist

-A INPUT -s 123.123.123.123 -j ACCEPT
-A INPUT -s 456.456.456.456 -j ACCEPT

Liste des IPs depuis lesquels l'accès à l'ensemble du serveur est autorisé. Si vous souhaitez bloquer l'accès SSH, assurez vous que cette liste d'IPs soit valide, au risque de ne plus pouvoir accéder au serveur.

Drop

-A INPUT -j DROP

On rejette tout le reste.

Réinitialisation

Si vous souhaitez restaurer les règles par défaut (ACCEPT), utilisez les commandes suivantes :

sudo iptables -F
sudo ip6tables -F

Pensez ensuite à sauvegarder, sans quoi les anciennes règles seront rechargées au prochain démarrage :

sudo netfilter-persistent save