ss
Réflexe moderneInventaire rapide des sockets TCP/UDP, connexions et ports en écoute.
À privilégier pour un diagnostic courant sur serveur Linux récent.
Informatique
Un serveur Linux peut paraître sain tant que l’application répond et que la supervision reste verte. Pourtant, un simple service lancé sur la mauvaise interface peut suffire à exposer une base interne, une console d’administration ou un composant de test oublié. Identifier les ports ouverts sous Linux n’est donc pas une curiosité d’administrateur : c’est une vérification de base avant mise en production, migration, durcissement ou reprise d’un serveur existant.
La bonne méthode tient en trois questions : quel port écoute, quel processus le tient et sur quelle adresse locale il est disponible. Les commandes ss, lsof et netstat couvrent ce besoin, mais elles n’ont pas le même rôle. L’objectif n’est pas de toutes réciter : il faut savoir laquelle lancer, comment lire sa sortie, puis quoi décider sans casser un service utile.
C’est ce niveau de décision qui transforme une commande terminal en vraie mesure de sécurité, utile aussi en astreinte.
Le réflexe est simple : commencez large avec ss, puis filtrez seulement lorsqu’un service mérite enquête.
Sur une distribution actuelle, commencez par ss et conservez la sortie dans le ticket d’audit. La commande est rapide, largement disponible via iproute2, et donne une vue claire des sockets TCP et UDP. Pour un premier audit des services en écoute, la base est simple :
sudo ss -tulpen
Cette commande liste les sockets TCP (-t) et UDP (-u), limite la sortie aux ports en écoute (-l), affiche les ports en numérique (-n), ajoute le processus quand les droits le permettent (-p) et inclut des informations étendues (-e). En pratique, c’est le meilleur compromis entre rapidité de diagnostic et précision exploitable.
Pour limiter l’audit aux ports TCP, utilisez cette variante :
sudo ss -ltnp
Pour l’UDP, gardez une commande séparée :
sudo ss -lunp
La différence est importante. TCP affiche un état LISTEN explicite. UDP, lui, ne fonctionne pas avec la même notion de connexion persistante ; selon les versions et options, vous verrez plutôt des lignes actives, des sockets UDP ouvertes ou des états différents. Ne cherchez donc pas toujours le même mot-clé : cherchez surtout l’adresse locale, le port et le programme associé.
Avant le numéro de port, regardez l’adresse locale. C’est elle qui révèle le périmètre réel d’écoute sur le serveur.
La colonne décisive est souvent la plus discrète : l’adresse locale indique où le service écoute réellement. Deux lignes avec le même port peuvent représenter deux niveaux de risque très différents. Un service lié à 127.0.0.1:5432 écoute seulement sur la boucle locale IPv4 ; il est destiné à être joint depuis la machine elle-même. Un service en 0.0.0.0:5432, lui, écoute sur toutes les interfaces IPv4 disponibles. Ce n’est pas automatiquement une faille, mais c’est une exposition à justifier.
Le même raisonnement vaut pour IPv6. Une ligne en [::]:443 peut indiquer une écoute sur toutes les interfaces IPv6. Dans certains environnements, l’IPv6 est activé par défaut alors que les procédures internes ne le mentionnent pas. C’est un cas classique de décalage entre le runbook et la réalité du serveur.
Dans un audit sérieux, notez aussi la différence entre écoute applicative et accessibilité réseau. Une commande locale vous dit que le service écoute sur la machine, mais elle ne prouve pas qu’un poste externe peut réellement l’atteindre : le trafic peut être filtré par nftables, iptables, firewalld, un security group cloud ou un pare-feu amont. Cette nuance évite les conclusions trop rapides, notamment sur les serveurs où plusieurs équipes se partagent l’exploitation.
| Adresse locale | Lecture opérationnelle | Action recommandée |
|---|---|---|
127.0.0.1:PORT |
Service accessible uniquement depuis la machine en IPv4. | Vérifier les dépendances locales, proxys et tunnels éventuels. |
0.0.0.0:PORT |
Service lié à toutes les interfaces IPv4. | Contrôler pare-feu, besoin métier et authentification. |
[::]:PORT |
Écoute IPv6 large, parfois oubliée dans les audits. | Valider la politique IPv6 et les règles firewall associées. |
192.168.x.x:PORT |
Service limité à une interface privée précise. | Confirmer le segment réseau et les machines autorisées. |
Cette lecture évite deux erreurs fréquentes : paniquer devant un port local parfaitement normal, ou banaliser un service réellement exposé. Dans une PME, la bonne question est rarement “ce port existe-t-il ?”. Elle est plutôt : qui doit pouvoir l’atteindre, depuis quel réseau, et pour quelle raison documentée ?
Pour approfondir ce point, consultez Bien gérer sources.list sous Debian sans casser, qui traite plus précisément de bien gérer sources.list sous debian sans casser apt.
Le port ouvert n’est qu’un symptôme ; la décision dépend toujours du contexte. Une interface d’administration liée à localhost derrière un reverse proxy peut être saine. La même interface exposée directement sur Internet devient un risque immédiat, même si le numéro de port semble banal.
Cette distinction doit rester visible dans le ticket, pas seulement dans la tête de l’administrateur qui a lancé la commande.
Quand le port est suspect, cherchez d’abord son propriétaire. Sans PID fiable, la décision reste trop fragile pour une production.
Ici, le sujet n’est plus seulement le port : c’est le responsable. lsof signifie “list open files”. Le nom peut surprendre, mais sous Linux les sockets réseau sont aussi manipulées comme des fichiers ouverts. C’est précisément ce qui rend l’outil utile : il relie un port à un processus, à un PID, à un utilisateur et parfois à un descripteur. Quand une ligne ss ne suffit pas à décider, lsof apporte souvent le contexte manquant.
sudo lsof -nP -iTCP -sTCP:LISTEN
Les options -nP évitent les résolutions DNS et la traduction des ports en noms de services. C’est plus rapide et moins ambigu : vous voyez 22, 80, 443 ou 5432 directement. Le filtre -iTCP -sTCP:LISTEN limite l’affichage aux ports TCP en écoute.
Pour cibler un port précis :
sudo lsof -nP -i:8080
Cette commande répond à une question simple : quel processus occupe ce port ? Elle est utile après un déploiement qui échoue parce que le port est déjà pris, après une migration Apache/Nginx, ou lorsqu’un service de test reste actif après recette. Le PID récupéré permet ensuite de remonter au service systemd, au conteneur ou au script de lancement.
Sur un serveur avec conteneurs, la lecture demande un cran de prudence. Le processus visible peut être un proxy, un runtime ou un service lancé par l’orchestrateur, pas forcément l’application métier elle-même. Dans ce cas, complétez avec systemctl status, docker ps, podman ps ou la documentation de déploiement. L’objectif reste le même : rattacher le port à un propriétaire opérationnel.
Les trois commandes ne répondent pas exactement au même besoin. En production, le choix dépend surtout de la distribution, du niveau de détail attendu et du temps disponible.
Inventaire rapide des sockets TCP/UDP, connexions et ports en écoute.
À privilégier pour un diagnostic courant sur serveur Linux récent.
Association port, PID, utilisateur et fichier/socket ouverte.
Très utile quand il faut comprendre qui tient réellement le port.
Lecture familière sur anciens serveurs ou procédures historiques.
À garder pour les environnements legacy, pas comme standard unique.
Le standard d’exploitation doit rester simple : une commande principale, une commande de confirmation, puis une décision assumée par l’équipe.
Netstat reste un outil de compatibilité. Il aide encore, mais il ne doit plus piloter seul un runbook Linux moderne.
netstat reste très connu, et beaucoup de procédures internes l’utilisent encore. Sur des serveurs anciens, il peut être l’outil disponible immédiatement. Mais sur des distributions modernes, il dépend souvent du paquet net-tools, alors que ss est devenu la voie la plus naturelle pour inspecter les sockets. La bonne posture consiste à savoir le lire, sans bâtir toute la procédure d’audit autour de lui.
sudo netstat -tulnp
Les options sont proches de l’intention vue avec ss : TCP, UDP, sockets en écoute, affichage numérique et programme associé. Là encore, sudo est important. Sans privilèges, la colonne programme/PID peut être incomplète, ce qui crée une fausse impression de port “orphelin”.
Netstat devient surtout pertinent dans trois cas : un serveur ancien où les procédures sont déjà validées, un dépannage avec un prestataire qui parle encore ce vocabulaire, ou une comparaison ponctuelle pour confirmer une lecture. Pour un nouveau runbook, mieux vaut écrire la procédure principale avec ss en première commande, puis mentionner netstat comme alternative de compatibilité.
Si vous maintenez un parc mixte, évitez les procédures qui supposent que tous les serveurs ont les mêmes paquets installés. Indiquez clairement la commande cible, puis l’alternative legacy. Cette petite discipline limite les erreurs lors d’une astreinte, surtout quand l’intervenant doit diagnostiquer vite un serveur qu’il ne connaît pas encore.
À ce stade, l’audit change de nature. On passe d’une observation technique à une décision d’exploitation vraiment documentée.
Un inventaire brut n’a pas beaucoup de valeur si personne ne tranche ensuite. Après la commande, classez chaque port dans une catégorie claire : attendu et documenté, attendu mais trop exposé, inconnu à investiguer, ou obsolète à retirer. Cette étape évite que l’audit finisse dans un fichier texte oublié.
Un audit fiable ne s’arrête pas à “le port 443 est ouvert”. Il faut relier la ligne à un service, une interface réseau et une décision d’exploitation.
Le service écoute-t-il sur 127.0.0.1, une IP privée, 0.0.0.0 ou :: ?
Impact décision : C’est le critère qui indique si le service est local, interne ou potentiellement joignable depuis plusieurs interfaces.
La ligne concerne-t-elle TCP, UDP, IPv4 ou IPv6 ?
Impact décision : Un service peut être fermé en IPv4 mais encore visible en IPv6, ou répondre en UDP sans état LISTEN classique.
Quel processus tient le port et sous quel compte s’exécute-t-il ?
Impact décision : Sans PID, impossible de décider proprement entre arrêt, reconfiguration, documentation ou investigation sécurité.
Le port est-il prévu dans l’architecture, le runbook ou la supervision ?
Impact décision : Un port inconnu n’est pas toujours malveillant, mais il ne doit jamais rester sans propriétaire.
Sur un serveur applicatif classique, le port 22 pour SSH, 80/443 pour HTTP(S) ou 9100 pour certains exports de métriques peuvent être normaux. Le problème apparaît quand un service d’administration, une base de données ou une interface de debug écoute sur toutes les interfaces sans justification. Le signal faible n’est pas le port en lui-même : c’est l’absence de propriétaire clair.
Le bon réflexe consiste aussi à croiser les niveaux. Un service peut écouter sur 0.0.0.0 mais être correctement filtré par le pare-feu local et le pare-feu réseau. À l’inverse, un service que vous pensez interne peut être exposé via NAT, proxy, conteneur ou règle cloud. L’audit de ports ne remplace pas le test depuis une autre machine autorisée.
La décision doit donc combiner trois preuves : la sortie de commande, la règle de filtrage et le test réseau. Si l’une manque, documentez l’incertitude au lieu de marquer le point comme clos. C’est souvent là que les écarts de sécurité persistent : chacun pense que l’autre couche protège déjà le service.
Dans la seconde partie de l’audit, ces deux lectures évitent les décisions trop rapides.
ss ou lsof aide à relier le port au processus, mais il faut encore confirmer le service, le conteneur ou le runbook associé.
127.0.0.1 à 0.0.0.0 et :: ne racontent pas la même histoire réseau. C’est souvent la différence entre service interne et surface exposée.
Premier cas : le port est déjà occupé. Une application Node.js ou Python refuse de démarrer sur 3000 ou 8000. Lancez sudo lsof -nP -i:3000, identifiez le PID, puis remontez au service. Si le processus appartient à une ancienne recette, arrêtez-le proprement via systemd, le superviseur applicatif ou l’orchestrateur concerné.
Deuxième cas : une base écoute trop largement. PostgreSQL, MySQL ou Redis peut apparaître en 0.0.0.0. Ce n’est acceptable que si l’architecture le prévoit et si le filtrage est strict. Sinon, la correction passe par la configuration du service, par exemple une adresse d’écoute limitée, puis par un redémarrage contrôlé et un nouveau test avec ss.
Troisième cas : IPv6 n’est pas dans la procédure. Vous voyez [::]:80 ou [::]:443, alors que le runbook ne mentionne que l’IPv4. Ne concluez pas que c’est grave par défaut. Vérifiez simplement si l’IPv6 est activé, filtré, supervisé et assumé. Une infrastructure moderne peut l’utiliser correctement ; une infrastructure oubliée peut l’exposer sans le savoir.
Quatrième cas : le port appartient à la supervision. Un exporteur de métriques ou un agent de monitoring peut écouter localement ou sur une interface privée. Il ne faut pas le supprimer par réflexe. En revanche, il doit avoir une règle claire : accès limité aux collecteurs, version maintenue, authentification si nécessaire, et documentation dans l’inventaire serveur.
Une bonne automatisation doit réduire le doute, pas produire un bruit d’alertes que l’équipe finira par ignorer en astreinte.
Automatiser l’inventaire est utile, surtout après patch, redémarrage, migration ou changement de firewall. Une commande planifiée peut produire un état régulier des ports en écoute et signaler les différences. Mais une automatisation naïve qui alerte sur chaque variation finit vite ignorée. Le plus utile est de comparer la sortie à une liste de ports attendus par serveur ou par rôle.
sudo ss -tulpen > /var/tmp/ports-$(hostname)-$(date +%F).txt
Pour aller plus loin, exportez les résultats dans votre outil de supervision, votre CMDB ou votre dépôt d’exploitation. L’objectif n’est pas de créer un script complexe, mais de garder une trace lisible : quelle machine, quelle date, quels ports, quel propriétaire, quelle décision. En audit interne, cette preuve simple vaut souvent mieux qu’un tableau trop ambitieux que personne ne maintient.
La surveillance doit rester proportionnée. Un poste de développement, un serveur de recette et une machine exposée sur Internet n’ont pas le même niveau d’exigence. Sur un serveur public, chaque nouvelle écoute doit déclencher une vérification. Sur un serveur interne contrôlé, la priorité peut être la documentation et la cohérence avec l’inventaire applicatif.
Pour éviter le bruit, définissez une base attendue par rôle : frontal web, base de données, serveur de fichiers, bastion, worker applicatif. Une variation sur un frontal exposé n’a pas le même poids qu’une variation sur une machine de recette isolée. Le runbook doit donc préciser le seuil d’alerte, pas seulement la commande à exécuter.
Le vrai gain est là : moins de ports “surpris”, moins de décisions improvisées, et une reprise plus calme.
À utiliser après l’inventaire, avant toute modification de firewall ou de configuration applicative.
Pour une PME, la meilleure procédure tient sur une page. Utilisez ss comme commande principale, lsof pour relier les ports aux processus, et netstat seulement si un ancien serveur ou un prestataire l’exige. Classez ensuite les résultats par service métier plutôt que par numéro de port. Cette approche parle autant à l’équipe IT qu’au dirigeant qui veut comprendre le risque réel.
La priorité n’est pas de fermer le plus de ports possible. Elle est de réduire les expositions inutiles, de garder les services nécessaires visibles uniquement au bon endroit, et de documenter les exceptions. Un serveur bien tenu n’est pas un serveur sans port ouvert : c’est un serveur où chaque port a un rôle, un propriétaire et une règle de filtrage cohérente.
Si vous ne devez lancer qu’une action après cet article, choisissez un serveur critique et produisez son inventaire avec sudo ss -tulpen. Comparez ensuite chaque ligne au runbook. Tout ce qui n’a pas de justification devient une tâche : expliquer, limiter, filtrer ou retirer.
Ajouter un utilisateur sudo sous Linux sans permet de retrouver les points pratiques liés à ajouter un utilisateur sudo sous linux sans ouvrir trop de droits.
À lire aussi