Vérifier si un port est ouvert sous Linux
Utilisez ss pour voir ce qui écoute, puis nc ou nmap depuis l’extérieur. Un port bloqué expire, tandis qu’un port fermé refuse immédiatement la connexion.
Vérifier si un port est ouvert sous Linux : commencez par définir la bonne question
Pour vérifier si un port est ouvert sous Linux, définissez d’abord la question que vous posez. Le terme « ouvert » n’a pas le même sens selon l’endroit d’où vous effectuez la vérification. Sur le serveur lui-même, un port est ouvert lorsqu’un processus est lié à ce port et attend des connexions. Depuis une autre machine, un port est ouvert lorsqu’un paquet atteint ce processus et qu’une réponse revient. Lorsqu’aucune réponse ne revient, la vraie question est de savoir quel équipement a supprimé le paquet. sudo ss -ltnp répond à la première question. nc -z ou nmap répondent à la deuxième. Les compteurs du pare-feu et tcpdump répondent à la troisième.
Utiliser le mauvais contrôle peut vous faire perdre une après-midi. Un test exécuté sur le serveur ne traverse jamais le pare-feu réseau de votre fournisseur, car ce filtre se trouve en dehors du serveur. Si les numéros de port ne vous sont pas encore familiers, comment fonctionnent les ports et les sockets sous Linux présente le modèle utilisé dans la suite de ce guide.
Qu’est-ce qui est en écoute sur cette machine ? Lisez la sortie de ss
ss est fourni avec iproute2. Il est donc présent sur toutes les distributions actuelles. netstat provient de net-tools, qu’Ubuntu n’installe plus par défaut depuis des années. netstat -tulpn donne donc souvent netstat: command not found. Apprenez ss et évitez cette déception.
sudo ss -ltnp-l affiche uniquement les sockets en écoute. -t limite la liste à TCP. -n affiche les numéros au lieu de résoudre les noms. La commande renvoie donc immédiatement son résultat. -p indique le processus propriétaire et nécessite root : sans sudo, la colonne Process est vide pour les processus que vous ne possédez pas. Remplacez -t par -u pour afficher UDP.
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=612,fd=14))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=921,fd=3))
LISTEN 0 511 127.0.0.1:8080 0.0.0.0:* users:(("node",pid=1442,fd=19))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=921,fd=4))La colonne Local Address détermine tout. C’est pourtant celle que l’on parcourt souvent trop rapidement.
0.0.0.0:22signifie que toutes les adresses IPv4 de la machine sont concernées. Le service est donc joignable depuis l’extérieur si le firewall l’autorise.[::]:22correspond à la même situation pour IPv6.127.0.0.1:8080signifie que le service est accessible uniquement via loopback. Rien à l’extérieur de cette machine ne peut le joindre.10.20.0.5:5432signifie qu’une seule adresse d’interface est utilisée, à l’exclusion des autres. C’est courant dans les configurations de réseaux privés.- Une colonne Process vide indique généralement l’absence de
sudo, et non l’absence de processus.
Pour vérifier un port précis, filtrez directement dans ss au lieu d’utiliser grep sur toute la liste :
sudo ss -ltnp 'sport = :8080'
sudo lsof -nP -iTCP:8080 -sTCP:LISTEN
sudo fuser 8080/tcpUne sortie vide avec les trois commandes signifie qu’aucun processus n’utilise ce port. Le service est arrêté, son démarrage a échoué ou il est en écoute ailleurs. Consultez systemctl status <unit> et journalctl -u <unit> -n 50 avant de modifier la moindre règle du firewall.
Pourquoi 127.0.0.1 dans Local Address peut vous faire perdre un après-midi
Un socket lié à 127.0.0.1 n’est pas accessible depuis un autre hôte, et aucune règle de pare-feu ne peut changer cela. Le noyau route 127.0.0.0/8 uniquement vers l’interface loopback. Un paquet portant cette adresse de destination et arrivant sur une véritable carte réseau est rejeté comme paquet martien. Le processus s’exécute donc, ss indique qu’il est en écoute, ufw allow 8080 signale une réussite, mais la connexion depuis votre ordinateur portable échoue toujours. Elle échoue avec un Connection refused immédiat, car le paquet atteint votre adresse publique, ne trouve aucun socket lié à cette adresse, puis le noyau répond par un reset TCP.
De nombreux programmes se lient volontairement à loopback. Pour une base de données ou une interface d’administration, c’est le comportement par défaut approprié. Vous avez deux choix corrects. Modifiez l’adresse d’écoute dans la configuration du programme (listen_addresses dans postgresql.conf, bind dans redis.conf ou l’argument d’hôte accepté par votre application), puis ouvrez le pare-feu. Ou laissez le service sur loopback et accédez-y par un autre moyen, par exemple avec un reverse proxy nginx ou un tunnel SSH depuis votre ordinateur portable :
ssh -L 8080:127.0.0.1:8080 user@203.0.113.10Docker applique la même distinction dans son option de publication de ports. -p 8080:8080 se lie à 0.0.0.0 et expose le conteneur sur Internet. -p 127.0.0.1:8080:8080 se lie à loopback et le garde accessible uniquement en local.
Comment vérifier depuis une autre machine si un port est ouvert sous Linux
Effectuez ce test depuis un autre réseau. Un test depuis le serveur prouve seulement que le chemin loopback fonctionne. Même une connexion à votre propre adresse IP publique depuis le serveur contourne le firewall réseau de votre fournisseur, car ce filtrage s’effectue en dehors du VPS.
nc -zv -w 3 203.0.113.10 443-z se connecte, puis ferme la connexion sans envoyer de données. -w 3 abandonne après trois secondes, et ce flag est important : sans timeout, un paquet perdu laisse le client retenter le SYN pendant plus de deux minutes avant que le kernel n’arrête les tentatives. En cas de succès, vous obtenez ceci :
Connection to 203.0.113.10 443 port [tcp/https] succeeded!Si l’outil est absent (nc: command not found), installez netcat-openbsd sur Debian ou Ubuntu, ou utilisez la redirection réseau intégrée de bash, qui ne nécessite aucun package :
timeout 3 bash -c '</dev/tcp/203.0.113.10/443' && echo open || echo "no answer"Cette syntaxe est une fonctionnalité de bash. Exécutez-la donc avec bash. /bin/sh sur Debian et Ubuntu est dash, qui ne prend pas en charge /dev/tcp et indique que le chemin n’existe pas. Pour une plage de ports, ou si vous voulez que l’état soit indiqué explicitement, utilisez nmap sur les hôtes dont vous êtes responsable :
sudo nmap -Pn -p 22,80,443 203.0.113.10
sudo nmap -Pn -p 1-1024 203.0.113.10-Pn désactive la découverte des hôtes. La plupart des hébergeurs de VPS bloquent les requêtes ICMP echo. Sans -Pn, nmap considère donc que l’hôte est arrêté et n’effectue aucun scan. nmap affiche open lorsqu’un élément répond et accepte la connexion, closed lorsqu’un élément répond avec un reset, et filtered lorsqu’aucun élément ne répond. Pour un service web, curl -sS -o /dev/null -w '%{http_code}\n' https://example.com permet de distinguer un problème réseau d’un problème applicatif, car un code d’état prouve que l’ensemble du chemin fonctionne.
Pourquoi un port bloqué attend et un port fermé refuse immédiatement
Un refus immédiat. Le paquet a atteint la machine et un élément y a répondu.
nc: connect to 203.0.113.10 port 443 (tcp) failed: Connection refusedDeux causes différentes produisent exactement ce résultat. Soit aucun processus n’est lié à cette adresse et à ce port : le kernel a alors répondu avec un TCP reset. Soit une règle de firewall a rejeté le paquet avec un reset ou un message ICMP port unreachable. Un refus est une réponse définitive qui revient en un aller-retour.
Une pause, puis un timeout. Un élément a supprimé le paquet sans rien renvoyer.
nc: connect to 203.0.113.10 port 443 (tcp) timed out: Operation now in progressC’est ce que fait une règle DROP, tout comme un firewall du fournisseur ou un cloud security group. Le silence caractérise un drop, car l’émetteur ne peut pas distinguer un paquet supprimé d’un hôte hors service.
Le symptôme indique où chercher ensuite. Un refus signifie que les paquets traversent correctement le réseau : revenez donc à ss -ltnp et vérifiez l’adresse d’écoute et le numéro de port. Un timeout signifie que les paquets sont supprimés : examinez les firewalls de l’extérieur vers l’intérieur. refus ou timeout avec SSH examine la même distinction pour le port 22, qui est le cas le plus courant.
ufw propose volontairement ces deux comportements : ufw deny 8080 supprime le paquet et ufw reject 8080 envoie un rejet. Dans nftables, les deux targets sont drop et reject ; dans iptables, ce sont -j DROP et -j REJECT. Les policies par défaut sont presque toujours configurées sur un drop. C’est pourquoi une règle manquante provoque une attente prolongée plutôt qu’un message d’erreur.
Qui bloque le port ? Procédez de l’extérieur vers l’intérieur
sudo ufw status verbose
sudo iptables -L INPUT -n -v --line-numbers
sudo nft list rulesetLes compteurs -v sont la partie utile. Exécutez votre test nc depuis l’extérieur, relancez la commande iptables et cherchez le compteur qui a évolué : la règle dont le nombre de paquets augmente est celle qui traite votre trafic. Vous remplacez ainsi les suppositions par des faits.
Le test décisif s’exécute sur le serveur et surveille le trafic réseau pendant que vous vous connectez depuis l’extérieur :
sudo tcpdump -ni any tcp port 8080Un SYN reçu sans SYN-ACK en retour signifie que le paquet a atteint votre VPS et que l’hôte l’a rejeté. Le pare-feu du fournisseur fonctionne donc correctement, contrairement à vos règles locales. L’absence totale de sortie signifie que le paquet n’est jamais arrivé. La cause est alors le pare-feu du fournisseur, un groupe de sécurité ou une adresse IP incorrecte. Cette distinction suffit à éliminer la plupart des vérifications.
Deux couches peuvent produire des résultats apparemment impossibles. Premièrement, IPv6 : si le nom d’hôte possède un enregistrement AAAA, votre client peut se connecter en IPv6 alors que votre règle ne couvre que l’IPv4. Testez donc chaque famille avec nc -4 et nc -6 avant de vous fier à l’un ou l’autre résultat. règles ufw et ports IPv6 sur un VPS explique ce problème de correspondance. Deuxièmement, Docker : un port de conteneur publié répond depuis Internet alors que ufw status indique que ce port est refusé, car ces paquets sont traités avant même d’atteindre la chaîne de ufw. pourquoi Docker publie des ports en contournant ufw présente le fonctionnement et le correctif, tandis que les règles ufw à définir sur un nouveau VPS constitue la base recommandée.
Pourquoi les réponses UDP sont ambiguës par conception
UDP n’effectue pas de handshake. Une sonde n’a donc rien qui puisse réussir. nc -zu 203.0.113.10 53 retourne 0 dès que le paquet est envoyé, ce qui prouve seulement que votre machine l’a envoyé et ne prouve rien sur l’extrémité distante. Lorsqu’un port UDP est fermé, l’hôte renvoie normalement un message ICMP « port unreachable ». Le kernel ne transmet cette erreur à un socket connecté qu’à l’écriture suivante. Une sonde constituée d’un seul paquet ne la détecte donc pas. Les firewalls bloquent généralement ICMP, ce qui supprime même cet indice. C’est pourquoi nmap affiche open|filtered pour la plupart des ports UDP : l’absence de réponse est exactement le comportement d’un service ouvert mais silencieux et d’un port filtré.
Testez UDP en utilisant le protocole concerné. Un serveur DNS répond à dig +short @203.0.113.10 example.com avec une adresse ou ne renvoie rien. Un pair WireGuard affiche une ligne latest handshake récente dans sudo wg show. Vérifiez ensuite l’arrivée des paquets côté serveur :
sudo tcpdump -ni any udp port 51820Si des paquets apparaissent pendant l’envoi côté client, ils arrivent bien au serveur. Le problème se situe alors au niveau du service ou de la chaîne d’entrée. Si aucun paquet n’apparaît, ils ne sont jamais arrivés.
Une checklist dans l’ordre qui permet de trouver la cause le plus rapidement
- Sur le serveur, exécutez
sudo ss -ltnp 'sport = :8080'. L’absence de sortie signifie qu’aucun processus n’écoute. Corrigez d’abord le service. - Si la commande renvoie une sortie, consultez la colonne Local Address.
127.0.0.1signifie qu’un accès externe est impossible tant que vous ne liez pas le service à la bonne adresse ou ne placez pas un proxy devant lui. - Depuis un autre réseau, exécutez
nc -zv -w 3 <public ip> 8080. - Un refus vous renvoie à l’étape 1. L’adresse, le port ou la machine n’est pas celui ou celle que vous pensez.
- Un délai d’attente indique que les paquets sont abandonnés. Lancez
sudo tcpdump -ni any tcp port 8080sur le serveur, puis répétez le test. - Le paquet SYN arrive, mais aucune réponse ne repart : le pare-feu de l’hôte est en cause. Recherchez la règle dont le compteur augmente dans
sudo iptables -L INPUT -n -v. - Aucun paquet SYN n’arrive : le pare-feu du fournisseur, un security group ou une mauvaise adresse IP est en cause.
FAQ
Comment vérifier les ports ouverts sur mon propre serveur Linux ?
Exécutez sudo ss -ltnp pour TCP et sudo ss -lunp pour UDP. Chaque ligne correspond à un socket en écoute. La colonne Local Address indique qui peut l’atteindre : 0.0.0.0 et [::] acceptent les connexions depuis toute adresse autorisée par le firewall, tandis que 127.0.0.1 n’accepte que les connexions provenant de la machine elle-même. La colonne Process nécessite les privilèges root. Exécutez donc la commande avec sudo, sinon cette colonne reste vide. ss fait partie d’iproute2 et est toujours installé. netstat fait partie de net-tools et n’est généralement pas installé.
Pourquoi ss indique-t-il que mon service est en écoute alors que je ne peux toujours pas me connecter ?
Deux causes sont fréquentes, et une commande permet de les distinguer. Si Local Address vaut 127.0.0.1, le service est lié à loopback et est inaccessible depuis un autre hôte, car le kernel ne route cette plage que vers l’interface loopback. Si la valeur est 0.0.0.0 et que les connexions échouent toujours, exécutez sudo tcpdump -ni any tcp port <port> sur le serveur, puis connectez-vous depuis l’extérieur. Un paquet SYN reçu sans réponse indique qu’une règle du firewall local le bloque. Si aucun paquet n’arrive, il est bloqué avant votre VPS, généralement par le firewall du fournisseur ou par un security group.
Quelle est la différence entre une connexion refusée et une connexion qui expire ?
Un refus est une réponse. Le paquet a atteint l’hôte, qui a renvoyé un reset TCP ou un message ICMP port unreachable. Cela signifie que rien n’écoute sur cette adresse et ce port, ou qu’une règle a rejeté la connexion. Un timeout correspond à un silence : une règle a supprimé le paquet sans rien envoyer en retour, et votre client réessaie jusqu’à l’expiration du délai. Un refus vous oriente vers le service et son adresse d’écoute. Un timeout vous oriente vers un firewall. Commencez par vérifier celui qui est le plus proche de l’extérieur.
Comment vérifier si un port UDP est ouvert ?
Vous ne pouvez pas obtenir de réponse fiable par une sonde générique, car UDP n’a pas de handshake et un service silencieux ressemble à un paquet bloqué. nc -zu renvoie un succès dès qu’il envoie le paquet. Pour la même raison, nmap indique open|filtered. Effectuez plutôt un test avec le protocole concerné : dig +short @<host> example.com pour DNS, ou sudo wg show pour un peer WireGuard avec un handshake récent. Pour confirmer que les paquets arrivent, exécutez sudo tcpdump -ni any udp port <port> sur le serveur pendant que le client envoie des paquets.
Puis-je encore utiliser telnet host port pour tester un port ?
Cela fonctionne pour TCP, et Escape character is '^]' indique que la connexion a été acceptée. Quittez-le avec Ctrl+], puis exécutez quit. Deux éléments font de nc -z le meilleur outil : telnet n’est pas installé sur la plupart des images serveur actuelles, et nc accepte un délai d’expiration avec -w et définit un code de retour que vous pouvez tester dans un script. Si aucun des deux outils n’est disponible, timeout 3 bash -c '</dev/tcp/<host>/<port>' ne nécessite l’installation d’aucun paquet.