Um túnel SSH via múltiplos saltos

299

O tunelamento de dados por SSH é bastante direto:

ssh -D9999 [email protected]

configura a porta 9999 no seu localhost como um túnel para example.com , mas eu tenho uma necessidade mais específica:

  • Estou trabalhando localmente em localhost
  • host1 está acessível para localhost
  • host2 só aceita conexões de host1
  • Eu preciso criar um túnel de localhost para host2

Efetivamente, quero criar um túnel SSH "multi-hop". Como posso fazer isso? Idealmente, eu gostaria de fazer isso sem precisar ser superusuário em qualquer das máquinas.

    
por Mala 16.01.2010 / 06:58

13 respostas

280

Você basicamente tem três possibilidades:

  1. Túnel de localhost para host1 :

    ssh -L 9999:host2:1234 -N host1
    

    Como mencionado acima, a conexão de host1 a host2 não será protegida.

  2. Túnel de localhost para host1 e de host1 para host2 :

    ssh -L 9999:localhost:9999 host1 ssh -L 9999:localhost:1234 -N host2
    

    Isso abrirá um túnel de localhost a host1 e outro túnel de host1 a host2 . No entanto, a porta 9999 to host2:1234 pode ser usada por qualquer pessoa em host1 . Isso pode ou não ser um problema.

  3. Túnel de localhost para host1 e de localhost para host2 :

    ssh -L 9998:host2:22 -N host1
    ssh -L 9999:localhost:1234 -N -p 9998 localhost
    

    Isso abrirá um túnel de localhost a host1 , através do qual o serviço SSH em host2 poderá ser usado. Em seguida, um segundo túnel é aberto de localhost para host2 pelo primeiro túnel.

Normalmente, eu escolheria a opção 1. Se a conexão de host1 a host2 precisar ser protegida, vá para a opção 2. A opção 3 é útil principalmente para acessar um serviço em host2 que é somente acessível a partir de host2 .

    
por 17.01.2010 / 22:31
141

Há uma resposta excelente que explica o uso da diretiva de configuração ProxyCommand para SSH :

Adicione isto ao seu ~/.ssh/config (veja man 5 ssh_config para detalhes):

Host host2
  ProxyCommand ssh host1 -W %h:%p

Em seguida, o ssh host2 irá encapsular automaticamente o host1 (também funciona com o encaminhamento do X11, etc.).

Isso também funciona para uma classe inteira de hosts. identificado por domínio:

Host *.mycompany.com
  ProxyCommand ssh gateway.mycompany.com -W %h:%p

Atualizar

O OpenSSH 7.3 apresenta uma diretiva ProxyJump , simplificando o primeiro exemplo para

Host host2
  ProxyJump host1
    
por 01.08.2010 / 19:10
20

Temos um gateway ssh em nossa rede privada. Se eu estiver fora e quiser um shell remoto em uma máquina dentro da rede privada, eu teria que ssh no gateway e de lá para a máquina privada.

Para automatizar este procedimento, eu uso o seguinte script:

#!/bin/bash
ssh -f -L some_port:private_machine:22 user@gateway "sleep 10" && ssh -p some_port private_user@localhost

O que está acontecendo:

  1. Estabeleça um túnel para o protocolo ssh (porta 22) para a máquina privada.
  2. Somente se isso for bem-sucedido, ssh na máquina privada usando o túnel. (o & & operadora garante isso).
  3. Depois de fechar a sessão ssh privada, quero que o túnel ssh seja fechado também. Isso é feito através do truque "sleep 10". Normalmente, o primeiro comando ssh fecha após 10 segundos, mas durante esse tempo, o segundo comando ssh estabelecerá uma conexão usando o túnel. Como resultado, o primeiro comando ssh mantém o túnel aberto até que as duas condições a seguir sejam satisfeitas: o sleep 10 está concluído e o túnel não é mais usado.
por 24.01.2010 / 19:47
18

