Guillaume Fenollar DevOps et SysAdmin Freelance

Guillaume FENOLLAR

Ingénieur Linux/DevOps Indépendant

− Montpellier −

Socat et Netcat (nc) à la rescousse de l'administrateur réseau

Un binaire vous manque, et tout est dépeuplé. En l'occurence deux. Si je suis sur un serveur en train d'investiguer un souci réseau et que je me retrouve sans netcat ni socat, alors rien ne va plus (ou presque). Si vous n'avez jamais entendu parler d'eux, c'est que vous êtes débutants et que vous êtes tombés au bon endroit pour une introduction si l'administration système vous botte. Commençons.

Les outils qui vont suivre sont les équivalents Unix de Telnet. Sauf que ce dernier est en voie de disparition, alors que Netcat et Socat ont de bons jours devant eux, de par leur utilité. Pour simplifier les choses, nous nous contenterons aujourd’hui de parler que de deux utilisations, celles qui me sont les plus courantes: tester une connectivité réseau vers un port TCP, ou créer des sockets pour communiquer entre des machines, le plus souvent pour envoyer des fichiers au sein d’un réseau local (car la connexion ne sera pas chiffrée).

Avec Netcat

Commençons par NetCat, aussi appelé NC. Le paquet d’installation peut prendre plusieurs noms :

apt install netcat
yum install nc
apk add netcat-openbsd
Les sources peuvent aussi être trouvées (ici)[http://netcat.sourceforge.net/download.php).

Tester l’ouverture d’un port

nc -zv guillaume.fenollar.fr 443
guillaume.fenollar.fr [139.99.159.179] 443 (https) open
L’argument ‘-z’ n’est pas disponible sur toutes les plateformes et est donc optionnel, mais permet de spécifier un test de port, sans transfert de donnée. Le ‘-v’ est la version verbose qui vous fait un retour clair et permet de voir qu’un port est ouvert. Il est également possible de spécifier un range pour scanner une plage de ports :
nc -zv -w 1 guillaume.fenollar.fr 80-443
guillaume.fenollar.fr [139.99.159.179] 443 (https) open
guillaume.fenollar.fr [139.99.159.179] 80 (http) open

Transférer un fichier

Transférer un fichier sans accès SSH est un jeu d’enfant, plus simple que Socat que l’on verra après.

# Ouvrir un port sur la machine distante et rediriger le tout vers un fichier (qui sera écrasé à chaque fois).
# Le port 6789 sera ici utilisé mais il peut-être n'importe lequel >1024 (pour un utilisateur non-root)
nc -l 6789 > fichier.tgz

# Sur l'hôte d'envoi, ouvrir le socket vers la machine de la connexion précédente
nc <IP> 6789 < fichier.tgz
Il est également possible de transférer un dossier entier en utilisant une archive Tar à la volée
# Lecture du fichier tar depuis l'entrée standard
nc -l 6789 | tar -xvf -
# Sur l'hôte d'envoi, utiliser tar pour compression et tout envoyer vers un nouveau socket
tar -cvf - <DOSSIER> | nc <IP> 6789
Ainsi, il est capable de chainer la commande nc avec d’autres commandes tant que celles-ci peuvent écrire/lire vers/depuis une sortie/entrée standard. Il est possible d’utiliser par exemple un dump mysql (mysqldump), ou même un volume de type block (dd) !

Avec Socat

Tester l’ouverture d’un port

SoCat n’est pas exactement fait pour tester un port dans son plus simple appareil (il nécessite deux arguments), mais c’est possible sans trop de difficultés. Ici, pas de retour visuel, mais si le système vous rend la main c’est que c’est mauvais signe (timeout de la connexion après 2 secondes, ou si le port est fermé).

socat - TCP:guillaume.fenollar.fr:443,connect-timeout=2

Transférer un fichier

# On ouvre un socket d'où le contenu reçu sera envoyé vers la sortie standard puis vers un fichier
socat TCP-LISTEN:6789 STDOUT > fichier.tgz
# On lit un fichier pour l'envoyer vers le socket créé
cat fichier.tgz | socat - TCP:<IP>:6789
J’utilise ici un fichier plat mais il est bien entendu possible d’utiliser, comme avec Netcat, n’importe quelle commande envoyant des données vers le pipe.

Tester un port sans aucun des deux

Si ces deux couteaux suisses ne sont pas installés ni installables, alors il vous reste encore l’utilisation de curl ou wget ou même d’une commande bash pour tester sa connectivité réseau.

curl

Si la commande reste suspendue, c’est très probablement un firewall qui vous bloque l’accès. Une erreur renvoyée indiquerait plutôt un port fermé, ou un serveur défaillant (port fermé par exemple).

curl -v https://guillaume.fenollar.fr

wget

Même chose que curl, le texte renvoyé vous donne un bon indice si votre connectivité réseau à la cible est up

wget -O - https://guillaume.fenollar.fr

bash

Il est également possible d’ouvrir des sockets sans le moindre outil autre qu’un terminal. Très utile si vous vous retrouvez dans un conteneur Docker réduit au strict minimum type busybox.

Avec cette méthode, et au contraire des deux commandes ci-dessus, une erreur est en général renvoyée quand le système vous rend la main. Dans le cas contraire et si la connexion est ouverte, alors il vous laisse envoyer ce que vous voulez vers le socket, donc un ctrl+c va être utile ici ;)

# Ouverture d'une connexion vers le port https. 
cat < /dev/tcp/guillaume.fenollar.fr/443
# Envoi de métriques via udp sur un daemon telegraf local
cat < /dev/udp/127.0.0.1/8125
# Test d'un port SSH
guillaume :~ $ cat < /dev/tcp/guillaume.fenollar.fr/22
SSH-2.0-OpenSSH_7.4p1 Debian-10+deb9u6
^C

À vous d’appliquer ces pratiques à vos problématiques de tous les jours !