Comment configurer un pare-feu iptables pour protéger le trafic entre vos serveurs

Introduction

Le déploiement de composants discrets de votre application sur différents nœuds est une manière courante de réduire la charge et de commencer à mettre en place une scalabilité horizontale. Un exemple typique est la configuration d’une base de données sur un serveur distinct de votre application. Bien qu’il y ait plusieurs avantages à cette configuration, la connexion via un réseau entraîne de nouvelles préoccupations en matière de sécurité.

Dans ce guide, nous vous montrerons comment configurer un pare-feu sur chacun de vos serveurs dans une configuration distribuée. Nous configurerons notre politique pour autoriser le trafic prévu entre nos composants tout en refusant les autres types de trafic.

Vous pouvez également configurer les pare-feux Cloud de DigitalOcean qui fonctionnent en tant que couche supplémentaire et externe à vos serveurs sur l’infrastructure de DigitalOcean. De cette manière, vous n’avez pas besoin de configurer un pare-feu sur vos serveurs eux-mêmes.

Pour la démonstration dans ce guide, nous utiliserons deux serveurs Ubuntu 22.04. L’un d’entre eux hébergera une application web servie par Nginx et l’autre hébergera la base de données MySQL de l’application. Bien que nous utilisions cette configuration comme exemple, vous devriez pouvoir extrapoler les techniques utilisées pour adapter les exigences à vos propres serveurs.

Prérequis

Pour commencer, vous devrez disposer de deux serveurs Ubuntu 22.04 frais. Ajoutez un compte utilisateur régulier avec des privilèges sudo sur chacun d’eux. Pour ce faire, suivez notre guide de configuration initiale du serveur Ubuntu 22.04.

La configuration de l’application que nous allons sécuriser est basée sur ce guide. Si vous souhaitez suivre cet exemple, configurez vos serveurs d’application et de base de données comme indiqué dans ce tutoriel. Sinon, vous pouvez utiliser cet article comme référence générale.

Étape 1 – Configuration d’un pare-feu

Vous commencerez par mettre en place une configuration de pare-feu de base pour chacun de vos serveurs. La politique que nous allons mettre en place adopte une approche axée sur la sécurité. Nous allons tout verrouiller sauf le trafic SSH, puis ouvrir des ports dans le pare-feu pour notre application spécifique.

Ce guide utilise la syntaxe iptables. iptables est automatiquement installé sur Ubuntu 22.04 avec une backend nftables, vous ne devriez donc pas avoir à installer de paquets supplémentaires.

À l’aide de nano ou de votre éditeur de texte préféré, ouvrez le fichier /etc/iptables/rules.v4:

  1. sudo nano /etc/iptables/rules.v4

Collez la configuration à partir du guide modèle du pare-feu :

/etc/iptables/rules.v4
*filter
# Autoriser toutes les connexions sortantes, mais bloquer les paquets entrants et de transfert par défaut
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

# Chaînes personnalisées par protocole
:UDP - [0:0]
:TCP - [0:0]
:ICMP - [0:0]

# Trafic UDP acceptable

# Trafic TCP acceptable
-A TCP -p tcp --dport 22 -j ACCEPT

# Trafic ICMP acceptable

# Politique d'acceptation par défaut
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT

# Rejeter les paquets invalides
-A INPUT -m conntrack --ctstate INVALID -j DROP

# Passer le trafic aux chaînes spécifiques au protocole
## Autoriser uniquement les nouvelles connexions (les connexions établies et apparentées devraient déjà être gérées)
## Pour TCP, autoriser uniquement les nouveaux paquets SYN, car c'est la seule méthode valide
## pour établir une nouvelle connexion TCP
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

# Rejeter tout ce qui est arrivé jusqu'à ce point
## Essayer d'être spécifique au protocole avec un message de rejet
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable

# Appliquer les modifications
COMMIT

*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

*security
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

