Como SSH para usinar A via B em um comando?

103

Quero acessar um computador, digamos, a máquina A, que é baseada na rede da minha universidade. No entanto, este computador é acessível apenas através da rede interna da universidade, portanto, não posso usar o SSH para este computador diretamente de casa.

Aqui está o que eu faço agora:

  1. Faça login em uma máquina universitária diferente, digamos, máquina B

    (Esta máquina B pode ser acessada via SSH no meu computador em casa.)

  2. Use SSH em B para conectar-se a A.

Existe uma maneira de fazer isso mais rápido? Usando apenas um comando ssh.

Nikosdi
fonte
relacionados: ssh através de vários hosts
Trevor Boyd Smith

Respostas:

97

Sim, usando ProxyCommandna sua configuração SSH.

Crie um arquivo de configuração SSH em seu diretório pessoal (a menos que você queira torná-lo em todo o sistema) ~/.ssh/config:

Host unibroker          # Machine B definition (the broker)
Hostname 12.34.45.56    # Change this IP address to the address of the broker
User myusername         # Change this default user accordingly 
                        # (`user@unibroker` can overwrite it)

Host internalmachine    # Machine A definition (the target host)
ProxyCommand ssh -q unibroker nc -q0 hostname.or.IP.address.internal.machine 22

Agora você pode acessar a Máquina A diretamente usando

ssh user@internalmachine

Observe também que agora você tem um único nome de destino de host SSH para ele, também pode ser usado em outros aplicativos. Por exemplo:

  • SCP para copiar arquivos.

    scp somefile user@internalmachine:~/
    
  • Nos seus aplicativos GUI:

    use sftp://user@internalmachine/como local para navegar na máquina.

    Baseado no KDE (Dolphin): use fish://user@internalmachine/

Notas

Mude hostname.or.IP.address.internal.machinee a porta ( 22) para a máquina que você deseja alcançar como se fosse da unibrokermáquina.

Dependendo das versões do netcat no host unibroker, a -q0opção deve ser omitida. Em relação à autenticação; você está basicamente configurando duas conexões SSH da sua estação de trabalho. Isso significa que o host unibroker e o host da máquina interna são verificados / autenticados um após o outro (para verificação de chave / senha e chave do host).

Explicação

Essa abordagem do uso de ProxyCommande 'netcat' é apenas uma maneira de fazê-lo. Eu gosto disso, porque meu cliente SSH se comunica diretamente com a máquina de destino para que eu possa verificar a chave do host do meu cliente e usar minha autenticação de chave pública sem usar outra chave no broker.

Cada um Hostdefine o início de uma nova seção de host. Hostnameé o nome do host ou o endereço IP de destino desse host. Useré o que você forneceria como parte do usuário ssh user@hostname.

ProxyCommandserá usado como o tubo para a máquina de destino. Usando o SSH na primeira máquina e configurando diretamente um 'netcat' ( nc) simples para o destino a partir daí, isso é basicamente apenas um texto sem formatação encaminhado para a máquina interna do intermediário entre eles. As -qopções são silenciar qualquer saída (apenas uma preferência pessoal).

Certifique-se de ter o netcat instalado no broker (normalmente disponível por padrão no Ubuntu) - netcat-openbsdInstale o netcat-openbsd ou netcat-traditionalInstale o netcat-traditional .

Observe que você ainda está usando SSH com criptografia duas vezes aqui. Enquanto o canal netcat estiver em texto sem formatação, seu cliente SSH no seu PC configurará outro canal criptografado com a máquina de destino final.

gertvdijk
fonte
4
Eu tive que remover a opção -q0, pois não era suportada pela máquina que estava usando. Fora isso, tudo funcionou. Esta é uma dica fantástica. Muito obrigado. :)
Gerry
Corri para um problema, sua resposta funciona bem para mim no terminal, mas não consigo fazer isso usando o gui sftp, ele diz: mensagem de erro sem tratamento, o tempo limite expirou durante o login.
Vikash B
@ VikashB Bem, isso realmente deve funcionar. Considere criar uma NOVA pergunta para lidar com sua situação específica.
gertvdijk
Eu fiz aqui é a pergunta: askubuntu.com/questions/688567/…
Vikash B
1
Para complementar a palavra sábia de @gertvdijk, há um ótimo wikibook sobre o tópico de proxies ssh e hosts de salto que pode servir como uma referência inestimável.
Travis Clarke
51

