Tela, ou similar, para retomar automaticamente uma conexão ssh esquisita

18

Muitas vezes, tenho que me conectar a um servidor via ssh em um ambiente wifi não confiável. No servidor, eu executo a tela; portanto, se eu for desconectado, posso reconectar e retomar a sessão de tela e continuar de onde parei, mas a perda de conexão ainda é um grande problema: se a conexão cair enquanto eu estiver estou no servidor, a janela do terminal tende a congelar. Eu tenho que matar essa guia, abrir um novo, ssh para o servidor novamente e retomar a sessão de tela. Eu tentei isso com tela em execução no servidor e tela localmente. De qualquer maneira, ele tende a congelar quando a conexão é interrompida.

Existe alguma maneira de ter algo semelhante à tela, ou talvez a própria tela, que tentará se reconectar automaticamente e manter a sessão em execução, para que eu não precise se reconectar manualmente? Muitas vezes, quando perco a conexão, acho que é apenas por um período muito breve - menos de um segundo, talvez.

Estou usando o Ubuntu 14.04 LTS, edição MATE. obrigado

Max Williams
fonte
4
Re "a janela do shell tende a congelar": Isso ocorre porque o ssh local não sabe que a conexão está morta. Pressione <Enter>e digite ~.para dizer ao seu lado para interromper a conexão, e você pode simplesmente repetir o último comando ssh para reconectar (por exemplo, com seta para cima ou !!).
21418 Alexis
@alexis que parece uma maneira mais rápida de reconectar, obrigado! Eu adoraria que isso acontecesse automaticamente embora ...
Max Williams

Respostas:

23

Você pode usar mosh: https://mosh.org/

Você pode configurar um servidor 'jump' com uma conexão de internet confiável à qual você moshse conecta e ter sshsessões para cada servidor que você gerencia. O motivo pelo qual sugiro usar um servidor de salto é que você pode não querer instalar moshnos servidores que está gerenciando.

Outra vantagem moshdisso é que ele é baseado em UDP e não em TCP, e sua sessão pode sobreviver a uma mudança de endereço IP, por exemplo, passando de WiFi para uma conexão de Internet móvel.

Só para deixar claro, moshnão é um substituto para screen, mas sim ssh. Ainda é uma boa idéia usá screen-lo, pois moshele não fornece uma maneira de se reconectar à sua sessão se o cliente morrer por algum motivo.

