The configuration
mkdir -m 700 ~/.ssh/cm
Host server
HostName example.com
User user
ControlMaster auto
ControlPath ~/.ssh/cm/%C
ControlPersist 10m
ControlMaster autouses an existing connection if there is one, and otherwise opens a new one that others can share.ControlPathis the socket file that sessions use to find the connection.%Cis a hash of the local host, remote host, port, user and jump host, so different logins do not get mixed up.ControlPersist 10mkeeps the connection open for 10 minutes after the last session ends. Withno, the default, the connection lives inside the firstsshyou started, which stays open until every session on it has ended. Withyes, it stays open until you close it.
In our test, between two containers on one machine, the first ssh server true took 74 ms and the second took 3 ms. The second one skips the key exchange and login, so you also get no new password or passphrase prompt. Over a real network the first login is slower, so the gap is larger.
The same block can hold the rest of a host's settings. For more, see SSH config file examples.
Control the connection
| Command | What it does |
|---|---|
ssh -O check server | Prints Master running (pid=1534), exit code 0 |
ssh -O conninfo server | Shows the addresses and algorithms of the connection |
ssh -O forward -L 8080:localhost:80 server | Adds a port forward to the open connection |
ssh -O cancel -L 8080:localhost:80 server | Removes that forward |
ssh -O stop server | Accepts no new sessions, and running sessions continue |
ssh -O exit server | Closes the connection and every session on it |
ssh -S none server | Opens a separate connection and ignores the shared one |
When nothing is running, -O check exits with code 255:
Control socket connect(/home/user/.ssh/cm/936446a2...): No such file or directory
Limits and traps
All sessions share one fate
If the connection dies, every session on it dies. In our test, ssh -O exit ended a running session with exit code 255. The escape ~. also ends all sessions on the connection, as ssh itself says in its ~? list.
The server limits sessions per connection
MaxSessions in sshd_config defaults to 10. We opened 12 sessions at once, and the last 2 failed with:
mux_client_request_session: session request failed: Session open refused by peer
Those commands failed outright. They did not fall back to a new connection, so scripts that run many parallel commands need a higher limit or -S none.
The socket path can be too long
Unix socket paths have a short length limit. A path that is too long stops the connection:
unix_listener: path "/very/long/path/..." too long for Unix domain socket
A short folder with %C avoids this. The hash has a fixed length, unlike %r@%h:%p.
The socket gives access without a login
Anyone who can use the socket file can open sessions on your connection with no password. Keep it in a folder that only you can write to, which is why ~/.ssh/cm has mode 700. The manual warns about this too.
Long-lived tunnels should use their own connection
A forward started through a shared connection belongs to the master. In our test, with multiplexing on, a second ssh -f -N -o ExitOnForwardFailure=yes -R 2222:localhost:22 server on a port already in use returned exit code 0. Without multiplexing, the same command printed an error and returned 255. For a tunnel that scripts depend on, add -S none.
A killed master leaves a stale socket
After a kill -9 on the master, the socket file remains and -O check reports Connection refused. The next normal ssh server still worked in our test, and it replaced the socket. If it ever gets stuck, delete the file in ~/.ssh/cm.
Questions
Is SSH multiplexing safe?
Yes, when the socket is in a folder only you can write to, such as ~/.ssh/cm with mode 700. Anyone who can use the socket can open sessions on your connection without logging in.
Does ControlMaster work with the OpenSSH client on Windows?
The OpenSSH client that comes with Windows does not support ControlMaster, because it relies on Unix domain sockets. It works in WSL.
How do I close a multiplexed SSH connection?
Run ssh -O exit with the host name. It closes the connection and every session on it. ssh -O stop refuses new sessions and lets running ones finish.