Fork me on GitHub

Making your SSH sessions fast

SSH is great. But it does inevitably introduce some delays as whenever you use it, SSH has to:

  • Establish a TCP connection to the remote host. (1.5 network roundtrips)
  • Verify the identity of the remote host (another network roundtrip)
  • Authenticate to the remote host (another network roundtrip)
  • Set up encryption keys for this session (another network roundtrip)
  • Start the remote command

Which ends up as (at least) 4 or 5 network round trips. If you are connecting to a host which is 100ms away (i.e. has a ping roundtrip of 100ms), then this is basically 0.5 seconds. Not bad, but quite noticeable for interactive use - especially if you are "in the zone". And even more so if you are running a script which runs SSH a lot..

And this is for the "simple" case - if your ssh session has to jump through proxies and/or bastion hosts, these add their own delays.

It is basically annoying.

Luckily, SSH (OpenSSH >= version 4.0) has a way of short-circuiting this, by re-using previous sessions (and piggybacking onto existing sessions), by keeping existing sessions open for a while even after you have finished using them. This is 100% client-side logic; the SSH server is blissfully unaware and can thus be an older version.

Unfortunately, this is not the default for SSH - but you can make it your default by adding this to the bottom of your $HOME/.ssh/config:

Host *
  ControlPersist 5m
  ControlMaster auto
  ControlPath ~/.ssh-%u@%l-%r@%h:%p.sock
  # Note that %u/%r/%p requires OpenSSH >= 4.2

(For the technically curious: The ControlPath specifies a pipe file that your SSH client processes can use to talk to each other. When re-using a connection, you need to make sure you re-use a SSH session to the same host (and same login user) - hence the need to have %r and %h in it, which SSH will replace with the username/hostname. If you use the same ControlPath for all connections (i.e. a path without any %-replacements) you will end up with very confusing "crosstalk" between them: When you SSH somewhere, you risk ending up somewhere else! The pipe file need to be placed where other users cannot read/write, lest they can piggyback on your connections and impersonate you on remote hosts...)

For the initial ssh connection to a host, SSH still has to do everything listed above. But when you have finished using the SSH connection, it will be kept open (in the background) for up to 5 minutes.

And if you SSH to the same host again within those 5 minutes then SSH can re-use the previous session - or even or piggyback onto an existing session.

End result: You cut out at least 0.5 seconds off the next SSH command. When working with hosts which are very remote (e.g. from the UK to Australia) this can easily shave 3-4 seconds of your work flow for each command.