Introduction à socat

socat est un outil en ligne de commande du même type que netcat, mais il est tellement plus polyvalent !

Ce programme (concaténation de socket et cat) est décrit sur le site officiel comme un relais à usages multiples. Des exemples parlent mieux qu’un long discours :

Connexion à un serveur TCP :

# Avec netcat
netcat <HOST> <PORT>
# Avec socat
socat TCP-CONNECT:<HOST>:<PORT> -

Explication :

socat requiert 2 arguments interchangeables (hors cas spécifiques) représentant les 2 connexions à relayer. Ici :

  • TCP-CONNECT:<HOST>:<PORT> est la connexion vers le serveur
  • - représente l’entrée standard et la sortie standard (stdin et stdout)

Création d’un serveur TCP écoutant sur le port <PORT> :

# Avec netcat
netcat -l -p <PORT>
# Avec socat
socat TCP-LISTEN:<PORT> -

Création d’un relais TCP (“proxy”) entre 2 hôtes :

# Avec socat
socat TCP-LISTEN:<PORT1> TCP-CONNECT:<HOST2>:<PORT2>

Explication :

Ce dernier exemple permet de recopier le contenu reçu sur le PORT1 vers le serveur HOST2:PORT2, mais également de recopier le contenu envoyé depuis HOST2:PORT2 vers le client connecté sur le PORT1.

Nous venons de créer un serveur mandataire (dit “proxy” en anglais). Cette dernière commande laisse entrevoir les nombreuses possibilités offertes par socat. Pour plus d’informations, ne pas hésiter à lire le man (en anglais).

Socat peut faire bien plus que du TCP !

Si socat gère parfaitement les domaines de communication AF_INET / AF_INET6 (IPv4 / IPv6), il est aussi capable d’utiliser des sockets UNIX, des fichiers ou même d’appeler des programmes … (et sans doute plus encore ?).

Cet article s’intéresse uniquement aux sockets (IP ou UNIX). En C, ces sockets sont créés avec l’appel système suivant :

int socket(int domain, int type, int protocol);

Lors de la création d’un socket, on spécifie donc le domaine (AF_INET, AF_INET6 ou AF_UNIX), le type (plus de détails ci-dessous) et le protocole (valeur souvent omise et égale à 0).

Le type peut notamment être :

  • SOCK_STREAM (connexion TCP)
  • SOCK_DGRAM (connexion UDP)
  • SOCK_SEQPACKET (connexion SCTP)
  • SOCK_DCCP (connexion DCCP)

La plupart de ces types de socket sont rendu facilement accessibles par socat. Voici quelques exemples :

# Connexion à un serveur TCP (STREAM)
socat TCP-CONNECT:<HOST>:<PORT> -
# Envoi de paquets UDP (DGRAM)
socat UDP-DATAGRAM:<HOST>:<PORT> -
# Connexion à un serveur SCTP (SEQPACKET)
socat SCTP-CONNECT:<HOST>:<PORT> -
...

Utiliser un type de socket non défini dans socat

Si on prête attention à la page de man, il n’existe pas de “raccourcis” permettant de se connecter à un serveur DCCP ou de créer une socket UNIX en mode SEQPACKET.

Il est cependant possible de créer des sockets génériques en forçant les valeurs type et protocol utilisées pour l’appel à socket().

Il nous faut tout d’abord récupérer la bonne valeur de type souhaité (nous laisserons le protocole à une valeur par défaut). Afin d’obtenir le type, je propose de directement parcourir les fichiers en-tête de votre distribution.

Voici un exemple :

Recherche du type SEQPACKET :

grep -r SEQPACKET /usr/include/sys /usr/include/bits
# On trouve dans le résultat la ligne suivante :
#   SOCK_SEQPACKET = 5

Création d’un serveur UNIX en mode SEQPACKET :

socat UNIX-LISTEN:/tmp/mysocket,type=5 -

Connexion au serveur UNIX en mode SEQPACKET :

socat UNIX-CONNECT:/tmp/mysocket,type=5 -

Pour aller plus, voici la page sur les sockets génériques de socat (anglais).

Ressources