Alive : où comment tester un port d’un hôte distant

  • Scripts
  • 7 minutes de lecture

Introduction

Quand je crée une VM sur mes infras, parfois j’ouvre un port, et je ne parviens pas à utiliser le service derrière. Les causes peuvent être multiples :

  • Il faut faire un ping sur le serveur, pour être certain que le réseau est correctement configuré,
  • s’y connecter,
  • vérifier que le service est démarré,
  • installer et utiliser netstat pour s’assurer que le port attendu est à l’écoute,
  • vérifier si le pare-feu ne bloque pas,
  • vérifier que fail2ban ne m’a pas bloqué à cause de trop d’essais,
  • parfois vérifier si le port est routé sur mon pfsense…

Bref : c’est long, et en plus, je peux en oublier. C’est pourquoi telnet, par exemple, permet de simplifier la vie. Mais j’ai trouvé que netcat (AKA nc) pouvait simplifier encore le tout, en donnant une logique de répétition façon ping. Je vous partage mon tool ?

Présentation de Netcat

Netcat est un outil en ligne de commande utilisé pour lire et écrire des données sur des connexions réseau à l’aide des protocoles TCP ou UDP. C’est souvent le « couteau suisse » des outils de réseau pour sa flexibilité et ses nombreux cas d’usage. On est sur une CLI simple mais puissante qui peut être utilisée pour transférer des fichiers entre des machines ou encore créer des serveurs et des clients TCP/UDP simples.

Pour tester si un port TCP est ouvert sur un hôte distant, Netcat peut être utilisé pour tenter de se connecter à ce port. Si la connexion est établie, cela signifie que le port est accessible pour votre IP.

Utilisation de Netcat pour tester un port TCP

Pour tester si un port TCP est ouvert sur un hôte distant, vous pouvez utiliser la commande suivante :

nc -z <hôte> <port>
  • -z : Indique à Netcat de scanner sans envoyer de données.
  • <hôte> : L’adresse IP ou le nom de domaine de l’hôte a tester.
  • <port> : Le numéro de port à tester.

Exemples :

testons le port HTTPS (443) du blog :

$ nc -z blog.talma.cloud 443
Connection to blog.talma.cloud (212.83.143.1) 443 port [tcp/https] succeeded!

Mais si on teste un port qui n’est pas ouvert :

$ nc -z blog.talma.cloud 21

🧌 Rien ne se passe.
🤓 Hé non ! En réalité, Netcat essaie de joindre le port FTP (21), mais ce dernier ne répond pas, et la commande nc attend. Alors en soi, c’est une réponse acceptable, mais j’ai parlé de faire un outil qui répond comme un ping, il faut donc sortir de cet état, et pour ça il existe le paramètre « timeout », qui définit combien de temps nc doit attendre avant de conclure que le port n’est pas joignable.

$ nc -w 1 -z blog.talma.cloud 21

$

🧌 Ok ! mais il ne se passe toujours rien. On a seulement récupéré l’invite de commande !
🤓 Pas exactement. nc a quitté après 1 seconde, et quand un logiciel se termine, il « meurt » avec un code de sortie. Ce code vaut 0 si tout va bien, et une autre valeur sinon. Dans notre cas, reprenons ces exemples et vérifions le code de sortie (aussi appelé exit code) :

$ nc -z blog.talma.cloud 443
Connection to blog.talma.cloud (212.83.143.1) 443 port [tcp/https] succeeded!

$ echo $?
0

$ nc -w 1 -z blog.talma.cloud 21

$ echo $?
1

Si le port n’est pas accessible, on a un exit code (dans la variable $?) qui vaut 1. C’est tout ce qu’il nous faut !

alive : un script bash pour tester un port

Voici donc un script bash commenté dans lequel on va jouer en boucle la commande vue précédemment. Pour chaque essai, on va afficher si l’hôte distant est joignable sur le port défini.

#!/bin/bash

# Vérifie si les arguments nécessaires sont fournis. Si aucun port n'est défini, je choisis de tester le port SSH (22).
if [ -z "$1" ]; then
        # Si l'hôte n'est pas défini, j'affiche un message et un mode d'emploi, puis je quitte avec le code de sortie "1"
        echo "Aucun hôte défini"
        echo "Usage : alive <host>"
        echo "<host> : IPv4 | IPv6 | Hostname"
        echo "<port> : port 22 par défaut (Optionnel)"
        exit 1
else
        # Si l'hôte est défini, je poursuis
        REMOTEHOST=$1
        TIMEOUT=3

        if [ -z "$2" ]; then
                REMOTEPORT=22
        else
                REMOTEPORT=$2
        fi