enferrujado shackleford
fonte
Obrigado, é apenas o servidor (na maioria das vezes) e nós o possuímos, por isso devo poder instalar o Mosh. Vou dar uma olhada.
Max Williams
Na verdade, acontece que, como o nosso servidor é muito antigo (ou devo rodar um Ubuntu antigo), é muito difícil de instalar. :(
Max Williams
@MaxWilliams quantos anos tem? Até o LTS 12.4 ficou sem suporte. E por que não apenas tentar compilá-lo você mesmo
phuclv
Enquanto eu leio os documentos mosh, você precisa do servidor mosh em cada host que pretende gerenciar remotamente. Ainda assim, definitivamente interessante.
Curinga
11
Conectar-me a um terminal tmux sobre mosh é a solução mais estável para mim.
Nemo
3

Estou usando tmuxhá alguns anos e, na minha experiência, ele se reconecta automaticamente. Pelo menos quando a conexão falha apenas por um tempo relativamente curto. Note que eu realmente uso byobucom o tmux como back-end. Eu não sei se isso robustez é uma característica de tmuxou byobuou mesmo da combinação dos dois, mas eu sugiro que você dê tanto uma tentativa.

Eu me conecto da minha instalação local do Arch a vários servidores remotos do Ubuntu por meio de uma VPN. Testei-o agora desconectando meu cabo de rede enquanto estava conectado ao controle remoto. A sessão foi interrompida, mas assim que meu cabo foi conectado novamente, ele foi retomado sem problemas.

No entanto, quando eu testei reiniciando meu roteador, a conexão não retornou. Suponho que tenha algo a ver com o tempo que a rede ficou inoperante, mas parece reconectar-se se estiver apenas inoperante em alguns segundos.

Caso seja relevante, faço tudo isso terminatorcomo meu emulador de terminal.

Todos os três estão disponíveis nos repositórios do Ubuntu:

sudo apt-get install tmux terminator byobu

No entanto, não tenho certeza de que seja tmuxou byobuseja melhor no tratamento de desconexões ssh. Só sei que, em minha experiência, eles geralmente retornam de pequenas perdas de conexão. Isso pode estar relacionado a outros aspectos da minha configuração.

terdon
fonte
11
Quando você reiniciou o roteador, pode ter recebido um endereço IP público diferente, o que interrompeu a tcpconexão. Pela minha experiência, sshpode ser muito resistente a interrupções intermitentes da rede, não acho que isso tenha algo a ver com o fato de você estar usando tmuxdentro da sshjanela.
Rusty shackleford
3
Eu diria o mesmo: mesmo com SSH simples, você pode lidar com uma breve desconexão, desde que a conexão TCP não morra. O que pode acontecer, se sua interface for desligada ou se algum roteador for excessivamente zeloso (os roteadores NAT podem esquecer o estado NAT na reinicialização e interromper as conexões existentes), ou ClientAlive/ ServerAlivetriggers, ou ... Não sei o que byobufaz, no entanto .
precisa saber é o seguinte
Sim, mas o OP parece estar com congelamento em qualquer falha de conexão, enquanto eu não. Mas sim, você está certo, eu também vejo isso com ssh simples e sem tmux. No entanto, talvez a tela não consiga lidar com isso?
terdon
2
@ MaxWilliams tmuxé basicamente uma alternativa mais moderna para screen, sim. Quando comecei a trabalhar como agora e precisava desse tipo de coisa, minha leitura superficial sugeriu que tmuxé a melhor escolha hoje em dia. Também não tenho 100% de certeza de que ele tenha um melhor gerenciamento de conexões perdidas, tudo que sei é que ele se recupera de breves interrupções na minha experiência. Se é isso tmuxou algo mais, eu não sei. Mas parece que vale a pena tentar :). O Byobu é basicamente um frontend para o screen / tmux, não um emulador de terminal da GUI. É extremamente útil: byobu.org
terdon
2
O tmux não faz nada sobre interrupções de conexão. Funciona com o dispositivo terminal fornecido pelo ssh. Tudo fica parado e cai com a conexão ssh.
Jonas Schäfer
2

Use as ServerAliveopções do ssh para detectar quando a conexão falhou.

ServerAliveCountMax
Define o número de mensagens ativas do servidor (veja abaixo) que podem ser enviadas sem o ssh (1) receber mensagens de volta do servidor. Se esse limite for atingido enquanto as mensagens ativas do servidor estiverem sendo enviadas, o ssh será desconectado do servidor, encerrando a sessão. É importante observar que o uso de mensagens ativas do servidor é muito diferente do TCPKeepAlive (abaixo). As mensagens ativas do servidor são enviadas através do canal criptografado e, portanto, não serão falsificadas. A opção TCP keepalive ativada pelo TCPKeepAlive é falsificada. O mecanismo ativo do servidor é valioso quando o cliente ou servidor depende de saber quando uma conexão se tornou inativa.

O valor padrão é 3. Se, por exemplo, ServerAliveInterval (veja abaixo) estiver definido como 15 e ServerAliveCountMax for deixado no padrão, se o servidor não responder, o ssh será desconectado após aproximadamente 45 segundos.

ServerAliveInterval
Define um intervalo de tempo limite em segundos, após o qual, se nenhum dado foi recebido do servidor, o ssh (1) enviará uma mensagem através do canal criptografado para solicitar uma resposta do servidor. O padrão é 0, indicando que essas mensagens não serão enviadas ao servidor.

Portanto, se você definir ServerAliveInterval5, sshserá desconectado automaticamente se a rede sair por 15 segundos.

