Patrice Ferlet
Patrice Ferlet
Créateur de ce blog.
Publié le juin 25, 2008 Temps de lecture: 8 min

Me suivre sur Mastodon

Netcat, créez votre serveur en BASH

Bash est puissant, très puissant. Les commandes et utilisations sont vastes à tel point que vous pouvez aller jusqu’à créer un serveur complet en Bash… oui vous m’avez bien entendu: **en Bash**. Ceci est possible grâce à la commande **nc** communément appelée //netcat//. Son principe est simple comme bonjour. Tout comme “cat” peut lire un fichier et l’envoyer sur la sortie standard, “nc” va faire exactement la même chose mais depuis un port.

Netcat est un outil développé depuis des années, abandonné par son auteur puis redéveloppé et maintenu par la communauté. Il existe plusieurs implémentation de cette commande, mais la plus répandue est celle d’OpenBSD nommée GNUnetcat. Les différentes implémentations fonctionnent toutes quasiment de la même manière, seules les options peuvent changer. J’ai pour ma part la même version de netcat sur mon macOSX et ma Fedora 9. Je pense que les distributions actuelles sont à jour sur ce point. Il existe des implémentations Windows de netcat. Mais voyons maintenant ses capacités.

Je vais vous montrer comment utiliser netcat pour communiquer d’une machine à l’autre, transférer des fichiers,… et communiquer avec des serveurs existant (serveur WEB, serveur MAIL…). Puis nous verrons comment créer un véritable serveur communiquant avec le client grâce à des “backpipes” (tube FIFO).

Cas simple 1, communication standard

“nc” peut prendre différentes options, mais je vais vous donner seulement celles qui vont nous intéresser par la suite. –l demande à netcat de se mettre en écoute. C’est le mode **serveur** qui sera activé (“l” pour “listen”) –k après fermeture du clients, le serveur n’est pas coupé et peut attendre d’autres clients (“k” pour “keep alive”). Pour le moment je ne l’utilise pas, mais si vous souhaitez que le serveur tourne continuellement, ajoutez l’option à votre ligne de lancement server.

Si aucune option n’est donnée, nous n’allons pas écouter mais tenter de nous connecter à une machine, c’est à dire que nous utiliserons netcat comme **client**. Testons un cas simple: Ouvrez deux terminaux de commande pour commencer. Dans le premier tapez:

nc -l 3333

Vous venez de créer un serveur basique qui écoute sur le port 3333 de votre machine.

Dans le second terminal, tapez:

nc 127.0.0.1 3333

Cette fois, c’est le client qui est créé. Vous venez de vous connecter à votre propre machine (127.0.0.1 ou localhost) sur le port 3333. Toujours sur ce terminal, vous voyez que la commande n’est pas terminée. Effectivement, elle attend que l’on tape dans l’entrée standard. Tapez “Salut” par exemple puis sur la toucher “Entrée” et regardez dans la première fenêtre de terminal où nous avons créé notre serveur. Et oui, vous voyez que le serveur reçoit votre “Salut”.

Mais cela fonctionne dans l’autre sens, d’ailleurs, tapez “Hello” dans la première fenêtre de terminal où le serveur a été créé, et regardez la fenêtre cliente. Idem, vous recevez les données.

Dans la fenêtre “cliente” (la seconde) pressez CTRL+C. Le client se ferme mais et le serveur aussi. Nous verrons par la suite qu’il est possible de se mettre en attente d’autres connexions sans que le serveur s’éteigne.

Vous pouvez aussi transformer les donnée reçues, par exemple, créez ce serveur:

nc -l 3333 | sed "s/world/galaxy/"

Puis tapez dans un autre terminal:

echo "Hello the world" | nc 127.0.0.1 3333

Sur le serveur, vous devriez voir apparaitre “Hello the galaxy”. La redirection de sortie va être **très utile** par la suite, notamment pour traiter des données et répondre au client. Pour le moment, voyons un autre exemple.

Cas simple 2, transfère de fichier

Nous l’avons vu précédemment, netcat lit et écrit sur la sortie standard. Comme pour toutes les commandes bash, il est possible de rediriger les sorties. Voyons comment copier rapidement un fichier d’une machine à l’autre. D’abord, créons le serveur qui va lire les donnée envoyées et les enregistrer dans un fichier:

nc -l 3333 > /tmp/fichier.txt

Créez un fichier /tmp/transf.txt et mettez-y “Hello the world” à l’interieur. Ensuite faites:

nc 127.0.0.1 3333 < /tmp/transf.txt
   -- ou bien --
cat /tmp/transf.txt | nc 127.0.0.1 3333

Alors que ce passe-t-il ? on se connecte à la machine 127.0.0.1 sur le port 3333 et on y envoie le contenu d’un fichier texte. Du coté serveur, on écoute sur le port local 3333 et on redirige ce que l’on reçoit vers le fichier /tmp/fichier.txt.

Vérifiez le contenu du fichier /tmp/fichier.txt, et oui ça a marché

Le droit de réponse, code boomerang

Pour le moment, nous n’avons put répondre au client qu’en tapant dans le terminal qui écoute. Le soucis c’est que nous aimerions pouvoir automatiser les réponses. L’idée est d’utiliser des “pipes” (ou “tube” en français) qui vont permettre de lire et écrire au fur dans les deux sens.

    • Petit rappel:**