Hop de uma só vez

Uma alternativa óbvia à abordagem ProxyCommand que forneci em minha outra resposta seria 'pular' diretamente para a máquina de destino:

ssh -t user@machineB ssh user@machineA

Observe o -tno primeiro sshcomando. Sem ele, falhará:

Pseudo-terminal will not be allocated because stdin is not a terminal.
ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory
Permission denied, please try again.
[...]

Isso forçará um TTY real a ser alocado

A desvantagem disso é que agora toda a configuração, verificação e autenticação ocorre na Máquina B, da qual realmente não gosto na minha situação por motivos de segurança. Gosto do meu par de chaves no meu próprio PC, autentico e verifico a máquina de destino final no meu próprio PC. Além disso, você só pode usar o shell interativo para SSH, para que isso não lide com outras ferramentas como o SCP ou com o gerenciador de arquivos da GUI.

Por todos os motivos acima mencionados, recomendo fortemente a abordagem ProxyCommand , mas para uma conexão rápida isso funciona bem.

gertvdijk
fonte
Por que não ter uma resposta com as soluções 'One Off' e Permanente?
precisa
5
@demure É assim que os sites StackExchange funcionam ... Veja: Qual é a etiqueta oficial para responder uma pergunta duas vezes? diz "É melhor postar duas respostas diferentes do que colocá-las em uma resposta". . E não considero que seja a mesma solução. Permanente / temporariamente não é o que torna essa abordagem diferente, na minha opinião.
gertvdijk
Outros guias dizem usar, além disso, a opção -A, mas indicam que isso tem implicações de segurança. Você sabe o que significa encaminhar ou não a conexão do agente de autenticação?
Diagon
@gertvdijk super ninja aqui! você tem as duas melhores soluções. Eu nunca vi isso antes. muito legal. muito melhor do que criar uma solução mega longa com soluções N (que é o que eu costumo ver).
Trevor Boyd Smith
Isso é muito mais conveniente do que configurar uma configuração que prejudicará outros sshs também.
Nikhil Sahu 25/03
37

Você pode usar a -Jopção de linha de comando:

ssh -J user@machineB user@machineA

De man ssh:

-J [user@]host[:port]
     Connect to the target host by first making a ssh connection to
     the jump host and then establishing a TCP forwarding to the
     ultimate destination from there.  Multiple jump hops may be
     specified separated by comma characters.  This is a shortcut to
     specify a ProxyJump configuration directive.

Foi introduzido no OpenSSH versão 7.3 (lançado em agosto de 2016). Está disponível no Ubuntu 16.10 e posterior.

Erik Sjölund
fonte
3
+1 porque isso funciona mesmo se você precisar especificar o arquivo de chave para machineA
Grief
1
+1, esta é a versão melhor em comparação com a minha resposta ProxyCommand se todos os seus hosts estiverem executando uma versão do OpenSSH recente o suficiente.
gertvdijk 18/03
O servidor OpenSSH deve ser instalado nas máquinas A e B neste caso? Estou bem entendido?
Mikhail
17

Tente usar

Host <visible hostname alias>
        Controlmaster auto
        User <user>
        hostname <visible hostname>
        port <port>
        IdentityFile ~/.ssh/<id file>

Host <private LAN hostname alias>
     ProxyCommand ssh -q -W <private LAN hostname>:<private LAN port> <visible hostname alias>

no seu ~ / .ssh / config e faça tudo de uma vez só com as chaves que residem no seu computador.

Ajuda SSH
fonte
1
Isso é mais limpo do que introduzir o netcat na mistura. Além disso, a chave SSH privada também não precisa existir na Bmáquina.
22816 Danemacmillan
1

Esta é uma sugestão muito útil. Depois de mexer por horas, encontrei esta nota e confirmei que funciona exatamente como documentado. Para conectar o MachineA ao MachineB, na máquina remota C:

por exemplo: [xuser @ machineC ~] ssh -t MachineA ssh MachineB

