La liste des ports ouverts, c’est la liste des chemins vers votre serveur. Tout le reste — pare-feu, WAF, détection d’intrusion — se construit par-dessus. C’est pourquoi « qu’est-ce qui écoute ici » vient en premier dans tout audit, et c’est aussi la vérification qui donne le plus souvent un résultat désagréable : la moitié de ce qu’on y trouve n’a pas été ouverte par vous mais par l’installateur d’un paquet.
Lire la sortie
sudo ss -tulpn
Les options : t pour TCP, u pour UDP, l seulement ce qui écoute, p le processus, n les nombres restent des nombres. Sans sudo, la colonne du processus est vide et l’exercice perd son sens.
Ce qui compte est la colonne Local Address:Port, et la distinction y est fondamentale :
127.0.0.1:3306— le service n’est joignable que depuis la machine elle-même. C’est bien ;0.0.0.0:3306— depuis toute adresse IPv4, donc depuis l’internet. C’est ce qu’il faut vérifier ;[::]:3306— la même chose en IPv6. Une ligne à part, régulièrement négligée ;203.0.113.25:443— sur une adresse précise, généralement volontaire.
Ensuite, pour chaque ligne avec 0.0.0.0 ou [::], posez une question : un inconnu doit-il pouvoir joindre cela ? Pour 80 et 443, la réponse est oui. Pour presque tout le reste, non.
Les découvertes habituelles
Redis, port 6379. La ligne la plus dangereuse qui soit. Par défaut, Redis n’exige pas de mot de passe, et ses commandes permettent d’écrire un fichier sur le disque — donc une clé étrangère dans authorized_keys. Entre l’apparition de Redis sur une adresse publique et son exploitation, il s’écoule des heures, parfois moins. Vérifiez bind 127.0.0.1 et protected-mode yes dans la configuration.
Memcached, 11211/UDP. Même s’il ne contient rien de précieux, votre serveur devient un amplificateur pour les attaques d’autrui — et la réclamation viendra de l’hébergeur.
MySQL et PostgreSQL, 3306 et 5432. Il y a un mot de passe, mais on le cherche en continu, et les versions de bases de données sont mises à jour moins souvent qu’on ne le voudrait. Ils n’ont presque jamais besoin d’être exposés : l’application vit sur la même machine, et un tunnel SSH suffit pour votre travail.
Elasticsearch 9200, MongoDB 27017. Historiquement sans authentification par défaut. Les instances publiques de ces services sont une source constante de nouvelles de fuites de données.
L’API Docker, 2375. Un port de commande Docker ouvert, c’est root sur l’hôte sans aucun mot de passe. Il apparaît d’ordinaire après des expériences d’accès distant à Docker.
Panneaux de gestion et phpMyAdmin sur leurs ports : 8080, 8083, 10000. Non qu’il ne faille jamais les ouvrir, mais ce sont eux qui concentrent l’essentiel des tentatives.
Corriger au niveau du service, pas du pare-feu
L’envie de fermer chaque découverte par une règle UFW se comprend, mais c’est la seconde ligne, pas la première. Une règle peut être supprimée par erreur, un pare-feu désactivé le temps d’un débogage, et Docker publie les ports en contournant complètement UFW. Un réglage d’attachement dans la configuration du service survit à tout cela :
- MySQL/MariaDB —
bind-address = 127.0.0.1; - PostgreSQL —
listen_addresses = 'localhost'; - Redis —
bind 127.0.0.1 ::1; - Docker Compose — publication sous la forme
"127.0.0.1:5432:5432".
Le pare-feu se pose par-dessus comme assurance, et non à la place.
Trouver le processus en cas de doute
ss donne le nom et le pid. Ensuite :
sudo systemctl status <pid>
sudo lsof -i :8080
La première commande nomme l’unité systemd à laquelle appartient le processus — généralement assez pour comprendre ce que c’est et si c’est nécessaire. Un processus inconnu qui écoute sur un port élevé et a été lancé hors des répertoires système — depuis /tmp ou /dev/shm, par exemple — n’est plus une question de configuration mais un motif d’enquête à part entière.
La vérification depuis l’extérieur est obligatoire
ss répond à « qu’est-ce qui écoute », pas à « qu’est-ce qui est joignable ». Entre les deux se trouvent le pare-feu, le NAT et les règles de l’hébergeur. La seule réponse honnête vient d’un balayage depuis une autre machine :
nmap -Pn -p- 203.0.113.25
nmap -Pn -p- -6 2001:db8::1
Ne négligez pas la seconde commande : presque tout VPS possède une adresse IPv6, ses règles s’écrivent séparément, et le service écoute sur les deux versions du protocole à la fois.
Ce n’est pas une vérification ponctuelle
La liste des ports ouverts change toute seule. Vous avez installé un paquet, il a amené un service et ouvert un port. Vous avez mis à jour un panneau, il a rétabli une valeur par défaut. Vous avez lancé un conteneur, il a publié un port en contournant le pare-feu. Une vérification ponctuelle répond pour aujourd’hui et pour rien d’autre.
La valeur n’est pas dans la liste elle-même mais dans ses changements : un port nouveau qui n’existait pas hier est un signal court et très parlant. C’est exactement ainsi qu’il faut la regarder — en instantané avec historique, et non comme une sortie de ss reconstituée de mémoire. La page de démonstration ci-dessous montre précisément cela.