Skip to content
Go back

SSH Multiplexing: Stop Reconnecting Every Time

By SumGuy 5 min read
SSH Multiplexing: Stop Reconnecting Every Time

Every time you SSH, OpenSSH negotiates a connection, authenticates, and sets up encryption. On a slow link, that’s 2-3 seconds gone.

Do it 50 times a day? You’ve wasted 100 seconds before lunch.

SSH multiplexing reuses connections. First connection is normal. Every other one piggybacks on that socket. Result: instant SSH.

How It Works

SSH creates a control socket. Subsequent connections to the same host use that socket instead of creating a new one.

Terminal window
# First connection: slow (normal negotiation)
$ time ssh prod ls /
real 0m2.134s
# Second connection: fast (reuses socket)
$ time ssh prod ls /
real 0m0.042s

100x faster. No password, no auth delay. Just traffic through the existing socket.

Setup: Three Lines

Add to your ~/.ssh/config:

~/.ssh/config
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%h-%p-%r
ControlPersist 600

That’s it:

Create the socket directory:

Terminal window
mkdir -p ~/.ssh/sockets
chmod 700 ~/.ssh/sockets

Done. Test it:

Terminal window
$ ssh prod 'echo first'
first
$ ssh prod 'echo second'
second

The second one should be instant.

Verify It’s Working

Check for socket files:

Terminal window
$ ls -la ~/.ssh/sockets/
total 0
srwx------ 1 user user 0 Apr 2 10:00 prod.example.com-22-admin
that's the socket (s = socket)

The s in -rw- means socket. Only the owner can access it (for security).

Or ask SSH directly:

Terminal window
$ ssh -O check prod
Master running (pid=12345)
$ ssh -O check nonexistent
No ControlPath specified, cannot check control master status

Control It Manually

While a socket exists, you can:

Terminal window
# Stop multiplexing for this host
$ ssh -O exit prod
# Close all multiplexed connections
$ ssh -O exit -S ~/.ssh/sockets/\*

Or kill the socket:

Terminal window
rm ~/.ssh/sockets/prod.example.com-22-admin

Real-World Example: Rapid SCP

Copying multiple files without multiplexing:

Terminal window
$ time for f in file{1..10}; do scp prod:~/data/$f .; done
real 0m25.000s
# 2.5 seconds per SCP (connection overhead)

With multiplexing:

Terminal window
# First connection establishes socket
$ ssh prod ls / > /dev/null
# Now SCPs reuse it
$ time for f in file{1..10}; do scp prod:~/data/$f .; done
real 0m2.500s
# 0.25 seconds per SCP (mostly just transfer)

10x faster.

Rsync Without Pain

Rsync is SSH-heavy (lots of small operations):

Terminal window
# Without multiplexing: crawls
$ rsync -av prod:~/source/ ./dest/
# Each file operation = new SSH connection
# With multiplexing: zip
$ ssh prod ls / > /dev/null # Prime the socket
$ rsync -av prod:~/source/ ./dest/
# Reuses socket for all operations

ControlPersist Explained

ControlPersist 600 means:

“Keep the socket open for 600 seconds after the last connection exits.”

So:

Terminal window
$ ssh prod cmd1
# Connection exits, but socket stays open for 10 min
$ sleep 30; ssh prod cmd2
# cmd2 reuses the existing socket (still fresh)
$ sleep 800; ssh prod cmd3
# Socket is dead, so this creates a new one

For always-on sessions, use:

~/.ssh/config
Host prod
ControlMaster auto
ControlPath ~/.ssh/sockets/%h-%p-%r
ControlPersist yes

Socket persists until you manually close it.

Combining With Config

Put it in your Host blocks for maximum control:

~/.ssh/config
# Multiplexing for everything
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%h-%p-%r
ControlPersist 600
# Except this one (security-sensitive)
Host secure-server
ControlMaster no

Security Considerations

Socket lives in your home directory. If your home is NFS-mounted or accessible to others, someone could hijack the socket.

Fix it:

Terminal window
chmod 700 ~/.ssh/sockets
# Only you can access the directory

SSH checks socket ownership anyway (won’t use it if group/others can write).

For sensitive hosts, disable multiplexing:

~/.ssh/config
Host secure-prod
ControlMaster no

Performance: Numbers

Baseline (no multiplexing):

Terminal window
$ for i in {1..10}; do time ssh prod 'echo x'; done
# Average: ~2 seconds per connection

With multiplexing:

Terminal window
$ ssh prod 'echo x' # Establish socket (2 sec)
$ for i in {1..10}; do time ssh prod 'echo x'; done
# Average: ~0.05 seconds per connection

40x speedup after priming.

Over slow links (high latency):

Bandwidth unchanged. Latency is the win.

Gotchas

ControlPath too long: Linux has a max socket path length (~108 chars). If your hostname is long, the path might exceed it.

Terminal window
# Check your limit
python3 -c "import socket; print(socket.AF_UNIX)" # Usually 108
# If using long hostnames, shorten the path
ControlPath ~/.ssh/m/%h-%p

Stale sockets: If SSH crashes, the socket lingers. You may get weird errors. Just delete it:

Terminal window
rm ~/.ssh/sockets/*

Different users, same host: Use %r (remote user) in ControlPath so each user gets their own socket:

~/.ssh/config
ControlPath ~/.ssh/sockets/%h-%p-%r

TL;DR

Three lines. Instant SSH. Worth it.

~/.ssh/config
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%h-%p-%r
ControlPersist 600

Your fingers—and your patience—will thank you.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it may appear here.


Previous Post
Why Your Cron Job Is Failing Silently
Next Post
The Linux OOM Killer: Why It's Killing Your App

Related Posts