Table of Contents
Introduction
Few things are as annoying as a productive SSH session that suddenly dies with:
client_loop: send disconnect: Broken pipe
You step away for a coffee, come back, and your connection is gone — along with whatever you were running in the foreground. This happens because an idle SSH session gets timed out, either by the server, an intermediate firewall/NAT device, or your own client giving up on a silent connection.
The good news: you can keep sessions alive with a simple keepalive mechanism. This guide covers the two steps that solve it — one on the server side and one on the client side. You can apply either independently, but together they make your SSH sessions rock-solid.
Why SSH Sessions Time Out
Before the fix, it helps to understand the culprits:
- Idle timeouts — a server or client closes connections that have sent no data for a while.
- Firewall / NAT timeouts — routers and firewalls drop idle TCP connections from their state tables (often after 5–30 minutes of silence).
- Unreliable networks — a brief drop with no traffic goes undetected until you try to type something.
The fix for all of these is the same: send a small keepalive packet at regular intervals so the connection never looks idle. SSH has this built in — you just need to enable it.
Step 1: Configure the Server (sshd_config)
Setting keepalives on the server keeps every client connected, without each user having to configure anything. This is the best option if you administer the server.
Edit the SSH daemon configuration:
sudo nano /etc/ssh/sshd_config
Add (or update) these two directives:
ClientAliveInterval 300
ClientAliveCountMax 3
What these mean:
| Directive | Purpose |
|---|---|
ClientAliveInterval 300 | The server sends a keepalive message to the client every 300 seconds (5 minutes) of inactivity. |
ClientAliveCountMax 3 | If the client fails to respond to 3 consecutive keepalives, the server closes the connection. |
With these values, the server tolerates up to 300 × 3 = 900 seconds (15 minutes) of true silence before disconnecting — but because it’s sending traffic every 5 minutes, idle firewalls and NAT devices never drop the session.
See also: Mastering the Linux Command Line — Your Complete Free Training Guide
💡 To keep sessions alive essentially indefinitely, you can raise the interval or the count. For example,
ClientAliveInterval 60withClientAliveCountMax 60sends a probe every minute and tolerates up to an hour of unresponsiveness.
Save the file, then restart the SSH service to apply the change:
# Debian/Ubuntu
sudo systemctl restart ssh
# RHEL/CentOS/Fedora
sudo systemctl restart sshd
⚠️ Safety tip: Keep your current SSH session open and test a new connection from another terminal before logging out — that way a config mistake won’t lock you out.
Step 2: Configure the Client
If you don’t control the server — say it’s a shared host or a cloud instance you’d rather not modify — you can fix timeouts entirely from your own machine. The client sends the keepalives instead.
Option A: Per-User Config (Recommended)
Edit (or create) your personal SSH config file. This applies only to your account and needs no root:
nano ~/.ssh/config
Add these lines to apply keepalives to all hosts you connect to:
Host *
ServerAliveInterval 300
ServerAliveCountMax 3
What these mean:
| Directive | Purpose |
|---|---|
ServerAliveInterval 300 | The client sends a keepalive to the server every 300 seconds of inactivity. |
ServerAliveCountMax 3 | After 3 unanswered keepalives, the client gives up and disconnects. |
Make sure the file has the correct permissions, or SSH may ignore it:
chmod 600 ~/.ssh/config
You can also scope it to a single host instead of Host *:
Host myserver
HostName 203.0.113.10
User admin
ServerAliveInterval 300
ServerAliveCountMax 3
Option B: System-Wide Client Config
To apply the same behavior for every user on your machine, add the directives to the global client config instead:
sudo nano /etc/ssh/ssh_config
Host *
ServerAliveInterval 300
ServerAliveCountMax 3
Option C: One-Off Command-Line Flag
For a quick, temporary fix without editing any files, pass the option directly:
ssh -o ServerAliveInterval=300 -o ServerAliveCountMax=3 user@server-ip
This is handy for a single session or for testing your values before making them permanent.
Server vs. Client: Which Should You Use?
Server (ClientAliveInterval) | Client (ServerAliveInterval) | |
|---|---|---|
| Where configured | sshd_config | ~/.ssh/config or ssh_config |
| Who it affects | All users connecting to that server | Only your outgoing connections |
| Needs server access? | Yes (root) | No |
| Best when | You administer the server | You’re a user of someone else’s server |
- Admin a server? Use Step 1 so no one gets disconnected.
- Just a user? Use Step 2 to fix it from your side, no server changes required.
- Want maximum reliability? Do both — belt and suspenders.
Verifying It Works
After configuring, connect and confirm the keepalives are active. Use verbose mode to watch the probes:
ssh -v user@server-ip
While idle, you’ll periodically see lines like:
debug1: Sending keepalive
You can also leave a session idle past the previous timeout window to confirm it survives. To inspect the effective server setting:
sudo sshd -T | grep -i clientalive
# clientaliveinterval 300
# clientalivecountmax 3
A Quick Note on TCPKeepAlive
You may also see the TCPKeepAlive directive. It’s related but different:
TCPKeepAlive yesuses the OS-level TCP keepalive, which can be spoofed by some devices and isn’t encrypted.ClientAliveInterval/ServerAliveIntervaloperate at the SSH protocol level, are encrypted, and are the preferred method.
For reliably defeating idle timeouts, stick with the AliveInterval settings above.
Conclusion
Keeping SSH sessions from timing out comes down to just two steps, and you only need whichever one fits your access level:
- Server side — add
ClientAliveInterval 300andClientAliveCountMax 3to sshd_config, then restart the SSH service. - Client side — add
ServerAliveInterval 300andServerAliveCountMax 3to~/.ssh/config.
Both work by sending a quiet keepalive packet on a schedule, so firewalls, NAT devices, and idle timeouts never get the chance to sever your connection. Configure the side you control — or both — and say goodbye to the dreaded broken pipe.
Now the current ssh connection timeout is 10 minutes (600 seconds). We can increase this value if needed. Check the detailed info about how to increase SSH timeout value in Linux here.
Related:



Thanks for sharing. I read many of your blog posts, cool, your blog is very good.