← back to latest

Reuse SSH connections instead of authenticating every time

ssh -o ControlMaster=auto -o ControlPath=~/.ssh/sockets/%r@%h-%p -o ControlPersist=600 devbox

anatomy

ssh
Open a secure shell connection. Each invocation normally runs the full TCP handshake and authentication sequence from scratch, even if you connected to the same host seconds ago.
-o ControlMaster=auto
If no existing control socket exists for this host, become the master and create one. If one already exists, use it. The auto setting means you never have to think about which terminal goes first.
-o ControlPath=~/.ssh/sockets/%r@%h-%p
Where to place the Unix domain socket that subsequent connections will reuse. %r is the remote user, %h the host, %p the port. Keeping sockets in a dedicated directory avoids clutter in /tmp.
-o ControlPersist=600
Keep the master connection alive for 600 seconds after the last session using it disconnects. Without this, the socket disappears the moment you close the first terminal, defeating the point.

Sample output

$ time ssh devbox echo ok
ok
ssh devbox echo ok    0.02s user 0.01s system 4% cpu 0.041 total

$ time ssh devbox echo ok   # without multiplexing
ok
ssh devbox echo ok    0.03s user 0.02s system 2% cpu 1.820 total

The first timing is a multiplexed connection reusing an existing socket: 41 milliseconds. The second is a cold connection with full TCP and key exchange: 1.8 seconds. The difference compounds fast when you run scp, rsync, or git push against the same host repeatedly.

When you would reach for it

You SSH into the same machine dozens of times a day, deploying code, tailing logs, running one-off commands. Each connection pays the full cost of TCP setup, key exchange, and authentication. With multiplexing, the first connection pays that cost once, and every subsequent connection to the same host piggybacks on it in milliseconds. The effect is most visible over high-latency links, through bastion hosts, or when a deploy script opens several SSH sessions in quick succession.

Gotchas

  • The socket directory (~/.ssh/sockets/) must exist before the first connection. Create it with mkdir -p ~/.ssh/sockets. SSH will not create it for you and will silently fall back to non-multiplexed connections.
  • If the master connection drops (network interruption, laptop sleep), every session sharing that socket hangs or dies. The -o ServerAliveInterval=60 option helps the master detect a dead link sooner.
  • Multiplexed connections share the master’s authentication. If you SSH as one user and then try to connect as a different user to the same host on the same port, the %r token in ControlPath keeps the sockets separate. Drop %r and you get confusing authentication failures.
  • Some older jump hosts or hardened servers disable multiplexing on their end with MaxSessions 1 in sshd_config. The connection will still work, but each session opens a new channel negotiation, and the speed benefit shrinks.

Variants

$ ssh -O check devbox

Check whether a master socket exists for this host. Prints the PID of the master process or reports that no socket is available. Useful for debugging when multiplexing seems to not be working

$ ssh -O exit devbox

Tear down the master connection and remove the socket. Use this before changing SSH config or when you need a clean reconnection. This closes all sessions sharing that socket, so check first

$ cat >> ~/.ssh/config <<'BLOCK'
Host *
  ControlMaster auto
  ControlPath ~/.ssh/sockets/%r@%h-%p
  ControlPersist 600
BLOCK

Move the options into your SSH config so every connection benefits without typing flags. The Host * block applies to all hosts. This is how most people use multiplexing in practice

lineage

SSH connection multiplexing arrived in OpenSSH 3.9, released in 2004, as part of a broader push by Damien Miller and the OpenBSD team to reduce overhead for workflows that open many short-lived connections to the same host. The ControlMaster directive let a single TCP connection and authentication exchange serve multiple logical sessions through a shared Unix domain socket. The feature was useful immediately but fragile in practice: if the master died, every multiplexed session died with it. ControlPersist, added in OpenSSH 5.6 in 2010, solved the worst of this by decoupling the master's lifetime from any individual session. By most accounts, the combination of ControlMaster, ControlPath, and ControlPersist was the single largest practical speedup available to heavy SSH users until connection resumption proposals began circulating years later.