Можно ли выставить TCP-туннель в Linux как устройство специального символа?

10

Недавно я обнаружил в документации QNX, что она позволяет устанавливать IPC на основе сообщений между процессами на отдельных физических машинах с помощью serial device ( dev/serX), и это заставило меня задуматься:

Возможно ли в Linux создание общесистемного специального устройства для туннеля TCP / UDP? Что-то вроде ncstdin / stdout открыто публикуется в / dev / что-то.

В конце я хотел бы иметь возможность записать что-то в такой файл на одном компьютере и получить это на другом конце, например:

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

#machine2:
cat < /dev/somedev

Я взглянул на ncчеловека, но не нашел никакой возможности указать источник / назначение io, кроме stdio.

Lapsio
источник
См. Почему сетевые интерфейсы не находятся в / dev, как другие устройства? которая охватывает часть «почему бы и нет».
Жиль "ТАК - перестань быть злым"
1
Похвальное упоминание: устройства tun / tap могут быть созданы в / dev, но вы должны сами выполнить IP-инкапсуляцию. Чрезвычайно полезно для некоторых целей.
pjc50

Ответы:

19

socat может сделать это и многое другое с вещами, напоминающими «потоки»

Что-то, использующее эту основную идею, должно сделать это для вас:

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

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

(адаптировано со страницы примеров )

Если вы хотите зашифровать, вы можете использовать вариант ssl-l:54321,reuseaddr,cert=server.pem,cafile=client.crt,forkна machine1 и что-то вроде ssl:server-host:1443,cert=client.pem,cafile=server.crtна machine2

(Подробнее о socat ssl )

Алекс Страгиес
источник
7

Передача сообщений должна быть реализована на более высоком уровне; TCP не имеет понятия сообщения - TCP-соединения передают потоки октетов.

Вы можете достичь чего-то вроде того, что вы запрашиваете, ncи именованных каналов , видите man mkfifo; или проверьте, socatкак указывает Алекс Страгиес.

Без службы среднего уровня основные проблемы заключаются в том, что (1) данные не могут быть записаны в сеть, если на другом конце их не слушают, и (2) соединения TCP являются двунаправленными.

Поскольку вы не можете записывать данные в сеть, если кто-то их не слушает, вы всегда должны запустить прослушиватель, прежде чем сможете отправлять данные. (В системе передачи сообщений процесс, обрабатывающий сообщения, обеспечит некоторую буферизацию.)

Ваш пример может быть легко переписан:

  • Сначала запустите слушатель на машине 2 (место назначения):

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

    В вашем примере это будет

     nc -l 1234 | cat
    

    Это заблокирует и подождет, пока кто-нибудь отправит данные на порт 1234.

  • Затем вы можете отправить некоторые данные из machine1 (источник):

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

    В вашем примере это будет

     echo "Hello" | nc machine2 1234
    

Если вы хотите каким-то образом обработать полученные данные и ответить на них, вы можете использовать средство совместной обработки оболочки. Например, это очень простой (и очень упрямый) веб-сервер:

#! /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

Посмотрите, как достигается двунаправленная связь между основной частью сценария и сопроцессом с использованием файловых дескрипторов в массиве $ncfd.

AlexP
источник
Вы правы, и я признал это в ответе. Не может быть символьного устройства без какого-либо посреднического программного обеспечения.
AlexP
Похоже, у вас там есть UUOC.
Майкл Хэмптон
1
@MichaelHampton: Это был пример, предоставленный ОП. Я предполагаю, что это catозначает "некоторый процесс чтения для стандартного ввода".
AlexP
5

Если вы просто хотите соединить два компьютера с помощью базовой программы, такой как nc, вы можете перенаправить из / в /dev/tcp/<host>/<port>.

Это не настоящие устройства, а вымысел, созданный bash, поэтому такие вещи, как « cat /dev/tcp/foo/19не будут работать, а cat < /dev/tcp/foo/19будут работать».

Анхель
источник