Depois de ler o acima e colar tudo junto, criei o seguinte script Perl (salve-o como mssh em / usr / bin e torne-o executável):

#!/usr/bin/perl

$iport = 13021;
$first = 1;

foreach (@ARGV) {
  if (/^-/) {
    $args .= " $_";
  }
  elsif (/^((.+)@)?([^:]+):?(\d+)?$/) {
    $user = $1;
    $host = $3;
    $port = $4 || 22;
    if ($first) {
      $cmd = "ssh ${user}${host} -p $port -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no";
      $args = '';
      $first = 0;
    }
    else {
      $cmd .= " -L $iport:$host:$port";
      push @cmds, "$cmd -f sleep 10 $args";
      $cmd = "ssh ${user}localhost -p $iport -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no";
      $args = '';
      $iport ++;
    }
  }
}
push @cmds, "$cmd $args";

foreach (@cmds) {
  print "$_\n";
  system($_);
}

Uso:

Para acessar o HOSTC via HOSTA e HOSTB (mesmo usuário):

mssh HOSTA HOSTB HOSTC

Para acessar o HOSTC via HOSTA e HOSTB e usar números de porta SSH não padrão e usuários diferentes:

mssh user1@HOSTA:1234 user2@HOSTB:1222 user3@HOSTC:78231

Para acessar o HOSTC via HOSTA e HOSTB e usar o X-forwarding:

mssh HOSTA HOSTB HOSTC -X

Para acessar a porta 8080 no HOSTC via HOSTA e HOSTB:

mssh HOSTA HOSTB -L8080:HOSTC:8080
    
por 11.01.2012 / 12:02
18

O OpenSSH v7.3 em diante suporta uma opção -J e uma opção ProxyJump , que permitem um ou mais hosts de salto separados por vírgulas, portanto, basta fazer isso agora:

ssh -J jumpuser1@jumphost1,jumpuser2@jumphost2,...,jumpuserN@jumphostN user@host
    
por 10.08.2016 / 11:11
8

Esta resposta é semelhante ao kynan, pois envolve o uso do ProxyCommand. Mas é mais conveniente usar o IMO.

Se você tem o netcat instalado em suas máquinas de salto, você pode adicionar este trecho ao seu ~ / .ssh / config:

Host *+*
    ProxyCommand ssh $(echo %h | sed 's/+[^+]*$//;s/\([^+%%]*\)%%\([^+]*\)$/ -l /;s/:/ -p /') nc $(echo %h | sed 's/^.*+//;/:/!s/$/ %p/;s/:/ /')

Então

ssh -D9999 host1+host2 -l username

fará o que você pediu.

Eu vim aqui procurando o lugar original onde eu li esse truque. Vou postar um link quando o encontrar.

    
por 13.03.2013 / 10:57
4
ssh -L 9999:host2:80 -R 9999:localhost:9999 host1

-L 9999:host2:80

Significa bind para localhost: 9999 e qualquer pacote enviado para localhost: 9999 encaminhar para host2: 80

-R 9999:localhost:9999

Significa que qualquer pacote recebido pelo host1: 9999 o encaminha de volta para o localhost: 9999

    
por 19.01.2010 / 03:03
2

você deve poder usar o encaminhamento de porta para acessar um serviço em host2 de localhost . Um bom guia está localizado aqui . Trecho:

There are two kinds of port forwarding: local and remote forwarding. They are also called outgoing and incoming tunnels, respectively. Local port forwarding forwards traffic coming to a local port to a specified remote port.

For example, if you issue the command

ssh2 -L 1234:localhost:23 username@host

all traffic coming to port 1234 on the client will be forwarded to port 23 on the server (host). Note that localhost will be resolved by the sshdserver after the connection is established. In this case localhost therefore refers to the server (host) itself.

Remote port forwarding does the opposite: it forwards traffic coming to a remote port to a specified local port.

For example, if you issue the command

ssh2 -R 1234:localhost:23 username@host

