Tudo sobre o sxy ProxyCommand

6

Estou procurando uma explicação detalhada sobre o ProxyCommand a seguir, até as porcas e parafusos de sua operação, por favor. Você pode gentilmente dissecar isso para mim e melhorar se puder? Por legibilidade, se nada mais.

ProxyCommand ssh gatewayserver 'exec 3<>/dev/tcp/targetserver/22; cat <&3 & cat >&3;kill $!'
    
por Robottinosino 28.08.2011 / 16:07

1 resposta

4

(Eu não tenho um dispositivo /dev/tcp no meu sistema; entretanto, bash parece ter algum tratamento interno para ele, alocando um soquete tcp conectado à seguinte /host/port part.)

Assim, o comando ssh proxy executa um shell com segurança em gatewayserver , o que faz:

exec 3<>/dev/tcp/targetserver/22

i.e. Anexe um soquete no filedescriptor 3 (conectado ao targetserver / port ). Então:

cat <&3 & cat >&3; kill $!

que é uma maneira de ter um redirecionamento bidirecional (usando dois processos separados) entre os dois grupos de descritores 0 (entrada) e 1 (saída) e filedescriptor 3 (entrada e saída). O kill $! está lá para matar o processo de segundo plano cat <&3 depois que o outro processo cat >&3 retornou.

Tudo isso é apenas um equivalente de um padrão:

ProxyCommand ssh gatewayserver "tcpconnect targetserver port"

usando os recursos /dev/tcp (ou bash ) em vez do comando tcpconnect .

Mais alguns detalhes:

O comando proxy usado pelo ssh está lá para definir como se conectar ao host remoto targetserver (a criptografia não é realmente necessária lá porque o protocolo ssh será usado sobre este canal). Em nosso caso, queremos estabelecer a conexão com esse host de destino através de gatewayserver (provavelmente porque um firewall impede a conexão com targetserver diretamente.

Então, um processo

ssh gatewayserver 'exec 3<>/dev/tcp/targetserver/22; cat <&3 & cat >&3;kill $!'

é iniciado e:

  • filedescriptor (fd) 1 (a.k.a. saída padrão) será usado por um cliente ssh para enviar dados para o host de destino.
  • fd 0 (a.k.a. entrada padrão) será usado por um cliente ssh para ler dados do host remoto.

O ssh gatewayserver é usado para se conectar primeiro ao gateway, que será o primeiro salto. Um novo shell é iniciado neste host e essa instância de ssh retransmitirá fd 0 / fd 1 do processo no host de origem para fd 0 / fd 1 do shell em execução no host do gateway . O comando executado por este shell é:

exec 3<>/dev/tcp/targetserver/22; cat <&3 & cat >&3;kill $!

O exec sem um comando não executará nada, apenas aplicará os seguintes redirecionamentos ao próprio shell. Os redirecionamentos habituais são:

  • n>file para redirecionar fd n para file (aberto somente para escrita, n é 1 se omitido).
  • n<file para redirecionar fd n para file (aberto apenas para leitura, n é 0 se omitido).
  • n<>file para redirecionar fd n para file (aberto para leitura e escrita).
  • quando especificado como n>&m ou n<&m ou n<>&m , o fd n é redirecionado para o arquivo anteriormente apontado por fd m .

Aqui, o seguinte é usado:

exec 3<>/dev/tcp/targetserver/22

Isso redirecionará um fd 3 recém-criado para algum arquivo muito especial /dev/tcp/targetserver/22 (que não é realmente um arquivo, mas algo que o bash entende nativamente). Aqui, o bash cria um socket (arquivo especial que usa o protocolo tcp) para falar com targetserver na porta 22 (onde esperamos encontrar um sshd server), e este arquivo está aberto (read & write) no fd 3 .

Agora precisamos "bombear" os dados em fd 0 (dados do cliente) e enviá-los para fd 3 (conectado ao servidor de destino). Nós também precisamos assegurar a comunicação para trás "bombeando" os dados em fd 3 e enviando-os de volta para fd 1 (resultado para o cliente). Essas duas "bombas" são configuradas usando dois processos cat :

  • cat <&3 (que lê do fd 3 do shell e escreve no fd 1 do shell.)
  • cat >&3 (que lê do fd 0 do shell e escreve no fd 3 do shell.)

Ambos cat s devem ser executados em paralelo, portanto, é necessário ter um plano de fundo. Aqui, queremos que o que lê em fd 0 (que provavelmente será um tty) seja o que resta em primeiro plano. Isso dá:

cat <&3 &  #run in the background
cat >&3; kill $!

O kill $! está lá para eliminar o processo em segundo plano ( $! expande para o pid do último processo em segundo plano). Desta forma, quando o cliente desliga, o processo em primeiro plano termina, o kill é executado e o último processo também é finalizado.

É isso! Nós fizemos a ponte:

origin host —(ssh)→ gateway —(pumps+socket)→ targetserver(port 22)

Um ssh user@targetserver no host origin poderá se conectar ao host target por meio dessa ponte!

    
por 28.08.2011 / 16:59