Il messaggio
client_loop: send disconnect: Broken pipe
Nella nostra prova, un reset TCP sotto una sessione attiva ha stampato questo:
Read from remote host server: Connection reset by peer
client_loop: send disconnect: Broken pipe
I client più vecchi stampano lo stesso problema in un'altra forma:
packet_write_wait: Connection to 203.0.113.10 port 22: Broken pipe
Broken pipe significa che ssh ha scritto su una connessione che non esiste più. Non dice chi l'ha chiusa e non ha niente a che fare con le tue chiavi o la tua password.
Cause, in ordine di probabilità
1. Un router o un firewall ha chiuso una connessione inattiva
I router di casa, i firewall degli uffici e i gateway NAT del cloud tengono una tabella delle connessioni aperte e rimuovono quelle inattive, spesso dopo pochi minuti. La tua sessione sembra a posto finché non premi un tasto. L'indizio è che la sessione muore solo dopo che l'hai lasciata ferma, e a un momento abbastanza regolare. Una prova rapida è applicare la correzione qui sotto a una connessione e lasciarla inattiva più a lungo di quanto di solito sopravvive.
2. Il tuo computer è andato in stop o ha cambiato rete
Chiudere un portatile, o passare dal Wi-Fi all'hotspot del telefono, interrompe la connessione. Quando il tuo indirizzo cambia, nessun keepalive può salvarla. L'indizio è che succede subito dopo aver aperto il portatile o esserti spostato.
3. L'ha chiusa il server
Un riavvio, un crash o un timeout di inattività impostato dall'amministratore sembrano tutti simili dal tuo lato. Controlla l'uptime e il log del server, e cerca le impostazioni di inattività:
uptime
sudo journalctl -u ssh --since "1 hour ago"
sudo sshd -T | grep -iE '^(clientalive|channeltimeout|unusedconnectiontimeout)'
Una sessione chiusa di proposito dal server di solito stampa Connection to server closed by remote host. invece di Broken pipe.
La correzione sul client: ServerAliveInterval
Metti questo in ~/.ssh/config:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
Per provarlo una volta senza modificare alcun file:
ssh -o ServerAliveInterval=60 user@server
Dopo 60 secondi di silenzio dal server, ssh invia un piccolo messaggio attraverso la connessione cifrata e aspetta una risposta. Fa due cose:
- Il traffico mantiene la connessione nella tabella del router.
- Se le risposte si fermano,
sshrinuncia dopoServerAliveCountMaxtentativi, circa 3 minuti qui, invece di restare bloccato.
L'intervallo predefinito è 0, cioè disattivato, e il conteggio predefinito è 3. Se la tua connessione viene rimossa prima di un minuto, abbassa l'intervallo. Quando si raggiunge il limite, vedi questo:
Timeout, server 203.0.113.10 not responding.
Quel messaggio significa che il keepalive sta facendo il suo lavoro: la rete ha davvero smesso di rispondere.
Lo stesso sul server: ClientAliveInterval
Se gestisci il server e vuoi questo per tutti, aggiungi un file come /etc/ssh/sshd_config.d/keepalive.conf:
ClientAliveInterval 60
ClientAliveCountMax 3
Poi controlla e ricarica:
sudo sshd -t && sudo systemctl reload ssh
Su alcuni sistemi l'unità si chiama sshd. Oltre a mantenere vive le connessioni, questo ripulisce anche le sessioni di client scomparsi. Quando abbiamo congelato un client, il server ha registrato questo e ha chiuso la sessione:
Timeout, client not responding from user user 203.0.113.20 port 40896
TCPKeepAlive non è la stessa cosa
TCPKeepAlive è attivo per impostazione predefinita su entrambi i lati, e riattivarlo raramente aiuta. Ci sono due differenze:
- Lo invia il sistema operativo con i suoi tempi. Su Linux l'attesa predefinita è di 2 ore, troppo lunga per mantenere viva una voce nella tabella di un router.
- Sta fuori dal canale cifrato, quindi può essere falsificato. I messaggi server alive no.
Il manuale nota anche che il keepalive TCP fa morire le connessioni se una rotta cade per poco tempo. Se preferisci superare brevi interruzioni, puoi disattivarlo e affidarti al solo ServerAliveInterval.
Quando usare tmux invece
I keepalive impediscono che una connessione sana venga chiusa perché inattiva. Non possono salvare una sessione quando la rete sparisce davvero. Se la connessione termina, normalmente terminano anche la shell sul server e ciò che vi gira dentro.
Per i job lunghi, o se ti sposti tra reti, esegui il lavoro dentro tmux sul server:
tmux new -A -s work
Esegui lo stesso comando dopo esserti riconnesso e torni nella stessa sessione, con il job ancora in esecuzione. Vedi Mantenere vive le sessioni SSH con tmux. Usa entrambi: i keepalive per le cadute di tutti i giorni, tmux per ciò che non deve andare perso.
Se cambi rete spesso, un client Mosh va oltre: la sessione segue il nuovo indirizzo invece di chiudersi.
Domande
Cosa significa client_loop: send disconnect: Broken pipe?
La connessione di rete sotto la sessione SSH si è chiusa, e ssh se n'è accorto quando ha provato a inviare dati. Chiavi e password non c'entrano.
Che valore usare per ServerAliveInterval?
60 secondi vanno bene con la maggior parte di router e firewall. Se le sessioni inattive cadono prima di un minuto, usa 30. Con ServerAliveCountMax 3, una connessione morta si chiude dopo circa tre intervalli.
ServerAliveInterval tiene viva la sessione quando cambio rete?
No. Evita la chiusura per inattività su una connessione che funziona. Quando cambia il tuo indirizzo la connessione finisce, quindi esegui i lavori lunghi in tmux sul server oppure usa Mosh.