Module 5 · 5.1
Français
Ports et services en écoute
Module 5: Protéger le réseau · Temps de lecture : 10 minutes
Objectif pédagogique: À l'issue de cette leçon, vous saurez voir quels services écoutent sur votre serveur et sur quelle adresse, expliquer la différence entre 0.0.0.0 et 127.0.0.1, et vérifier depuis l'extérieur ce que tout internet voit de votre serveur.
Notions clés: port, TCP et UDP, écouter, ss -tulpn, 0.0.0.0 et [::], 127.0.0.1 et [::1], bind-address, ouvert, fermé et filtré, surface d'attaque, scanners
Une adresse IP avec 65.535 portes
Votre serveur possède une adresse IP, par exemple 192.0.2.10 et 2001:db8::10. Sur cette adresse, plusieurs programmes peuvent être joignables en même temps, chacun sur son propre port: un numéro de 1 à 65.535. Un programme qui accepte des connexions écoute sur un port. Quelques ports connus:
| Port | Protocole | Service |
|---|---|---|
| 22 | TCP | SSH |
| 80 | TCP | http (serveur web) |
| 443 | TCP et UDP | https (UDP pour HTTP/3) |
| 25 | TCP | courrier entre serveurs de messagerie (SMTP) |
| 3306 | TCP | MySQL et MariaDB |
| 5432 | TCP | PostgreSQL |
| 6379 | TCP | Redis |
TCP est le protocole des connexions qui doivent arriver de manière fiable (web, SSH, bases de données). UDP sert aux petits paquets rapides et indépendants (DNS, VPN comme WireGuard, HTTP/3). Un service écoute en TCP, en UDP ou les deux.
Chaque port en écoute est une porte vers votre serveur. Derrière chaque porte se trouve un logiciel qui peut contenir des failles. L'ensemble des portes accessibles depuis l'extérieur s'appelle votre surface d'attaque. Plus elle est petite, mieux c'est: un serveur qui héberge un site web n'a besoin, depuis l'extérieur, que des ports 22, 80 et 443.
Voir ce qui écoute: ss
La commande ss (socket statistics) affiche ce qui écoute sur votre serveur. Avec les options -t (TCP), -u (UDP), -l (uniquement en écoute), -p (quel programme) et -n (numéros, pas de noms):
anna@web1:~$ sudo ss -tulpn
Netid State Local Address:Port Peer Address:Port Process
udp UNCONN 127.0.0.54:53 0.0.0.0:* users:(("systemd-resolve",pid=402,fd=16))
tcp LISTEN 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=611,fd=3))
tcp LISTEN 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=902,fd=6))
tcp LISTEN 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=902,fd=7))
tcp LISTEN 127.0.0.1:3306 0.0.0.0:* users:(("mariadbd",pid=755,fd=21))
tcp LISTEN 0.0.0.0:6379 0.0.0.0:* users:(("redis-server",pid=780,fd=6))
tcp LISTEN [::]:22 [::]:* users:(("sshd",pid=611,fd=4))
tcp LISTEN [::]:80 [::]:* users:(("nginx",pid=902,fd=8))
tcp LISTEN [::]:443 [::]:* users:(("nginx",pid=902,fd=9))La colonne la plus importante est Local Address: l'adresse sur laquelle le programme écoute.
| Adresse | Signification |
|---|---|
0.0.0.0 | Toutes les adresses IPv4 du serveur, donc aussi l'adresse publique: joignable depuis l'extérieur (sauf si un pare-feu bloque) |
[::] | Toutes les adresses IPv6: idem pour IPv6 |
127.0.0.1 ou [::1] | Uniquement le serveur lui-même (loopback): jamais joignable depuis l'extérieur |
127.0.0.53, 127.0.0.54 | Également du loopback; c'est ici qu'écoute le résolveur DNS local de systemd-resolved |
192.0.2.10 | Uniquement cette adresse précise |
Dans l'exemple ci-dessus, MariaDB est correctement configuré: il écoute sur 127.0.0.1, donc seuls les programmes du serveur lui-même (votre site web) peuvent y accéder. En revanche, Redis écoute sur 0.0.0.0:6379. Si le pare-feu est mal réglé, tout internet peut y accéder. C'est exactement le type d'erreur dont traite cette leçon.
Écouter sur la bonne adresse
Une base de données, un cache ou un panneau d'administration ne doit presque jamais être accessible depuis l'extérieur. La première et la meilleure défense consiste à ce que le service n'écoute que sur le loopback. Un pare-feu (leçon 5.2) constitue la deuxième couche; il peut être désactivé par erreur ou ne pas s'appliquer (par exemple avec Docker, leçon 9.3).
L'endroit où vous réglez cela dépend du programme:
| Programme | Paramètre | Fichier (Debian/Ubuntu) |
|---|---|---|
| MariaDB/MySQL | bind-address = 127.0.0.1 | /etc/mysql/mariadb.conf.d/50-server.cnf |
| PostgreSQL | listen_addresses = 'localhost' | /etc/postgresql/<versie>/main/postgresql.conf |
| Redis | bind 127.0.0.1 -::1 et protected-mode yes | /etc/redis/redis.conf |
Les paquets de Debian et d'Ubuntu configurent déjà ces services sur localhost par défaut. Le problème survient généralement lorsque quelqu'un suit un tutoriel qui indique "mettez bind-address sur 0.0.0.0 pour vous connecter depuis l'extérieur". Si vous souhaitez accéder vous-même à la base de données depuis votre ordinateur portable, utilisez un tunnel SSH (leçon 2.3): le port reste fermé, et seules les personnes connectées via SSH peuvent y accéder.
Après une modification, redémarrez le service et vérifiez de nouveau avec ss -tulpn.
Ouvert, fermé et filtré
Vu de l'extérieur, un port peut se trouver dans trois états:
- Ouvert (open): quelque chose écoute et la connexion aboutit.
- Fermé (closed): rien n'écoute, ou un pare-feu refuse activement. Le serveur renvoie immédiatement un "non" (en TCP, un paquet RST). La connexion échoue aussitôt avec "Connection refused", c'est-à-dire connexion refusée.
- Filtré (filtered): un pare-feu jette le paquet en silence. La connexion reste bloquée jusqu'à expiration du délai (time-out).
Pour votre base de données, fermé et filtré sont tous deux corrects: personne n'y accède. La différence vous indique seulement pourquoi: filtré signifie presque toujours que votre pare-feu bloque.
Regarder depuis l'extérieur
ss montre ce qui écoute sur le serveur, mais pas ce qui est accessible depuis l'extérieur. Entre les deux se trouve encore un pare-feu, et parfois aussi un pare-feu réseau chez votre fournisseur. Le seul vrai contrôle consiste donc à regarder depuis l'extérieur, depuis un autre ordinateur.
Depuis votre propre ordinateur (pas depuis le serveur lui-même, car vous passeriez alors par le loopback), vous pouvez le faire avec nc (netcat) pour un port:
anna@laptop:~$ nc -vz -w 3 192.0.2.10 6379
nc: connect to 192.0.2.10 port 6379 (tcp) failed: Connection refused
anna@laptop:~$ nc -vz -w 3 192.0.2.10 22
Connection to 192.0.2.10 22 port [tcp/ssh] succeeded!Sous Windows, PowerShell fait la même chose avec Test-NetConnection 192.0.2.10 -Port 6379. Un scanner de ports comme nmap peut examiner plusieurs ports à la fois; n'utilisez un tel scanner que sur votre propre serveur.
N'oubliez pas IPv6. Une erreur fréquente est un pare-feu qui n'a de règles que pour IPv4, alors que le service écoute aussi sur [::]. Testez donc aussi l'adresse IPv6: nc -6 -vz -w 3 2001:db8::10 6379.
Pourquoi c'est si important
Votre serveur est scanné dès la première minute. Les moteurs de recherche d'appareils et de services sur internet, ainsi que les bots de criminels, sondent en permanence toutes les adresses IPv4 sur des ports connus. Un Redis ouvert sans mot de passe, un cluster Elasticsearch ou un MongoDB sans contrôle d'accès est trouvé en très peu de temps. Les fuites de données dues à des bases de données et des clusters de recherche ouverts font régulièrement l'actualité, et il s'agit presque toujours de cette même erreur: un service destiné à un usage interne écoutait sur toutes les adresses.
Le port SSH reçoit lui aussi des tentatives toute la journée. C'est normal et, avec des clés (leçon 2.2) et fail2ban (leçon 5.3), cela ne pose pas de problème.
Le contrôle de la formation
Dans l'exercice de cette leçon, le programme de la formation vérifie depuis l'extérieur cinq ports de base de données fixes de votre serveur: 3306 (MySQL/MariaDB), 5432 (PostgreSQL), 6379 (Redis), 9200 (Elasticsearch/OpenSearch) et 27017 (MongoDB). Le programme essaie uniquement d'établir une connexion, n'envoie aucune donnée et ne se connecte nulle part. Il ne scanne aucun autre port. Les contrôles proviennent de l'adresse IP indiquée dans l'exercice, afin que vous puissiez les reconnaître dans vos propres journaux. Une adresse ne peut être contrôlée que quelques fois par heure.
Sur AlmaLinux et Rocky Linux
ss fonctionne de la même manière. Les fichiers des services se trouvent à d'autres emplacements (par exemple /etc/my.cnf.d/ pour MariaDB, /var/lib/pgsql/data/postgresql.conf pour PostgreSQL). Par ailleurs, SELinux peut bloquer un service qui veut écouter sur un port inhabituel; vous le verrez alors dans journalctl (leçon 6.2) et non dans ss.
Résumé
- Chaque port en écoute est une porte; depuis l'extérieur, ne laissez ouvert que ce qui est vraiment nécessaire (généralement 22, 80 et 443).
sudo ss -tulpnindique quel programme écoute sur quelle adresse et quel port.0.0.0.0et[::]signifient "toutes les adresses",127.0.0.1et[::1]signifient "uniquement le serveur lui-même". Les bases de données, caches et clusters de recherche doivent écouter sur le loopback.- Fermé et filtré sont tous deux corrects pour une base de données; ouvert est une erreur.
- Vérifiez toujours depuis l'extérieur, en IPv4 et en IPv6, car
ssne voit pas le pare-feu.
Quiz
Exercice
Exercice Z5.1: Ports de base de données fermés depuis l'extérieur. Exécutez sudo ss -tulpn sur votre serveur et identifiez les adresses sur lesquelles vos services écoutent. Laissez ensuite le programme de la formation vérifier depuis l'extérieur que les ports 3306, 5432, 6379, 9200 et 27017 de votre serveur ne sont pas accessibles, en IPv4 et (si votre serveur a un enregistrement AAAA) en IPv6. Indiquez également quels services écoutent chez vous sur 0.0.0.0 ou [::]. Le programme se contente d'ouvrir une connexion vers ces cinq ports et n'envoie rien.
