Faster SSH with Multiplexing
- Feb 20, 2018
In this article you will learn how to fundamentally speed up SSH logins to your most frequently used hosts and go easy on the TCP connection limits your endpoints might have. Read on to learn how…
If you’re a CLI jockey like me, you probably have multiple (at least in my case, that’s a real understatement :-D) SSH connections open to the same servers at once. Waiting a few seconds for a new one might not seem like long. If you’re using a very large ECDSA private/public keypair for authentification or have a slow server (Raspberry PI anyone?) these logins might take even longer.
When using tools like ansible or editing files remotely (like with TRAMP mode for emacs), these seconds add up quickly. Luckily there is a simple way to speed things up substantially!
SSH: Negotiation & Multiplexing
When connecting, the client and server have to go through a whole ordeal before you get to do anything. A little simplified, all this has to be completed before you get to do anything:
- a TCP handshake is performed and TCP connection established
- the client and server negotiate supported protocols
- the client verifies the servers host key
- both negotiate sessions parameters (authentication method, compression, etc.)
- they exchange a symmetric session key for encryption
- the server checks the user’s identity
- now the secure data transfer is started
TODO: Add VizGraph here (Normal connection)
With multiplexing SSH can reuse existing TCP connections and tunnel multiple client requests through a single Unix socket. Therefore no new TCP connection has to be setup when a concurrent new SSH connection is established – e.g. you start a new shell via SSH or initiate a file transfer with SCP.
TODO: Add VizGraph here. (Multiplexed connection).
SSH Multiplexing with ControlMaster
Luckily enabling multiplexing is easily done. All you got to do is modify your ~/.ssh/config file. Open in in your favorite editor and add this:
Host * ControlMaster auto ControlPath ~/.ssh/master-%r@%h:%p
This configures SSH to create a Unix-socket in your .ssh directory for every new triplet of username (%r), host (%h) and port (%p) you open. The first log in to a new host will still need to setup a TCP and TLS connection and therefore won’t be faster. But any consecutive logins will be accelerated – a lot.
You should only configure SSH this way on your local workstation and if you are the only root or sudo enabled user on the system, as somebody might highjack any of your sockets at any time!
Theoretically, anyone with enough access rights to your .ssh directory could do this. Also, make sure your file and directory permissions are set to 600 or 700 respectively – you have been warned!
Persisting Multiplexed SSH Tunnels
SSH will not keep the connection open indefinitely with the default configuration. As soon as you logout of your last ssh sessions, the ControlMaster will be closed. If you want SSH to persist unused connections, for example, 2 hours after your last open session closed, you can achieve this with the following config:
Host * ControlMaster auto ControlPath ~/.ssh/master-%r@%h:%p ControlPersist 2h
You can also set
ControlPersist to Yes so sessions will be kept indefinitely. Or disable persisting completely with No.
Multiplexing for Specific Hosts
If you only want to enable for specific hosts or configure different ControlPersist settings per host, you can accomplish this by adding multiple
Host entries in your .ssh/config file:
Host example.com ControlMaster auto ControlPath ~/.ssh/master-%r@%h:%p ControlPersist 2h Host anotherexample.com ControlMaster auto ControlPath ~/.ssh/master-%r@%h:%p ControlPersist No
Working with SSH Multiplexing
Just use your normal ssh command, itself will take care of everything.
Checking up on Multiplexed Connections
If you want to see if you already have an open master connection to a specific host, enter the following command:
ssh -O check HOSTNAME
If yes, you’ll get a
Master running (pid=XXXX), if there is no connection at the moment
Control socket connect(...): No such file or directory. will be the response.
Closing Multiplexed Connections
You can manually close a connection to a specific host with this command:
ssh -O stop HOSTNAME
One problem you might have, especially if you have a wonky internet connection (like when using a laptop on the road) or using a dynamic IP address, is that connections might die and consecutive attempts to log in to a rnemote server might timeout and fail. Therefore you have to kill the multiplexed connection to reestablish it.
Using the stop command is definitely the more elegant solution than a
killall ssh. 🙂