El mensaje
client_loop: send disconnect: Broken pipe
En nuestra prueba, un reinicio de TCP bajo una sesión en marcha mostró esto:
Read from remote host server: Connection reset by peer
client_loop: send disconnect: Broken pipe
Los clientes antiguos muestran el mismo problema de otra forma:
packet_write_wait: Connection to 203.0.113.10 port 22: Broken pipe
Broken pipe significa que ssh escribió en una conexión que ya no existe. No dice quién la terminó, y no tiene nada que ver con tus claves ni con tu contraseña.
Causas, de más a menos probable
1. Un router o firewall cortó una conexión inactiva
Los routers domésticos, los firewalls de oficina y las pasarelas NAT de la nube mantienen una tabla de conexiones abiertas y eliminan las inactivas, a menudo tras unos minutos. Tu sesión parece estar bien hasta que pulsas una tecla. La pista es que la sesión muere solo después de dejarla en paz, y a una hora bastante regular. Una prueba corta es aplicar la solución de abajo en una conexión y dejarla inactiva más tiempo del que suele sobrevivir.
2. Tu ordenador se suspendió o cambió de red
Cerrar un portátil, o pasar de Wi-Fi a un punto de acceso del móvil, termina la conexión. Cuando cambia tu dirección, ningún keepalive puede salvarla. La pista es que ocurre justo al abrir el portátil o al moverte.
3. El servidor la terminó
Un reinicio, una caída o un timeout de inactividad fijado por el administrador se ven parecidos desde tu lado. Comprueba el uptime y el log del servidor, y busca ajustes de inactividad:
uptime
sudo journalctl -u ssh --since "1 hour ago"
sudo sshd -T | grep -iE '^(clientalive|channeltimeout|unusedconnectiontimeout)'
Una sesión terminada a propósito por el servidor suele mostrar Connection to server closed by remote host. en lugar de Broken pipe.
La solución en el cliente: ServerAliveInterval
Ponlo en ~/.ssh/config:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
Para probarlo una vez sin cambiar ningún archivo:
ssh -o ServerAliveInterval=60 user@server
Tras 60 segundos de silencio del servidor, ssh envía un pequeño mensaje por la conexión cifrada y espera una respuesta. Esto hace dos cosas:
- El tráfico mantiene la conexión en la tabla del router.
- Si las respuestas se detienen,
sshse rinde trasServerAliveCountMaxintentos, unos 3 minutos aquí, en lugar de quedarse colgado.
El intervalo por defecto es 0, es decir, desactivado, y el contador por defecto es 3. Si tu conexión se elimina en menos de un minuto, reduce el intervalo. Cuando se alcanza el límite, esto es lo que ves:
Timeout, server 203.0.113.10 not responding.
Ese mensaje significa que el keepalive hace su trabajo: la red dejó de responder de verdad.
Lo mismo en el servidor: ClientAliveInterval
Si administras el servidor y quieres esto para todos, añade un archivo como /etc/ssh/sshd_config.d/keepalive.conf:
ClientAliveInterval 60
ClientAliveCountMax 3
Luego comprueba y recarga:
sudo sshd -t && sudo systemctl reload ssh
La unidad se llama sshd en algunos sistemas. Además de mantener vivas las conexiones, esto limpia las sesiones de clientes que han desaparecido. Cuando congelamos un cliente, el servidor registró esto y cerró la sesión:
Timeout, client not responding from user user 203.0.113.20 port 40896
TCPKeepAlive no es lo mismo
TCPKeepAlive está activado por defecto en ambos lados, y volver a activarlo rara vez ayuda. Hay dos diferencias:
- Lo envía el sistema operativo con su propio calendario. En Linux la espera por defecto es de 2 horas, demasiado para mantener viva la entrada de la tabla de un router.
- Va fuera del canal cifrado, así que puede falsificarse. Los mensajes de server alive no.
El manual también señala que el TCP keepalive hace que las conexiones mueran si una ruta está caída un rato corto. Si prefieres aguantar cortes breves, puedes desactivarlo y confiar solo en ServerAliveInterval.
Cuándo usar tmux en su lugar
Los keepalives evitan que se corte por inactividad una conexión sana. No pueden salvar una sesión cuando la red desaparece de verdad. Si la conexión termina, el shell del servidor y lo que corría en él normalmente terminan también.
Para trabajos largos, o si te mueves entre redes, ejecuta el trabajo dentro de tmux en el servidor:
tmux new -A -s work
Ejecuta el mismo comando tras reconectar y volverás a la misma sesión, con el trabajo todavía en marcha. Consulta Mantén vivas las sesiones SSH con tmux. Usa ambos: keepalives para los cortes cotidianos, tmux para lo que no debe perderse.
Si cambias de red a menudo, un cliente Mosh va más allá: la sesión sigue tu nueva dirección en lugar de cerrarse.
Preguntas
¿Qué significa client_loop: send disconnect: Broken pipe?
La conexión de red bajo tu sesión SSH terminó, y ssh se dio cuenta al intentar enviar datos. No tiene nada que ver con tus claves ni con tu contraseña.
¿Qué valor conviene para ServerAliveInterval?
60 segundos funcionan con la mayoría de routers y firewalls. Si las sesiones inactivas caen en menos de un minuto, usa 30. Con ServerAliveCountMax 3, una conexión muerta se cierra tras unos tres intervalos.
¿ServerAliveInterval mantiene la sesión si cambio de red?
No. Evita los cortes por inactividad en una conexión que funciona. Cuando cambia tu dirección, la conexión termina, así que ejecuta los trabajos largos en tmux en el servidor o usa Mosh.