all traffic which comes to port 1234 on the server (host) will be forwarded to port 23 on the client (localhost).

No seu elenco, substitua localhost no exemplo por host2 e host por host1 .

    
por 16.01.2010 / 07:34
2

Eu fiz o que eu acho que você queria fazer com

ssh -D 9999 -J host1 host2

Eu sou solicitado para ambas as senhas, então eu posso usar localhost: 9999 para um proxy SOCKS para host2. É o mais próximo que posso pensar do exemplo que você mostrou em primeiro lugar.

    
por 21.11.2017 / 12:06
1

Nesta resposta, vou passar por um exemplo concreto. Você só precisa substituir os nomes de host, os nomes de usuários e as senhas dos seus computadores.

Declaração do problema

Vamos supor que temos a seguinte topologia de rede:

our local computer <---> server 1 <---> server 2

Por uma questão de concretude, vamos supor que temos os nomes de host, nomes de usuário e senhas dos computadores a seguir:

LocalPC            <--->  hostname: mit.edu         <---> hec.edu
                          username: bob                   username: john 
                          password: dylan123              password: doe456

Objetivo: queremos configurar um proxy SOCKS que atenda na porta 9991 de LocalPC , para que cada vez que uma conexão em LocalPC seja iniciada a partir da porta 9991 , passe por mit.edu then hec.edu .

Exemplo de caso de uso: hec.edu tem um servidor HTTP que só pode ser acessado no link , por motivos de segurança. Gostaríamos de poder visitar o link ao abrir um navegador da Web em LocalPC .

Configuração

Em LocalPC , adicione ~/.ssh/config :

Host HEC
    HostName hec.edu
    User john
    ProxyCommand ssh [email protected] -W %h:%p

Em seguida, no terminal de LocalPC , execute:

ssh -D9991 HEC

Ele perguntará a você a senha de bob on mit.edu (ou seja, dylan123 ) e, em seguida, solicitará a senha de john on hec.edu (ou seja, doe456 ).

Nesse momento, o proxy SOCKS agora está sendo executado na porta 9991 de LocalPC .

Por exemplo, se você quiser visitar uma página da Web em LocalPC usando o proxy SOCKS, faça no Firefox:

Algumas observações:

  • em ~/.ssh/config , HEC é o nome da conexão: você pode alterá-lo para qualquer coisa que desejar.
  • O -D9991 informa ssh para configurar um proxy SOCKS4 na porta 9991 .
por 18.03.2017 / 21:13
0

Se você puder usar o SSH em ambas as máquinas, dê uma olhada na diretiva ProxyCommand do ssh. Isso permitirá que você vá direto do host local para o host2 (em um comando fácil se você usar chaves públicas !!). Então você pode fazer o que quiser com o host2.

link

    
por 19.01.2010 / 02:35
0

A opção 2 da melhor resposta poderia ser usada com diferentes usuários ssh do que a atual aka: user @ host

    export local_host_port=30000
    export host1_user=xyz
    export host1=mac-host
    export host1_port=30000
    export host2=192.168.56.115
    export host2_user=ysg
    export host2_port=13306

    # Tunnel from localhost to host1 and from host1 to host2
    # you could chain those as well to host3 ... hostn
    ssh -tt -L $local_host_port:localhost:$host1_port $host1_user@$host1 \
    ssh -tt -L $host1_port:localhost:$host2_port $host2_user@$host2
    
por 05.10.2017 / 10:43
0

No meu caso eu fiz

localhost$ ssh -D 9999 host1
host1$ ssh -L 8890:localhost:8890 host2

em que host2:8890 está sendo executado em um Bloco de anotações Jupyter.

Em seguida, configurei o Firefox para usar localhost:9999 como um host SOCKS.

Agora, eu tenho o notebook rodando em host2 acessível pelo Firefox em localhost:8890 na minha máquina.

    
por 26.07.2018 / 07:24

Tags