fi

# Mise en place de colorisation des retours du terminal. C'est facultatif mais rend l'outil bien plus visuel.
Red='\033[0;31m'
Green='\033[0;32m'
Cyan='\033[0;36m'
Disable_Color='\033[0m'

# Boucler à l'infini sur le test
while [[ true ]]; do
        # Ajout d'un indicateur temporel
        LASTDATE=$(date +"%H:%M:%S")
        # Tester le code de sortie de la commande netcat. "&> /dev/null" permet de ne pas afficher les retours de netcat ; on va faire nos propres retours.
        if $(nc -w $TIMEOUT -z $REMOTEHOST $REMOTEPORT &> /dev/null ); then
                # Si l'hôte est joignable sur le port, on le dit en vert
                printf "${Cyan}[${LASTDATE}] ${Green} ${REMOTEHOST} est joignable sur le port ${REMOTEPORT}"
        else
                # Si le port n'est pas joignable sur l'hôte distant, on le dit en rouge
                printf "${Cyan}[${LASTDATE}] ${Red} ${REMOTEHOST} n'est pas joignable sur le port ${REMOTEPORT}"
        fi
        # Ne pas oublier de désactiver la couleur. Puis attendre 1 seconde et recommencer
        printf "${Disable_Color} \n"
        sleep 1
done

exit 0

Utilisation du script

Pour utiliser ce script, enregistrez-le dans un fichier, par exemple alive.sh, et rendez-le exécutable :

chmod +x alive.sh

Dans le doute, installez netcat 🤓 sans ça, ça ne fonctionnera pas (mais il est probable que vous l’ayez déjà de base) :

sudo apt install netcat-openbsd

Ensuite, vous pouvez exécuter le script en fournissant l’adresse IP ou le nom de domaine de l’hôte et le numéro de port à tester :

./alive.sh <hôte> <port>

Je déplace le script dans un dossier où je n’aurais pas besoin de me rendre (et que je n’ai pas besoin de citer en lançant la commande) :

sudo mv alive.sh /usr/local/bin/alive

Du coup, quand vous voulez faire un nouveau serveur web par exemple, commencez par faire :

alive monsite.com 80

Puis installez votre serveur, mettez en place le routage, le pare-feu, le pointage DNS, installez votre serveur web (nginx, apache, tomcat…) et à un moment, comme par magie, vous allez voir ceci :

[13:58:19]  monsite.com n'est pas joignable sur le port 80 
[13:58:20]  monsite.com n'est pas joignable sur le port 80 
[13:58:21]  monsite.com n'est pas joignable sur le port 80 
[13:58:22]  monsite.com est joignable sur le port 80 
[13:58:23]  monsite.com est joignable sur le port 80 
[13:58:24]  monsite.com est joignable sur le port 80

Autres cas d’usage

J’utilise aussi alive quand je dois couper (ou redémarrer) un serveur critique (genre un SPOF) en testant le port du service. C’est vrai que j’ai toujours une sonde zabbix pas loin, mais là on est précis à la seconde près ! C’est toujours sympa de se dire qu’on a dû faire une coupure de service mais qu’elle n’a duré que 5 secondes, preuve à l’appui !

Lors du reboot d’un serveur bare metal (ou dédié comme disent les vieux 😛), on le sait : l’EFI (le BIOS papi !) fait bien plus de tests que sur un PC, et ça peut prendre 5 minutes. Mes serveurs ne répondent généralement pas au ping, alors j’utilise alive sur le port SSH. Dès que c’est vert, je sais que je peux m’y connecter. Selon les modèles, j’ai aussi mes petites stats perso sur le temps de reboot pour ne plus m’inquiéter à chaque fois.

Enfin, alive c’est aussi un script à placer sur vos templates de VM ! Moi, quand je vois qu’un serveur est « alive » depuis un serveur A, mais qu’il ne répond pas à mon serveur B, j’en déduis que le serveur n’a pas de soucis, et que c’est probablement une histoire de réseau ou de pare-feu.

D’autres usages sont probablement possibles (et j’en oublie certainement). Personnellement, j’utilise alive TOUS les jours depuis plusieurs années. Je l’ai partagé à mes collègues, je le vois régulièrement sur les écrans des copains.

Notez enfin qu’il est possible de tester des ports UDP en ajoutant l’option -u dans les paramètres comme suit :

nc -w $TIMEOUT -z $REMOTEHOST -u $REMOTEPORT