Pantalla, o similar, para reanudar automáticamente una conexión ssh débil

18

A menudo tengo que conectarme a un servidor a través de ssh en un entorno wifi poco confiable. En el servidor, ejecuto la pantalla, por lo que si me desconecto, puedo volver a conectarme y reanudar la sesión de la pantalla, y retomar donde lo dejé, pero la pérdida de conexión sigue siendo un sumidero de tiempo importante: si la conexión se cae mientras yo Estoy en el servidor, la ventana de terminal tiende a congelarse. Tengo que eliminar esa pestaña, abrir una nueva, ssh al servidor nuevamente y reanudar la sesión de pantalla. He intentado esto con la pantalla en ejecución en el servidor y la pantalla localmente. De cualquier manera, tiende a congelarse cuando se corta la conexión.

¿Hay alguna manera de que pueda tener algo similar a la pantalla, o tal vez la pantalla en sí misma, que intentará reconectarse automáticamente y mantener la sesión en ejecución, para que no tenga que volver a conectarme manualmente? A menudo, cuando pierdo la conexión, creo que es solo por un período muy breve, quizás menos de un segundo.

Estoy usando Ubuntu 14.04 LTS, edición MATE. Gracias

Max Williams
fuente
44
Re "la ventana de shell tiende a congelarse": eso se debe a que su ssh local no sabe que la conexión está desconectada. Presione <Enter>y escriba ~.para decirle a su lado que desconecte la conexión, y simplemente puede repetir el último comando ssh para volver a conectar (por ejemplo, con la flecha hacia arriba o !!).
alexis
@alexis que suena como una forma más rápida de reconectarse, ¡gracias! Sin embargo, me encantaría que suceda automáticamente ...
Max Williams

Respuestas:

23

Puedes mirar usando mosh: https://mosh.org/

Puede configurar un servidor 'jump' con una conexión a Internet confiable a la que se moshconecte y luego tener sshsesiones en cada servidor que administre. La razón por la que sugiero usar un servidor de salto es que quizás no desee instalar moshen los servidores que está administrando.

Otra ventaja moshes que se basa en UDP en lugar de TCP, y su sesión puede sobrevivir a un cambio de dirección IP, por ejemplo, pasar de WiFi a una conexión de internet móvil.

Solo para dejarlo claro, moshno es un reemplazo screen, sino más bien ssh. Todavía es una buena idea usarlo screen, ya que en moshsí mismo no proporciona una manera de volver a conectarse a su sesión si el cliente muere por alguna razón.