-un fichier FIFO (pipe FIFO) va se vider chaque fois qu’il est lut, et ce //ligne par ligne//. Il accumule les lignes chaque fois qu’on écrit dedans. La première ligne entrée dans le fichier sera la première à sortir. //FIFO = First In, First Out//. -Si vous exécutez une commande le flux standard se trouve dans le canal 1, les erreurs dans le canal 2. Par exemple sed “s/titi/toto/” < /tmp/fichier.txt | cat 1> /tmp/transform va faire ceci -envoyer le contenu du fichier dans la commande sed pour transformer les données -le flux de sortie va partir dans /tmp/transform sans les erreurs -Pour qu’un script Bash puisse lire l’entrée standard, il faut utiliser la commande read

    • ATTENTION** Veillez à ce que le “1” soit **collé** au symbole “>” sinon Bash vous répondra qu’il ne connait pas le fichier “1”. Or nous voulons parler du canal 1.

Maintenant, lançons nous. Nous allons faire un //“boomerang”//, c’est à dire que tout ce que le client tapera sera retourné au client. Cet exemple vous montre comment lire et écrire dans netcat directement.

Coté serveur:

mkfifo /tmp/backpipe
nc -l 3333 < /tmp/backpipe | cat 1> /tmp/backpipe
</code>  


Je demande à netcat d'écouter le port 3333 et d'écrire le contenu de /tmp/backpipe (notre FIFO) au client. Tout ce que le client tapera sera aussi envoyé au backpipe... c'est pas génial ça ?

Allons y, tentons:
<code>
$ nc 127.0.0.1 3333
Hello
Hello

Je n’ai tapé qu’une seule fois “Hello” dans cet exemple, mais le serveur m’a retourné ce que j’ai tapé. Notre serveur lit et écrit. Nous allons pouvoir nous amuser un peu.

Pour le moment, je fais cat 1> /tmp/backpipe c’est à dire que tout ce que je reçois en sortie standard repars dans /tmp/backpipe. L’idée, c’est de ne plus utiliser cat mais notre propre serveur en bash, en perl, en ce que vous voulez. Tout ce qui importe c’est que votre serveur lise en continue **l’entrée standard** et écrive le résultat dans **la sortie standard**. En bash, nous utiliserons read pour lire STDIN, et echo pour écrire sur STDOUT. Vous pouvez tout aussi bien créer un service en perl, en python, en java…

Premier serveur en bash

Nous allons nous amuser à faire un petit serveur qui saura faire deux chose selon ce que le client demande.

-Si l’utilisateur tape “date” alors le serveur enverra la date -Si le client tape ping alors le serveur doit répondre par “pong”.

Voici notre script bash, que vous placerez dans /tmp/server1.sh: ` #! /bin/bash

tous ce que le client va m’envoyer se trouvera dans la variable “question”

while read question do if [[ “$question” == “date” ]]; then date fi

 if [[ "$question" == "ping" ]]; then
    echo pong
 fi

done

exit 0 `

Maintenant la ligne de bash qui va faire fonctionner le service:

mkfifo /tmp/backpipe
nc -l 3333 < /tmp/backpipe | bash /tmp/server.sh 1> /tmp/backpipe

Notre serveur est lancé; lancons un client:

patrice$ nc 127.0.0.1 3333
date
Mer 25 jui 2008 14:28:41 CEST
ping
pong

Il fonctionne… c’est pas merveilleux ? Vous pourriez aussi rendre la ligne un peu moins grosse en rendant /tmp/server1.sh executable:

chmod +x /tmp/serer1.sh

Ce qui vous donnera le lancement de serveur de cette manière:

mkfifo /tmp/backpipe
nc -l 3333 < /tmp/backpipe | /tmp/server.sh 1> /tmp/backpipe

Notes

J’ai passé un moment à chercher pourquoi seulement “cat 1> /tmp/backpipe” fonctionnait très bien, mais pas les commandes tr, sed, etc… en fait il semblerait que c’est simplement parce que ces commandes ne savent pas lire en boucle STDIN. Notre script Bash lit continuellement STDIN (boucle while read…) et ne pose pas de soucis.

Run basic server

Sur la base de ce ticket, j’ai créé un petit scipt appelé RBS ou Run Basic Sever. Il est opensource et sous licence GPL. Voici comment elle fonctionne:

rbs monserver.sh 3333

Et j’ai aussi pensé à l’option “-k” pour garder le serveur actif après fermeture du client:

rbs -k monserver.sh 3333

Il existe aussi les options -h pour avoir de l’aide, et -v pour avoir la version du script. Je vous laisse récupérer mon script rbs-0.0.1.tar.gz.

Vous pouvez tester le serveur de notre tutoriel:

./rbs -k /tmp/server1.sh 3333

Vous pouvez copier le fichier rbs.sh dans /usr/bin pour qu’il soit accessible directement:

cd /tmp
wget http://www.metal3d.org/tools/rbs-0.0.1.tar.gz
tar zxvf rbs-0.0.1.tar.gz
cp rbs-0.0.1/rbs.sh /usr/bin/rbs
chmod +x /usr/bin/rbs
rbs -v

Vous devriez avoir le numéro de version de RBS qui s’affiche à la fin de ces commandes. Si c’est le cas, c’est que rbs est installé, sinon, dites mois où vous coincez.

Dans tous les cas, laissez moi des commentaires c’est toujours sympa d’avoir des retours.

Références

Gnu Netcat: http://netcat.sourceforge.net/\\ Man page: http://www.openbsd.org/cgi-bin/man.cgi?query=nc\\ Run Basic Server: http://www.metal3d.org/tools/rbs-0.0.1.tar.gz

comments powered by Disqus