O "-t" é crítico, o ssh falha se não estiver presente. Você será solicitado duas vezes, primeiro para a senha no MachineA, e depois para o MachineB. Além disso, observe que isso pressupõe que você tenha o usuário "xuser" definido nas três máquinas. Caso contrário, use a sintaxe ssh: "yuser @ MachineA ...". Observe também que você pode usar IP # s brutos de quatro pontos, se desejar. Isso é útil se você estiver vinculando através de uma rede local privada que esteja usando IPs não expostos ao mundo - ie. não no arquivo host local ou em qualquer DNS. Para obter um arquivo do MachineB, para o machineC remoto, você pode scp do MachineB para o MachineA, depois do MachineA para o machineC remoto. (Por exemplo, a máquina remota C pode executar ping na Máquina A, mas não na Máquina B.) Advertência: Eu testei com o Fedora e o WindowsXP, a Máquina A é uma caixa XP executando o ICS (Internet Connection Sharing), enquanto MachineB e machineC remoto são caixas do Fedora-Linux. Essa sugestão resolveu um problema importante para mim - ie. acesso remoto restrito e monitorado à LAN do meu site remoto. Observe também que, quando você "efetua logout" no MachineB, verá duas "Conexão com xxx.xxx.xxx.xxx fechadas". mensagens.

Mcl
fonte
Se você instalar e configurar a autenticação de chave pública, não precisará se preocupar em inserir suas senhas. Mas -tainda é necessário.
Felipe Alvarez
@FelipeAlvarez Você ainda precisa se preocupar em digitar a segunda senha se não confiar na máquina B para ter um login sem senha em A!
Michael
1

O ProxyCommand é uma solução limpa para um caso em que você permite acesso ao shell nos dois sistemas. Queríamos dar aos usuários remotos acesso a uma máquina interna (A) por meio de um broker (B), mas sem permitir ao usuário um acesso shell a B para maior segurança. Isso funcionou:

Substitua o shell de login

Substitua o shell de login (uso chsh) para extuserno broker pelo seguinte script (armazenado em um arquivo):

#!/bin/sh   # this is essential to avoid Exec format error
ssh internaluser@A

Desde que nenhum login de senha tenha sido configurado no extuser @ B para o usuário remoto e no internaluser @ A para o extuser @ B, a execução do comando a seguir levará diretamente o usuário remoto para A

ssh extuser@B

Dica : Crie a configuração necessária sem login de senha author_keys no extuser @ B antes de mudar para o shell de login personalizado. Após a alteração, como essa conta é inacessível a qualquer pessoa por meio de um shell, apenas um sudoer @ B pode fazer alterações no arquivo authored_keys editando-o diretamente.

sudo vi ~extuser/.ssh/authorized_keys
sudo touch ~extuser/.hushlogin

A última linha é suprimir a exibição do banner de login de B, para que o usuário remoto tenha acesso transparente a A.

Sunthar
fonte
Abordagem muito interessante. No entanto, as principais desvantagens disso são: 1) O uso é limitado ao uso SSH padrão (sem suporte a SFTP / SCP). 2) Um usuário não pode selecionar outro host de destino que não seja o único (porque codificado no shell de login) 3) A validação da chave do host não pode ser feita da estação de trabalho para o host de destino final (desde o uso do binário SSH do broker) . 4) As chaves privadas para os usuários acessarem o host de destino final residem no broker e não no usuário. Isso permite a representação do usuário por um administrador (o que normalmente não é possível).
precisa saber é o seguinte
Todos os pontos verdadeiros, obrigado por elaborar. No entanto, o objetivo principal é fornecer um acesso ssh de usuário confiável a A sem logon em B. Como apenas o administrador pode adicionar a chave pública do usuário confiável em B (por meio do sudo, sem logon), isso já implica que o usuário possui ( admin) acesso à chave privada do extuser @ B (não do usuário confiável externo) e a configurou, em primeiro lugar!
Sunthar 29/09/16
1

Você quer dizer que você precisa de vários jumpers :)

Recentemente, eu encontrei este problema com jumper1 jumper2 e minha máquina final, quanto ao meu sol

script local:

#!/bin/bash
sshpass -p jumper1Passwd ssh -t jumper1@jumper1IP ./Y00.sh

depois, no 1º jumper (que é o meu roteador), coloquei um script chamado Y00.sh:

ssh -tt jumper2@jumper2 -i ~/.ssh/id_rsa sshpass -p finalPassWord ssh -tt final@final

Você pode substituí-los pelo seu IP e senhas, boa sorte!

Z-Y00
fonte