SSH trava antes do prompt de login

0

Eu tenho vários túneis ssh reversos configurados a partir de pisteis de framboesa remotos, executando o debian jessie. Os RPIs usam um dongle 3G para obter conectividade intrnet, e é por isso que eu estou usando o ssh reverso para fazer o login remotamente. Cada RPI configura um túnel ssh reverso para um servidor em nuvem, que eu uso para efetuar login em cada sistema.

Os túneis ssh são configurados da seguinte forma:

ssh -N -o ExitOnForwardFailure=yes -R 23xx:localhost:22 [email protected]

em que 23xx é a porta usada para encaminhar conexões da porta 22 e 178.x.x.xxx é o endereço IP do servidor.

Meu problema é que, às vezes, quando tento ssh em um sistema, ele fica suspenso para sempre, sem erros, como segue:

ssh pi_username@localhost -p 23xx

O terminal não produz nada depois disso e fica pendurado para sempre. Quando eu tento depurar usando -vvv isso é o que eu recebo:

ssh pi_username@localhost -p 23xx -vvv

OpenSSH_6.7p1 Debian-5+deb8u4, OpenSSL 1.0.1t  3 May 2016
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug2: ssh_connect: needpriv 0
debug1: Connecting to localhost [::1] port 23xx.
debug1: Connection established.
debug1: key_load_public: No such file or directory
debug1: identity file /home/master/.ssh/id_rsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/master/.ssh/id_rsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/master/.ssh/id_dsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/master/.ssh/id_dsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/master/.ssh/id_ecdsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/master/.ssh/id_ecdsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/master/.ssh/id_ed25519 type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/master/.ssh/id_ed25519-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.7p1 Debian-5+deb8u4

Parece que a conexão foi estabelecida, mas o login não é solicitado. Alguma ideia? Qualquer recomendação sobre como depurar ainda mais?

    
por LecauseAndThePi 05.03.2018 / 12:43

1 resposta

0

Esta é apenas uma teoria, mas o que eu suspeito que está acontecendo é que as conexões TCP para suas sessões ssh estão morrendo, mas o "servidor em nuvem" não está detectando isso. Então, quando você vai fazer uma conexão com localhost -p 23xx , o processo ssh ainda está lá e escutando, mas quando ele tenta enviar dados de volta para o Pi ele trava até que o número máximo de retransmissões TCP seja encontrado e finalmente decida se a conexão é morto e sai (você diz que trava para sempre, mas eu estou apostando que se você esperasse o suficiente você teria uma conexão redefinida). Agora, supondo que você tenha o Pi configurado para reconectar se o túnel ssh morrer, você pode pensar que isso deve resolver o problema. Existem alguns problemas em potencial com essa ideia. Primeiro, o Pi também pode não estar detectando a conexão morta. Então, até que ele tente enviar dados e atingir o limite de retransmissões TCP, ele não verá a conexão inativa e fará a reconexão. O segundo problema em potencial é que, mesmo se detectar a conexão inativa e tentar se reconectar, ela não conseguirá estabelecer o ouvinte no servidor em nuvem, porque o ssh anterior ainda está lá e mantendo a porta.

A solução aqui é configurar o ssh para que ele possa detectar as conexões inativas. Existem algumas maneiras de fazer isso, TCP KeepAlive e SSH KeepAlive. (ref: link )

TCP KeepAlive ( TCPKeepAlive configuração em ssh config) usa a funcionalidade nativa keep-alive do TCP. Basicamente, o kernel envia um TCP ACK vazio a cada X segundos, e quando ele não obtém um ACK de volta da outra extremidade (ou obtém um reset) ele fecha a conexão que notifica o aplicativo (SSH).

O SSH KeepAlive (as configurações ServerAlive* & ClientAlive* ) é semelhante, mas opera em uma camada superior. Aqui, o processo SSH envia dados reais através da conexão e procura por uma resposta. Isto deve detectar uma conexão inoperante tão bem quanto um TCP KeepAlive normal, entretanto é mais provável manter a conexão viva porque os saltos no meio podem reconhecer pacotes TCP KeepAlive e ignorá-los, e timeout a conexão inativa. Mas um KeepAlive do SSH não pode ser reconhecido, pois parece um tráfego real para qualquer salto no meio.

TL; DR:

No raspberry Pis, adicione as seguintes configurações à configuração do seu cliente ssh ( ~/.ssh/config ou /etc/ssh/ssh_config ):

ServerAliveInterval 15
ServerAliveCountMax 1

( documentação )

No servidor, adicione as seguintes configurações à sua configuração do daemon ssh ( /etc/ssh/sshd_config ):

ClientAliveInterval 20
ClientAliveCountMax 1

( documentação )

Note que eu fiz o valor do intervalo um pouco mais alto. A razão para isso é apenas para que ambos os lados não enviem suas mensagens KeepAlive ao mesmo tempo e se cruzam no fio. Não há nenhum dano real nisso, apenas uma pequena ineficiência. Também não importa qual lado é maior, contanto que seja diferente.

    
por 05.03.2018 / 14:56

Tags