SSH ControlMaster and ControlPath

One of my favorite SSH tricks is using the ControlMaster and ControlPath options for speeding up connections. The idea is simple: if you're already logged into a server and you need to log in again, just reuse the connection you already have instead of redoing the entire connection handshake. In addition to making connections much faster, if you're logging in with a password, you don't have to re-type your password for each connection. This can be really handy if you're doing a lot of copies with scp, checking out files with Subversion's svn+ssh://, etc., and don't want (SSH keys can also solve this problem in many cases, but requires you to set up keys on the server, whereas this just requires client-side configuration.)

Setting this up is easy. We'll designate one ssh process as a master, and then when another ssh process wants to connect to the same host, it will connect to the master process instead and request a shared connection. In order to make this work, we first have to set up a place for this master process to listen for requests.

To do this, add the line

ControlPath ~/.ssh/control-%h-%p-%r

to your ~/.ssh/config file. You can read more about the syntax in the ssh_config man page; this particular setting puts the shared sockets in your ~/.ssh directory, which is usually a good place for it, and makes sure that the path is unique for each hostname, port, and remote username, as recommended by the man page.

Then create the master ssh process by running it with the -M option. You'll get a normal login, which you can use or just keep around in a minimized window. You have to keep this connection around until you're done with all your other connections. If for some reason you want to avoid opening a shell — for instance, you're using this with GitHub, which doesn't let you open a shell — you'll also want the -N option.

Once you've done this, every new ssh process that's connecting to the same host (with the same username and port) will reuse the master connection instead of making its own. You don't need to do anything special; as long as ControlPath is set, each new ssh process will check for a master connection at that path.

As mentioned, this can make SSH significantly faster for repeated operations. For instance, git fetch against GitHub becomes over twice as fast for me, compared to re-doing SSH key authentication:

geofft@cactuar:~/src/vireo$ time git fetch

real    0m0.305s
user    0m0.005s
sys     0m0.011s
geofft@cactuar:~/src/vireo$ ssh -M -N -f git@github.com
geofft@cactuar:~/src/vireo$ time git fetch

real    0m0.140s
user    0m0.000s
sys     0m0.010s

This example also used the -f option, which puts the connection into the background as soon as authentication is complete. To close the connection, you can use the -O exit option to ssh, which, instead of opening a new connection, signals the ControlMaster process to exit.

geofft@cactuar:~/src/vireo$ ssh -O exit git@github.com
Exit request sent.
geofft@cactuar:~/src/vireo$ time git fetch

real    0m0.303s
user    0m0.010s
sys     0m0.007s

There's a good article on Wikibooks about connection multiplexing that covers more advanced use of this feature.

7 April 2014