Shackleford oxidado
fuente
Gracias, es solo un servidor (la mayoría de las veces) y lo poseemos, así que debería poder instalar Mosh. Lo comprobaré.
Max Williams
En realidad, resulta que debido a que nuestro servidor es bastante antiguo (o que ejecuta un Ubuntu antiguo, debería decir) es demasiado difícil de instalar. :(
Max Williams
@MaxWilliams ¿cuántos años tiene? Incluso LTS 12.4 se ha quedado sin soporte. Y por qué no se limite a tratar de compilar usted mismo
phuclv
Mientras leo los documentos de Mosh, necesitas Mosh-Server en cada host que pretendes administrar de forma remota. Aún así, definitivamente interesante.
Comodín el
1
Conectarme a un terminal tmux sobre mosh es la solución más estable para mí.
Nemo
3

Lo he estado usando tmuxdurante algunos años y, según mi experiencia, se vuelve a conectar automáticamente. Al menos cuando la conexión falla solo por un tiempo relativamente breve. Tenga en cuenta que en realidad lo uso byobucon tmux como back-end. No sé si esto robustez es una característica de tmuxo byobu, o incluso de la combinación de los dos, pero sugiero que le permite obtener una oportunidad.

Me conecto desde mi instalación local de Arch a varios servidores remotos de Ubuntu a través de una VPN. Lo probé ahora mismo desenchufando mi cable de red mientras estaba conectado al control remoto. La sesión se suspendió, pero tan pronto como mi cable se volvió a enchufar, se reanudó sin problemas.

Sin embargo, cuando probé reiniciando mi enrutador, la conexión no regresó. Supongo que tiene algo que ver con el tiempo que la red estuvo inactiva, pero parece volver a conectarse si solo está inactiva unos segundos.

En caso de que sea relevante, hago todo esto usando terminatormi emulador de terminal.

Los tres están disponibles en los repositorios de Ubuntu:

sudo apt-get install tmux terminator byobu

Sin embargo, no estoy del todo seguro de que tampoco tmuxo byobusea ​​mejor en el manejo de desconexiones ssh. Solo sé que, en mi experiencia, a menudo regresan de pérdidas de conexión cortas. Sin embargo, eso puede deberse a otros aspectos de mi configuración.

terdon
fuente
1
Cuando reinició su enrutador, es posible que se le haya asignado una dirección IP pública diferente, lo que habrá interrumpido la tcpconexión. Según mi experiencia, sshpuede ser muy resistente a los abandonos de red intermitentes, no creo que esto tenga nada que ver con el hecho de que está usando tmuxdentro de la sshventana.
oxidado shackleford
3
Iba a decir lo mismo: incluso con SSH simple, puedes lidiar con una corta desconexión, siempre que la conexión TCP no falle. Lo que podría ocurrir, si su interfaz se apaga, o algún enrutador demasiado entusiasta lo mata (los enrutadores NAT pueden olvidar el estado NAT al reiniciar y romper las conexiones existentes), o ClientAlive/ ServerAlivedisparadores, o ... No tengo idea de lo que byobuhace, sin embargo .
ilkkachu
Sí, pero el OP parece estar experimentando congelamiento en cualquier falla de conexión, mientras que yo no. Pero sí, tienes razón, también veo esto con ssh simple y sin tmux. Sin embargo, ¿tal vez la pantalla no puede manejarlo?
terdon
2
@MaxWilliams tmuxes básicamente una alternativa más moderna a screen, sí. Cuando comencé a trabajar como lo hago ahora y necesitaba este tipo de cosas, mi lectura superficial sugirió que esa tmuxes la mejor opción en estos días. Tampoco estoy 100% seguro de que tenga una mejor gestión de las conexiones perdidas, todo lo que sé es que se recupera de breves interrupciones en mi experiencia. Si eso se debe a tmuxalgo más, no lo sé. Pero parece que vale la pena intentarlo :). Byobu es básicamente una interfaz para screen / tmux, no un emulador de terminal GUI. Sin embargo, es extremadamente útil: byobu.org
terdon
2
tmux no hace nada con respecto a las interrupciones de conexión. Funciona con el dispositivo terminal proporcionado por ssh. Todo se para y cae con la conexión ssh.
Jonas Schäfer
2

Use las ServerAliveopciones de ssh para detectar cuándo ha fallado la conexión.

ServerAliveCountMax
Establece el número de mensajes activos del servidor (ver más abajo) que pueden enviarse sin que ssh (1) reciba ningún mensaje del servidor. Si se alcanza este umbral mientras se envían mensajes vivos del servidor, ssh se desconectará del servidor y finalizará la sesión. Es importante tener en cuenta que el uso de mensajes vivos del servidor es muy diferente del TCPKeepAlive (a continuación). Los mensajes activos del servidor se envían a través del canal encriptado y, por lo tanto, no se podrán falsificar. La opción TCP keepalive habilitada por TCPKeepAlive es suplantable. El mecanismo de servidor activo es valioso cuando el cliente o el servidor dependen de saber cuándo una conexión se ha vuelto inactiva.

El valor predeterminado es 3. Si, por ejemplo, ServerAliveInterval (ver más abajo) se establece en 15 y ServerAliveCountMax se deja en el valor predeterminado, si el servidor deja de responder, ssh se desconectará después de aproximadamente 45 segundos.

