É possível expor o túnel TCP no Linux como dispositivo de caractere especial?

10

Recentemente, descobri na documentação do QNX que ele permite configurar o IPC baseado em mensagens entre processos em máquinas físicas separadas usando o dispositivo serial ( dev/serX) e isso me fez pensar:

É possível no Linux criar um dispositivo especial em todo o sistema para o túnel TCP / UDP? Algo como ncstdin / stdout exposto publicamente em / dev / something.

No final, eu gostaria de poder escrever algo nesse arquivo em uma máquina e recebê-lo na outra extremidade, por exemplo:

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

#machine2:
cat < /dev/somedev

Dei uma olhada no ncman, mas não encontrei nenhuma opção para especificar a origem / destino io diferente do stdio.

Lapsio
fonte
Consulte Por que as interfaces de rede não estão no / dev como outros dispositivos? que cobre a parte "por que não".
Gilles 'SO- stop be evil'
1
Menção honrosa: Os dispositivos tun / tap podem ser criados em / dev, mas você mesmo deve encapsular o IP. Extremamente útil para alguns propósitos.
Pjc50

Respostas:

19

socat pode fazer isso e muitas outras coisas com coisas parecidas com "fluxos"

Algo usando essa idéia básica deve fazer isso por você:

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

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

(adaptado da página Exemplos )

Se você deseja criptografar, você pode usar uma variação de ssl-l:54321,reuseaddr,cert=server.pem,cafile=client.crt,forkna máquina1 e algo como ssl:server-host:1443,cert=client.pem,cafile=server.crtna máquina2

(Mais sobre socat ssl )

Alex Stragies
fonte
7

A passagem de mensagens precisa ser implementada em uma camada superior; O TCP não tem noção de mensagem - as conexões TCP transferem fluxos de octetos.

Você pode obter algo como o que você solicita nce nomeia pipes , veja man mkfifo; ou verifique socatcomo Alex Stragies indica.

Sem um serviço de camada intermediária, os problemas básicos são (1) que os dados não podem ser gravados na rede, a menos que haja alguém do outro lado ouvindo e (2) que as conexões TCP sejam bidirecionais.

Como você não pode gravar dados na rede, a menos que alguém esteja ouvindo, você deve sempre iniciar o ouvinte antes de poder enviar dados. (Em um sistema de transmissão de mensagens, o processo que manipula as mensagens fornecerá algum tipo de buffer.)

Seu exemplo pode ser facilmente reescrito:

  • Primeiro, inicie um ouvinte na máquina2 (o destino):

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

    No seu exemplo, isso seria

     nc -l 1234 | cat
    

    Isso irá bloquear e aguardar que alguém envie alguns dados para a porta 1234.

  • Em seguida, você pode enviar alguns dados da máquina1 (a fonte):

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

    No seu exemplo, isso seria

     echo "Hello" | nc machine2 1234
    

Se você deseja processar os dados recebidos de alguma forma e responder, pode usar o recurso de coprocessamento do shell. Por exemplo, este é um servidor web muito simples (e muito teimoso):

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

Veja como a comunicação bidirecional é alcançada entre o corpo principal do script e o coprocesso usando os descritores de arquivo na matriz $ncfd.

AlexP
fonte
Você está certo, e eu reconheci isso na resposta. Não é possível ter um dispositivo de caractere sem algum tipo de software de mediação.
AlexP
Parece que você tem um UUOC lá.
Michael Hampton
1
@ MichaelHampton: Esse foi o exemplo fornecido pelo OP. Suponho que catsignifica "alguma leitura de processo para stdin".
AlexP
5

Se você simplesmente deseja conectar dois computadores usando um programa básico como o nc, poderá redirecionar de / para /dev/tcp/<host>/<port>.

Estes não são dispositivos reais, mas uma ficção criada pelo bash; portanto, coisas como cat /dev/tcp/foo/19não funcionarão, mas cat < /dev/tcp/foo/19funcionarão.

Anjo
fonte