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 ssh
TCP 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 ssh
y conectarse screen
. Pase el host o cualquier otra cosa que normalmente pasaría a su ssh
invocació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-agent
o 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 ^C
durante la fracción de segundo imperceptible para los humanos durante una reconexión, podrías terminar matando el script en lugar de pasarlo ^C
al terminal del cliente, por lo que si sospechas que una conexión se bloquea no triture ^C
demasiado 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 rscreen
comando de script conveniente que auto -se adjunta a screen
.
Detalles
Como ssh
normalmente 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 ssh
conexió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 ssh
sesión se recuperara, no pasó nada, así que presioné una tecla más, y la ssh
sesió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, ssh
solo 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 ssh
cuando 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 ssh
sesió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 ssh
cliente.
Los candidatos probables incluyen:
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.
Los cortafuegos / enrutadores con mejor comportamiento inyectarán un paquete TCP RST, que generalmente se manifiesta como un connection reset by peer
mensaje 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.
El servidor en sí 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 nft
si 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 .
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.
Es posible que simplemente no le esté dando suficiente tiempo para "destrabarse" por sí solo después de llegar al estado en el que ssh
cuelga su sesión.
<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!!
).