ServerAliveInterval
Establece un intervalo de tiempo de espera en segundos después del cual, si no se han recibido datos del servidor, ssh (1) enviará un mensaje a través del canal encriptado para solicitar una respuesta del servidor. El valor predeterminado es 0, lo que indica que estos mensajes no se enviarán al servidor.

Entonces, si configura ServerAliveIntervala 5, sshse desconectará automáticamente si la red falla durante 15 segundos.

Barmar
fuente
Para romper una sesión SSH por la fuerza, presiono ~.(o primero Enter, luego ~.) que consiste en: el personaje de escape ~y el comando para romper la sesión.
imz - Ivan Zakharyaschev
@ imz - IvanZakharyaschev Eso supone que se puede decir que la conexión está colgada. El uso de keepalive de SSH detectará la falla automáticamente.
Barmar
Eso suena realmente útil, gracias, definitivamente lo intentaré la próxima vez que esté en la "zona escamosa".
Max Williams
@ Barmar Sí, es cierto. También he pensado en el problema de determinar si la conexión está realmente bloqueada, o si presiono algo accidentalmente puedo enviar estas teclas al lado remoto ... Y no conozco una buena solución.
imz - Ivan Zakharyaschev 06/06/18
2

En condiciones similares, tiendo a usar eshellTRAMP (sobre ssh) dentro de Emacs. TRAMP se encarga de volver a conectar cuando sea necesario sin causarme muchos problemas al dar los comandos deseados para el shell remoto.

Sin embargo, eshell no es bueno como terminal, es decir, para ejecutar comandos que hacen algo especial con el terminal, o que se ejecutan durante un período significativo de tiempo de forma continua (incremental) imprimiendo algo.

Básicamente, es bastante simple comenzar a usarlo en Emacs con TRAMP:

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

Descargo de responsabilidad

Si su conexión SSH no está sobreviviendo a breves interrupciones de la red, entonces está sucediendo algo más que no permite que sshTCP haga lo normal.

Ver abajo para más detalles. De todas formas:

La solución sin dependencias más rápida y sucia

Cree un 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"

Esto solo ejecutará un bucle estúpido simple que sigue intentando conectarse sshy conectarse screen. Pase el host o cualquier otra cosa que normalmente pasaría a su sshinvocación como argumentos de línea de comandos.

La reconexión solo se basa en si SSH informa un error con la conexión, lo que significa que no tiene inteligencia para detectar errores que no sean SSH como "literalmente no tiene WiFI activado" o lo que sea, pero eso probablemente no importa tú.

Supongo que tiene ssh-agento una clave SSH sin frase de contraseña que permitirá que las reconexiones simplemente funcionen sin una entrada adicional de su parte.

Habrá una pequeña condición de carrera en la que si golpeas ^Cdurante la fracción de segundo imperceptible para los humanos durante una reconexión, podrías terminar matando el script en lugar de pasarlo ^Cal terminal del cliente, por lo que si sospechas que una conexión se bloquea no triture ^Cdemasiado celosamente.

La solución de software adicional más simple

Puede probar el programa autossh , que debería estar disponible en su repositorio de paquetes de Ubuntu.

Si necesita compilar desde la fuente o auditarlo, es un solo programa en C que se compila sin ninguna biblioteca adicional como dependencias, parece tener más inteligencia sobre la comprobación de la vida de la conexión que mi truco anterior, y también se envía con un rscreencomando de script conveniente que auto -se adjunta a screen.

Detalles

Como sshnormalmente se recupera

Solo para verificar, porque no me gusta decir cosas sin verificarme, realicé una pequeña prueba antes de responder:

Me conecté a mi WiFi con un dispositivo Linux, hice una conexión SSH a otro dispositivo en mi LAN, verifiqué que tenía una sshconexión que funcionaba con el otro extremo (podía ejecutar comandos, etc.), luego en el cliente desconecté el WiFi (causando la interfaz para ser desconfigurado: no más direcciones IP), ingresó un montón más de caracteres en la sesión ssh (sin respuesta, por supuesto) y luego se volvió a conectar a mi WiFi; la reconexión realmente falló al menos una vez debido a una mala señal y otros factores , luego finalmente me reconecté: esperé unos cinco segundos para que la sshsesión se recuperara, no pasó nada, así que presioné una tecla más, y la sshsesión inmediatamente volvió a la vida, con todas las teclas que había escrito durante la desconexión que aparecían en la línea de comando.

Vea, sshsolo escribe / lee en el socket de la red TCP hasta que el sistema operativo le dice que algo salió mal, y TCP en realidad es muy tolerante con las caídas prolongadas de la conexión.

Si se deja en sus propios dispositivos con la configuración predeterminada del kernel, la pila TCP en Linux tolerará felizmente que la conexión se quede completamente en silencio durante muchos minutos antes de declarar que la conexión está inactiva e informar un error: para sshcuando finalmente se dé por vencido, estamos hablando en el estadio. de ~ 30 minutos, o al menos lo suficientemente seguro como para durar un segundo o un minuto.

Debajo de las cubiertas, la pila TCP de Linux reintenta gradualmente los mensajes con retrasos cada vez más largos, lo que significa que para cuando vuelva su conexión, es posible que esté viendo un retraso adicional antes de que su sshsesión parezca "cobrar vida" nuevamente.

¿Por qué esto a veces se rompe?

A menudo, algo hace que la conexión se cierre activamente después de un período de inactividad significativamente más corto que la cantidad que tolerará la pila TCP, y luego no informa ese estado de conexión a su sshcliente.

Los candidatos probables incluyen:

  1. Los cortafuegos o enrutadores NAT, que tienen que usar memoria para recordar cada conexión TCP en vivo, como una optimización y alguna mitigación contra los ataques de DOS, a veces simplemente olvidan su conexión y luego ignoran silenciosamente los paquetes consiguientes, porque los paquetes en el En medio de una conexión cuando no recuerdas que la conexión existente parece no válida.

  2. Los cortafuegos / enrutadores con mejor comportamiento inyectarán un paquete TCP RST, que generalmente se manifiesta como un connection reset by peermensaje de error, pero el paquete de reinicio se dispara y olvida, por lo que si la conexión a su cliente todavía tiene problemas en ese momento y deja caer el restablecer el paquete también, su cliente pensará que la conexión sigue viva.

  3. El servidor en podría tener una política de firewall para eliminar silenciosamente paquetes inesperados, lo que interrumpiría los intentos de reanudación de la conexión del cliente cada vez que el servidor piense que la conexión se cerró pero el cliente no: su cliente sigue intentando continuar la conexión, pero el servidor simplemente ignorándolo porque no hay conexión en vivo a la que pertenecen estos paquetes en el estado del servidor de seguridad del servidor.

    Como está ejecutando Linux, revise cuidadosamente el servidor iptables/ ip6tables(o nftsi está usando las cosas nuevas) para saber exactamente lo que está permitiendo en lugar de dejarlo caer. Es muy común permitir paquetes nuevos / establecidos / relacionados en el puerto TCP SSH, pero no los "inválidos": si descarta silenciosamente todo lo que no está permitido, esta configuración común podría causar este tipo de bloqueos después de breves problemas de conexión .

  4. Su propio servidor SSH podría estar configurado para cerrar la conexión después de un período de inactividad, utilizando una de las opciones de OpenSSH para paquetes de keepalive del cliente TCP o SSH. Por sí solo, esto no causará bloqueos indefinidos, pero puede ubicarlo en uno de los estados descritos anteriormente.

  5. Es posible que simplemente no le esté dando suficiente tiempo para "destrabarse" por sí solo después de llegar al estado en el que sshcuelga su sesión.

mtraceur
fuente