Enregistrez et fermez le fichier. Si vous utilisez nano, appuyez sur Ctrl+X pour quitter, puis, lorsque vous y êtes invité, appuyez sur O et ensuite sur Entrée.

Si vous implémentez ceci dans un environnement en direct, ne rechargez pas encore vos règles de pare-feu. Le chargement de l’ensemble de règles décrit ici va immédiatement interrompre la connexion entre votre application et le serveur de base de données. Vous devrez ajuster les règles pour refléter nos besoins opérationnels avant de recharger.

Étape 2 – Découvrir les ports utilisés par vos services

Pour permettre la communication entre vos composants, vous devez connaître les ports réseau utilisés. Vous pouvez trouver les ports réseau corrects en examinant vos fichiers de configuration, mais une méthode indépendante de l’application pour trouver les ports corrects consiste simplement à vérifier quels services écoutent les connexions sur chacune de nos machines.

Vous pouvez utiliser l’outil netstat pour le découvrir. Étant donné que votre application ne communique qu’en IPv4, nous ajouterons l’argument -4, mais vous pouvez le supprimer si vous utilisez également IPv6. Les autres arguments dont vous avez besoin pour trouver vos services en cours d’exécution sont -p, -l, -u, -n et -t, que vous pouvez fournir comme -plunt.

Ces arguments peuvent être décomposés comme suit :

  • p: Show the PID and name of the program to which each socket belongs.
  • l: Show only listening sockets.
  • u: Show UDP traffic.
  • n: Show numeric output instead of service names.
  • t: Show TCP traffic.
  1. sudo netstat -4plunt

Sur votre serveur web, votre sortie pourrait ressembler à ceci :

Output
Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1058/sshd tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4187/nginx

La première colonne mise en évidence montre l’adresse IP et le port sur lesquels le service mis en évidence vers la fin de la ligne est en écoute. L’adresse spéciale 0.0.0.0 signifie que le service en question est en écoute sur toutes les adresses disponibles.

Sur votre serveur de base de données, votre sortie pourrait ressembler à ceci :

  1. sudo netstat -4plunt
Output
Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1097/sshd tcp 0 0 192.0.2.30:3306 0.0.0.0:* LISTEN 3112/mysqld

Vous pouvez lire ces colonnes exactement de la même manière. Dans cet exemple, l’adresse 192.0.2.30 représente l’adresse IP privée du serveur de base de données. Dans le tutoriel préalable, vous avez restreint MySQL à l’interface privée pour des raisons de sécurité.

Notez les valeurs que vous trouvez à cette étape. Ce sont les détails de mise en réseau dont vous aurez besoin pour ajuster la configuration de votre pare-feu.

Sur votre serveur web, vous devez vous assurer que les ports suivants sont accessibles :

  • Port 80 sur toutes les adresses
  • Port 22 sur toutes les adresses (déjà pris en compte dans les règles du pare-feu)

Votre serveur de base de données doit s’assurer que les ports suivants sont accessibles:

  • Port 3306 sur l’adresse 192.0.2.30 (ou l’interface associée à celle-ci)
  • Port 22 sur toutes les adresses (déjà pris en compte dans les règles du pare-feu)

Étape 3 — Ajuster les règles de pare-feu du serveur Web

Maintenant que vous disposez des informations de port dont vous avez besoin, vous allez ajuster l’ensemble des règles de pare-feu de votre serveur Web. Ouvrez le fichier des règles dans votre éditeur avec les privilèges sudo:

  1. sudo nano /etc/iptables/rules.v4

Sur le serveur Web, vous devez ajouter le port 80 à votre liste de trafic acceptable. Étant donné que le serveur écoute sur toutes les adresses disponibles – les serveurs Web s’attendent généralement à être accessibles de n’importe où – vous ne limiterez pas la règle par interface ou adresse de destination.