Barmar
fonte
Para quebrar uma sessão SSH pela força, eu imprensa ~.(ou entra pela primeira vez, então ~.) constituído por: o caractere de escape ~e o comando para quebrar a sessão.
IMZ - Ivan Zakharyaschev
@ imz - IvanZakharyaschev Isso pressupõe que você pode dizer que a conexão está travada. O uso do keepalive do SSH detectará a falha automaticamente.
Barmar
Isso parece realmente útil, obrigado. Definitivamente, tentarei na próxima vez em que estiver na "zona esquisita".
Max Williams
@ Barmar Sim, é verdade. Também pensei no problema de determinar se a conexão está realmente travada ou se pressionar alguma coisa pode acidentalmente enviar essas teclas para o lado remoto ... E não conheço uma boa solução.
imz - Ivan Zakharyaschev 6/06/19
2

Em condições semelhantes, eu costumo usar eshellcom TRAMP (over ssh) dentro do Emacs. O TRAMP cuida da reconexão quando necessário, sem causar muitos problemas para eu fornecer os comandos desejados para o shell remoto.

No entanto, eshell não é bom como um terminal, ou seja, para executar comandos que fazem algo especial com o terminal ou que funcionam por um período significativo de tempo continuamente (incrementalmente) imprimindo algo.

Basicamente, é bastante simples começar a usá-lo no Emacs com o TRAMP:

M-x eshell
cd /user@host:
imz - Ivan Zakharyaschev
fonte
1

aviso Legal

Se a sua conexão SSH não sobreviver a breves interrupções na rede, haverá outra coisa que não permitirá que o sshTCP faça o que é normal.

Veja abaixo para detalhes. De qualquer forma:

A solução sem dependência mais rápida e suja

Crie um script de shell como este:

#!/bin/sh -

# Tune these numbers depending on how aggressively
# you want your SSH session to get reconnected.
timeout_options='-o ServerAliveInterval=4 -o ServerAliveCountMax=2'

# 255 is the status OpenSSH uses to signal SSH errors, which
# means we want to connect. All other exit statuses suggest
# an intentional exit.
status=255

# Keep opening the SSH connection and immediately dropping into
# `screen` until an intentional exit happens.
while [ "$status" = 255 ]
do
    ssh $timeout_options -t "$@" screen -dR
    status=$?
    # You can add a `sleep` command here or a counter or whatever
    # you might need as far as rate/retry limiting.
done
exit "$status"

Isso apenas executará um loop simples e estúpido que continua tentando se conectar sshe se conectar screen. Passe o host ou qualquer outra coisa que você normalmente passaria para sua sshchamada como argumentos da linha de comando.

A reconexão baseia-se apenas no fato de o SSH relatar um erro na conexão, o que significa que ele não possui inteligência para detectar erros não-SSH como "você literalmente não tem o WiFI ativado" ou o que quer que seja, mas isso provavelmente não importa para você.

Suponho que você tenha ssh-agentou uma chave SSH sem senha que permita que as reconexões funcionem sem a necessidade de entrada adicional de você.

Haverá uma pequena condição de corrida em que, se você acertar ^Cdurante a fração de segundo imperceptível a humanos certa durante uma reconexão, poderá acabar matando o script em vez de passar o ^Ccaminho para o terminal do cliente, portanto, se você suspeitar de uma conexão travada não amasse ^Ccom zelo demais.

Solução de software adicional mais simples

Você pode tentar o programa autossh , que deve estar disponível no seu repositório de pacotes Ubuntu.

Se você precisar compilar a partir do código-fonte ou auditá-lo, é um único programa em C que compila sem nenhuma biblioteca adicional como dependências, parece ter mais inteligência sobre como verificar a vitalidade da conexão do que o meu hack acima, e também é fornecido com um conveniente rscreencomando de script que auto -anexa a screen.

Detalhes

Como sshnormalmente se recupera

Só para verificar, porque não gosto de dizer as coisas sem me verificar, fiz um pequeno teste antes de responder:

Eu entrei no meu WiFi com um dispositivo Linux, fiz uma conexão SSH com outro dispositivo na minha LAN, verifiquei que tinha uma sshconexão funcionando com a outra extremidade (podia executar comandos, etc.) e, em seguida, o cliente desconectou o WiFi (causando a interface para ser desconfigurado: não há mais endereços IP), digitou muitos caracteres na sessão ssh (sem resposta, é claro) e reconectou-se ao meu WiFi - a reconexão realmente falhou pelo menos uma vez devido a um sinal ruim e outros fatores e, finalmente, reconectado: esperei cerca de cinco segundos para que a sshsessão se recuperasse, nada aconteceu e pressionei mais uma tecla, e a sshsessão imediatamente voltou a funcionar, com todas as teclas que eu havia digitado durante a desconexão aparecendo na linha de comando.

Veja, sshapenas grava / lê no soquete da rede TCP até que o sistema operacional avise que algo deu errado, e o TCP é realmente muito tolerante a quedas prolongadas de conexão.

Deixada para seus próprios dispositivos com configurações padrão do kernel, a pilha TCP no Linux tolerará com prazer a conexão ficar completamente silenciosa por muitos minutos antes de declarar a conexão inativa e relatar um erro ssh- no momento em que finalmente desistir, estaremos conversando no estádio. de ~ 30 minutos, ou pelo menos certamente o tempo suficiente para superar os soluços de conexão que duram um segundo ou um minuto.

Por baixo das capas, a pilha TCP do Linux tenta novamente gradualmente as mensagens com atrasos cada vez maiores, o que significa que, quando sua conexão voltar, você poderá observar um atraso adicional antes que sua sshsessão pareça ficar "viva" novamente.

Por que isso às vezes quebra

Geralmente, algo está ativamente causando o fechamento da conexão após um período de inatividade significativamente mais curto do que o valor que a pilha TCP tolerará e, em seguida, falha ao relatar esse estado de conexão ao seu sshcliente.

Os candidatos prováveis ​​incluem:

  1. Firewalls ou roteadores NAT'ing, que precisam usar a memória para lembrar cada conexão TCP ativa - como uma otimização e alguma atenuação contra ataques do DOS, eles às vezes esquecem sua conexão e depois ignoram silenciosamente os pacotes resultantes, porque os pacotes no no meio de uma conexão quando você não se lembra da conexão existente parecer inválida.

  2. Firewalls / roteadores com melhor comportamento injetam um pacote TCP RST, que geralmente se manifesta como uma connection reset by peermensagem de erro, mas o pacote de redefinição é um alerta, portanto, se a conexão com o cliente ainda estiver com problemas naquele momento e eliminar o redefinir o pacote também, seu cliente pensará que a conexão ainda está ativa.

  3. O servidor em si pode ter uma política de firewall para eliminar silenciosamente pacotes inesperados, o que interromperia as tentativas de retomada de conexão do cliente sempre que o servidor considerar que a conexão foi fechada, mas o cliente não: seu cliente continua tentando continuar a conexão, mas o servidor é apenas ignorando-o porque não há conexão ativa à qual esses pacotes pertençam ao estado de firewall do servidor.

    Como você está executando o Linux, verifique cuidadosamente o servidor iptables/ ip6tables(ou nftse você estiver usando o novo material) exatamente o que está permitindo ou descartando. É muito comum permitir pacotes novos / estabelecidos / relacionados na porta TCP SSH, mas não "inválidos" - se você estiver descartando silenciosamente tudo o que não é permitido, essa configuração comum poderá causar esse tipo de congelamento após breves problemas de conexão .

  4. O próprio servidor SSH pode ser configurado para fechar a conexão após um período de inatividade, usando uma das opções do OpenSSH para pacotes de manutenção de atividade do cliente TCP ou SSH. Por si só, isso não causará travamentos indefinidos, mas pode colocá-lo em um dos estados descritos acima.

  5. É possível que você simplesmente não esteja dando tempo suficiente para "desfazer" sozinho depois de entrar no estado em que sua sshsessão é encerrada .

mtraceur
fonte