client_loop: send disconnect: Broken pipe : empêcher SSH de se couper

La connexion réseau sous votre session SSH est morte, et ssh ne l'a su qu'en essayant d'envoyer quelque chose. La cause habituelle est un routeur ou un pare-feu qui oublie une connexion inactive. Ajoutez ServerAliveInterval 60 à ~/.ssh/config pour que la session ne soit jamais inactive, et utilisez tmux pour le travail qui doit survivre à un vrai changement de réseau.

Mis à jour le . Le message Broken pipe a été reproduit avec OpenSSH 10.3 sur macOS, via un proxy local qui réinitialisait la connexion TCP.

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, ssh abandonne après ServerAliveCountMax essais, 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.

Sources

Autres guides : Messages d'erreur

Tous les guides