Le message
client_loop: send disconnect: Broken pipe
Dans notre test, une réinitialisation TCP sous une session active a affiché ceci :
Read from remote host server: Connection reset by peer
client_loop: send disconnect: Broken pipe
Les clients plus anciens affichent le même problème sous une autre forme :
packet_write_wait: Connection to 203.0.113.10 port 22: Broken pipe
Broken pipe signifie que ssh a écrit sur une connexion qui n'existe plus. Le message ne dit pas qui l'a terminée, et il n'a rien à voir avec vos clés ou votre mot de passe.
Les causes, par ordre de probabilité
1. Un routeur ou un pare-feu a coupé une connexion inactive
Les routeurs domestiques, les pare-feu d'entreprise et les passerelles NAT du cloud gardent une table des connexions ouvertes et suppriment les inactives, souvent au bout de quelques minutes. Votre session semble normale jusqu'à ce que vous appuyiez sur une touche. L'indice : la session ne meurt qu'après avoir été laissée de côté, et à un moment assez régulier. Un test rapide consiste à appliquer la correction ci-dessous sur une connexion et à la laisser inactive plus longtemps qu'elle ne survit d'habitude.
2. Votre ordinateur s'est mis en veille ou a changé de réseau
Fermer un portable, ou passer du Wi-Fi à un point d'accès de téléphone, coupe la connexion. Quand votre adresse change, aucun keepalive ne peut la sauver. L'indice : cela arrive juste après l'ouverture du portable ou un déplacement.
3. Le serveur l'a terminée
Un redémarrage, un plantage ou un délai d'inactivité réglé par l'administrateur se ressemblent tous de votre côté. Vérifiez l'uptime et le journal du serveur, et cherchez les réglages d'inactivité :
uptime
sudo journalctl -u ssh --since "1 hour ago"
sudo sshd -T | grep -iE '^(clientalive|channeltimeout|unusedconnectiontimeout)'
Une session terminée volontairement par le serveur affiche en général Connection to server closed by remote host. plutôt que Broken pipe.
La correction côté client : ServerAliveInterval
Mettez ceci dans ~/.ssh/config :
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
Pour l'essayer une seule fois sans modifier de fichier :
ssh -o ServerAliveInterval=60 user@server
Après 60 secondes de silence du serveur, ssh envoie un petit message dans la connexion chiffrée et attend une réponse. Cela fait deux choses :
- Le trafic maintient la connexion dans la table du routeur.
- Si les réponses s'arrêtent,
sshabandonne aprèsServerAliveCountMaxessais, soit environ 3 minutes ici, au lieu de rester bloqué.
L'intervalle par défaut est 0, c'est-à-dire désactivé, et le nombre d'essais par défaut est 3. Si votre connexion est supprimée en moins d'une minute, réduisez l'intervalle. Quand la limite est atteinte, vous voyez ceci :
Timeout, server 203.0.113.10 not responding.
Ce message signifie que le keepalive fait son travail : le réseau a vraiment cessé de répondre.
La même chose côté serveur : ClientAliveInterval
Si vous gérez le serveur et voulez cela pour tout le monde, ajoutez un fichier comme /etc/ssh/sshd_config.d/keepalive.conf :
ClientAliveInterval 60
ClientAliveCountMax 3
Puis vérifiez et rechargez :
sudo sshd -t && sudo systemctl reload ssh
L'unité s'appelle sshd sur certains systèmes. En plus de garder les connexions actives, cela nettoie les sessions des clients disparus. Quand nous avons gelé un client, le serveur a journalisé ceci et fermé la session :
Timeout, client not responding from user user 203.0.113.20 port 40896
TCPKeepAlive n'est pas la même chose
TCPKeepAlive est activé par défaut des deux côtés, et le réactiver aide rarement. Il y a deux différences :
- Il est envoyé par le système d'exploitation selon son propre calendrier. Sous Linux, l'attente par défaut est de 2 heures, bien trop longue pour garder vivante une entrée de la table d'un routeur.
- Il passe en dehors du canal chiffré, donc il peut être falsifié. Les messages server alive ne le peuvent pas.
Le manuel note aussi que le keepalive TCP fait mourir les connexions si une route est coupée un court instant. Si vous préférez supporter de brèves pannes, vous pouvez le désactiver et vous reposer uniquement sur ServerAliveInterval.
Quand utiliser tmux à la place
Les keepalives empêchent qu'une connexion saine soit coupée pour inactivité. Ils ne peuvent pas sauver une session quand le réseau disparaît vraiment. Si la connexion prend fin, le shell sur le serveur et ce qui y tourne se terminent normalement aussi.
Pour les longs travaux, ou si vous changez de réseau, lancez le travail dans tmux sur le serveur :
tmux new -A -s work
Lancez la même commande après la reconnexion, et vous retrouvez la même session, avec le travail toujours en cours. Voir Garder les sessions SSH actives avec tmux. Utilisez les deux : les keepalives pour les coupures de tous les jours, tmux pour ce qui ne doit pas être perdu.
Si vous changez souvent de réseau, un client Mosh va plus loin : la session suit votre nouvelle adresse au lieu de se fermer.
Questions
Que signifie client_loop: send disconnect: Broken pipe ?
La connexion réseau sous votre session SSH s'est terminée, et ssh s'en est aperçu en essayant d'envoyer des données. Vos clés et votre mot de passe n'y sont pour rien.
Quelle valeur choisir pour ServerAliveInterval ?
60 secondes conviennent à la plupart des routeurs et pare-feu. Si les sessions inactives tombent en moins d'une minute, utilisez 30. Avec ServerAliveCountMax 3, une connexion morte se ferme après environ trois intervalles.
ServerAliveInterval garde-t-il la session quand je change de réseau ?
Non. Il évite la coupure pour inactivité sur une connexion qui fonctionne. Quand votre adresse change, la connexion se termine : lancez les travaux longs dans tmux sur le serveur, ou utilisez Mosh.