Fixing “client_loop: send disconnect: Broken pipe” in SSH — A Practical Guide

SSH dropping with client_loop: send disconnect: Broken pipe? It’s usually an idle timeout or flaky network. This guide shows quick client fixes (ServerAliveInterval, TCPKeepAlive, IPQoS), sensible server defaults (ClientAliveInterval), and a fast diagnosis playbook using ssh -vvv and server logs. We also cover resilient workflows—tmux, rsync, and mosh—so brief outages don’t kill your work.

Table of Contents

If your SSH session suddenly drops with the message:

…you’ve hit a common—but fixable—network or keepalive issue. In this post we’ll show quick client-side remedies, server-side hardening, and a few diagnostics to pinpoint the root cause. Whether you’re connecting to a cloud VM, an on‑prem server behind a firewall, or a laptop on hotel Wi‑Fi, these steps will make your connection far more reliable.


TL;DR

Add keepalives to your SSH client and (optionally) your server. Start here:

Make it permanent by adding this to ~/.ssh/config:

If you control the server, add:

Reload SSH: sudo systemctl reload sshd (or service ssh reload).


Why this happens

“Broken pipe” means your SSH client tried to send data but the underlying TCP connection was gone. Common reasons:

  • Idle/NAT timeouts: Firewalls, load balancers, and carrier‑grade NATs often kill quiet TCP sessions.
  • Flaky networks or roaming Wi‑Fi: Short drops sever long‑lived connections.
  • Aggressive security appliances: Intrusion prevention may reset idle or long sessions.
  • MTU/QoS oddities: Some networks deprioritize or fragment small keepalive packets.
  • Rekey intervals: Infrequent, but if disconnects occur at clockwork intervals, rekey negotiation might be failing.

Quick client-side fixes

Start with temporary flags to confirm keepalives solve it. If they do, bake them into your config.

Make it permanent in ~/.ssh/config:

Tip: ServerAlive* are application-level keepalives. TCPKeepAlive leverages the OS stack. Using both increases your odds through finicky middleboxes.


Server-side hardening (if you’re the admin)

Give your users a more resilient baseline by enabling server keepalives and sensible TCP keepalive sysctls.

OpenSSH:

Reload sshd:

Kernel TCP keepalives: (system-wide safety net)

Firewalls & LBs: Increase stateful TCP idle timeouts (often 300–900s works well for SSH).


Fast diagnosis playbook

When it still drops, get a quick read on what’s failing.

  1. Verbose client logs

    Look near the end for timeouts, rekey notices, or sudden disconnect messages.
  2. Server logs
    • Debian/Ubuntu:
    • RHEL/Alma/CentOS:
  3. Pattern check
    • Many sessions drop at once? Suspect upstream firewall/LB.
    • Only idle shells die? Turn up ClientAliveInterval/ServerAliveInterval.
    • Drops exactly every N minutes? Check firewall state timers or SSH rekey limits.
  4. Network sanity
    • If you’re on VPN/coffee shop Wi‑Fi/hotel: expect aggressive NAT. Use short intervals (30–60s) and IPQoS 0.
    • If large transfers die midway, prefer resilient tools.

Working around unstable links

  • Use mosh for interactive shells over spotty networks. Mosh tolerates roaming, IP changes, and brief outages gracefully. (You’ll still use SSH for scp/rsync.)
  • Use rsync wisely for big copies:

    This resumes instead of restarting from zero.
  • Screen/Tmux: Always run long tasks inside tmux or screen so a dropped session doesn’t kill your process. Reattach after reconnect:

Less common culprits (but worth a try)

  • MTU/fragmentation: If you’re traversing VPNs, test a lower MTU at the OS or VPN level.
  • QoS deprioritization: IPQoS 0 (client) avoids DSCP markings that some networks punish.
  • Rekey intervals: If disconnects hit, say, every 60 minutes, align RekeyLimit between client and server. Example on the server:

A sensible default checklist

  1. Client: Add ServerAliveInterval 60, ServerAliveCountMax 3, TCPKeepAlive yes, IPQoS 0.
  2. Server: Enable ClientAliveInterval 60, ClientAliveCountMax 3, TCPKeepAlive yes; reload sshd.
  3. Network: Bump firewall/LB idle timeouts to ≥10 minutes for SSH.
  4. Workflows: Use tmux and resilient transfer tools (rsync --append-verify).
  5. Still failing? Capture ssh -vvv logs and check server logs to isolate NAT vs. host problems.

Conclusion

“client_loop: send disconnect: Broken pipe” is frustrating, but the fix is rarely mysterious. Keepalives mitigate idle timeouts, small config tweaks smooth over finicky middleboxes, and resilient tools protect your work during the occasional network hiccup. Apply the client defaults, harden the server if you can, and you’ll turn random drops into a rare event.

Have a project or a problem?

Talk with a senior engineer for practical recommendations—no obligation.

Leave a comment

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts

Categories

Get a free consultation from Reliable Penguin

Submit the form—or for immediate service call 866-649-7984.