Est-il possible d'exposer le tunnel TCP sous Linux en tant que périphérique de caractères spéciaux?

10

Récemment, j'ai trouvé dans la documentation QNX qu'il permet de configurer l'IPC basé sur les messages entre les processus sur des machines physiques distinctes en utilisant un périphérique série ( dev/serX) et cela m'a fait me demander:

Est-il possible sous Linux de créer un périphérique spécial à l'échelle du système pour le tunnel TCP / UDP? Quelque chose comme ncstdin / stdout exposé publiquement sous / dev / quelque chose.

À la fin, j'aimerais pouvoir écrire quelque chose dans un tel fichier sur une machine et le recevoir à l'autre extrémité, par exemple:

#machine1:
echo "Hello" > /dev/somedev

#machine2:
cat < /dev/somedev

J'ai jeté un œil à ncman mais je n'ai trouvé aucune option pour spécifier io source / destination autre que stdio.

Lapsio
la source
Voir Pourquoi les interfaces réseau ne sont-elles pas dans / dev comme les autres appareils? qui couvre la partie «pourquoi pas».
Gilles 'SO- arrête d'être méchant'
1
Mention honorable: Les périphériques tun / tap peuvent être créés dans / dev, mais vous devez effectuer vous-même l'encapsulation IP. Extrêmement utile à certaines fins.
pjc50

Réponses:

19

socat peut faire cela et bien d'autres choses avec des choses ressemblant à des "flux"

Quelque chose utilisant cette idée de base devrait le faire pour vous:

Machine1$ socat tcp-l:54321,reuseaddr,fork pty,link=/tmp/netchardev,waitslave

Machine2$ socat pty,link=/tmp/netchardev,waitslave tcp:machine1:54321

(adapté de la page d'exemples )

Si vous voulez crypter, vous pouvez utiliser une variante de ssl-l:54321,reuseaddr,cert=server.pem,cafile=client.crt,forksur machine1, et quelque chose comme ssl:server-host:1443,cert=client.pem,cafile=server.crtsur machine2

(En savoir plus sur socat ssl )

Alex Stragies
la source
7

Le passage de messages doit être implémenté à une couche supérieure; TCP n'a pas la notion de message - les connexions TCP transfèrent des flux d'octets.

Vous pouvez obtenir quelque chose de tri comme ce que vous demandez avec ncet les pipes nommés , voir man mkfifo; ou vérifiez socatcomme Alex Stragies l'indique.

Sans service de couche intermédiaire, les problèmes de base sont (1) que les données ne peuvent pas être écrites sur le réseau à moins qu'il n'y ait quelqu'un à l'autre bout pour les écouter, et (2) que les connexions TCP soient bidirectionnelles.

Parce que vous ne pouvez pas écrire de données sur le réseau à moins que quelqu'un ne les écoute, vous devez toujours démarrer l'écouteur avant de pouvoir envoyer des données. (Dans un système de transmission de messages, le processus qui gère les messages fournira une sorte de tampon.)

Votre exemple peut être facilement réécrit:

  • Démarrez d'abord un écouteur sur machine2 (la destination):

     nc -l 1234 | ...some processing with the received data...
    

    Dans votre exemple, ce serait

     nc -l 1234 | cat
    

    Cela bloquera et attendra que quelqu'un envoie des données au port 1234.

  • Ensuite, vous pouvez envoyer des données de machine1 (la source):

    ...make up some data... | nc machine2 1234
    

    Dans votre exemple, ce serait

     echo "Hello" | nc machine2 1234
    

Si vous souhaitez traiter les données reçues d'une manière et répondre, vous pouvez utiliser la fonction de coprocessing du shell. Par exemple, il s'agit d'un serveur Web très simple (et très têtu):

#! /bin/bash

while :; do
  coproc ncfd { nc -l 1234; }
  while :; do
    read line <&${ncfd[0]} || break
    line="$(
      echo "$line" |
      LC_ALL=C tr -cd ' -~'
    )"
    echo >&2 "Received: \"$line\""
    if [ "$line" = "" ]; then
      echo >&${ncfd[1]} "HTTP/1.0 200 OK"
      echo >&${ncfd[1]} "Content-Type: text/html"
      echo >&${ncfd[1]} "Connection: close"
      echo >&${ncfd[1]} ""
      echo >&${ncfd[1]} "<title>It works!</title>"
      echo >&${ncfd[1]} "<center><b>It works!</b></center>"
      echo >&${ncfd[1]} "<center>-- $(date +%Y-%m-%d\ %H:%M:%S) --</center>"
      break
    fi
  done
  kill %%
  sleep 0.1
done

Découvrez comment la communication bidirectionnelle est réalisée entre le corps principal du script et le coprocessus à l'aide des descripteurs de fichiers du tableau $ncfd.

AlexP
la source
Vous avez raison, et je l'ai reconnu dans la réponse. Impossible d'avoir un appareil de caractères sans une sorte de logiciel de médiation.
AlexP
On dirait que vous avez un UUOC là-bas.
Michael Hampton
1
@MichaelHampton: C'était l'exemple fourni par le PO. Je suppose que cela catsignifie "une lecture de processus pour stdin".
AlexP
5

Si vous souhaitez simplement connecter deux ordinateurs à l'aide d'un programme de base comme nc, vous pouvez rediriger depuis / vers /dev/tcp/<host>/<port>.

Ce ne sont pas des appareils réels mais une fiction créée par bash, donc des choses comme ça cat /dev/tcp/foo/19ne fonctionneront pas, mais le cat < /dev/tcp/foo/19feront.

Ange
la source