Vos visiteurs Web utiliseront le protocole TCP pour se connecter. Votre framework dispose déjà d’une chaîne personnalisée appelée TCP pour les exceptions d’application TCP. Vous pouvez ajouter le port 80 à cette chaîne, juste en dessous de l’exception pour votre port SSH:

/etc/iptables/rules.v4
*filter
. . .

# Trafic TCP acceptable
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 80 -j ACCEPT

. . .

Votre serveur web initiera la connexion avec votre serveur de base de données. Votre trafic sortant n’est pas restreint par votre pare-feu et le trafic entrant associé aux connexions établies est autorisé, donc vous n’avez pas besoin d’ouvrir de ports supplémentaires sur ce serveur pour permettre cette connexion.

Enregistrez et fermez le fichier lorsque vous avez terminé. Votre serveur web dispose maintenant d’une politique de pare-feu qui permettra tout le trafic légitime tout en bloquant tout le reste.

Testez votre fichier de règles pour détecter les erreurs de syntaxe :

  1. sudo iptables-restore -t < /etc/iptables/rules.v4

Si aucune erreur de syntaxe n’est affichée, rechargez le pare-feu pour mettre en œuvre le nouvel ensemble de règles :

  1. sudo service iptables-persistent reload

Étape 4 – Ajustez les règles de pare-feu du serveur de base de données

Sur votre serveur de base de données, vous devez autoriser l’accès au port 3306 sur l’adresse IP privée de votre serveur. Dans ce cas, cette adresse était 192.0.2.30. Vous pouvez limiter l’accès spécifiquement à cette adresse, ou vous pouvez limiter l’accès en fonction de l’interface qui est assignée à cette adresse.

Pour trouver l’interface réseau associée à cette adresse, exécutez la commande ip -4 addr show scope global :

  1. ip -4 addr show scope global
Output
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 203.0.113.5/24 brd 104.236.113.255 scope global eth0 valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 192.0.2.30/24 brd 192.0.2.255 scope global eth1 valid_lft forever preferred_lft forever

Les zones surlignées montrent que l’interface eth1 est associée à cette adresse.

Ensuite, vous ajusterez les règles de pare-feu sur le serveur de base de données. Ouvrez le fichier de règles avec les privilèges sudo sur votre serveur de base de données :

  1. sudo nano /etc/iptables/rules.v4

Encore une fois, vous ajouterez une règle à notre chaîne TCP pour former une exception pour la connexion entre vos serveurs web et de base de données.

Pour restreindre l’accès en fonction de l’adresse réelle en question, vous ajouterez la règle comme ceci:

/etc/iptables/rules.v4
*filter
. . .

# Trafic TCP acceptable
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -d 192.0.2.30 -j ACCEPT

. . .

Si vous préférez autoriser l’exception en fonction de l’interface qui contient cette adresse, vous pouvez plutôt ajouter une règle similaire à celle-ci:

/etc/iptables/rules.v4
*filter
. . .

# Trafic TCP acceptable
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -i eth1 -j ACCEPT

. . .

Enregistrez et fermez le fichier lorsque vous avez terminé.

Vérifiez les erreurs de syntaxe avec cette commande:

  1. sudo iptables-restore -t < /etc/iptables/rules.v4

Quand vous êtes prêt, rechargez les règles du pare-feu:

  1. sudo service iptables-persistent reload

Ainsi, vos deux serveurs devraient être protégés sans restreindre le flux de données nécessaire entre eux.

Conclusion

L’implémentation d’un pare-feu approprié devrait toujours faire partie de votre plan de déploiement lors de la configuration d’une application. Bien que nous ayons démontré cette configuration en utilisant deux serveurs exécutant Nginx et MySQL, les techniques démontrées ci-dessus sont applicables indépendamment de vos choix technologiques spécifiques.

Pour en savoir plus sur les pare-feu et iptables en particulier, consultez les guides suivants:

Source:
https://www.digitalocean.com/community/tutorials/how-to-set-up-an-iptables-firewall-to-protect-traffic-between-your-servers