At this point, it should basically be “Stupid SSH tricks™”, but whatever.
Prerequisites: Basic understanding of *nix and SSH
You have a server behind a firewalled network and you need to connect. You could just do something like
ssh first-server and from there
ssh internal-server. Not too bad, right?
What if there’s a whole subnet of servers that you might wanna reach? What if you don’t wanna SSH twice? What if you’re using something that wants to execute from your local machine but can’t really handle the manual two step SSH jump (such as Ansible)
This is where SSH Multiplexing comes in very handy
Solution, part 1: Pivot box
As you probably expected by now, we’re going to be digging into our ssh config file, so go ahead and pop an editor open to
The first thing we want to do is setup our “gateway” or “bastion” or “jump” host. Whatever you want to call it. Doesn’t matter to me. Here’s an excerpt of mine with a breakdown of each line in the config
host jump User fraq Hostname foo.bar.baz ControlMaster auto ControlPath ~/.ssh/proxy-%[email protected]%h:%p ControlPersist 5m
host jump defines a friendly name in SSH for your machine. Note that this isn’t in
/etc/hosts, so you can’t
ping jump, but you can
ssh jump. When you do use
ssh jump, ssh opens up the config file, looks for a host entry that matches, and then uses that config to build the connection. Nothing we haven’t covered already in previous chapters.
User fraq is the username we use to connect to
Hostname foo.bar.baz means that we connect to a server called
foo.bar.baz in DNS. This can also be an IP address.
These next three are the ones you need for multiplexing:
ControlMaster auto tells the ssh connection that you want to listen for control connections (used for multiplexing)
ControlPath tells ssh where to put the control socket for the connections and how to format the file names. Per the OpenSSH cookbook:
The combination %r, %h and %p stand for the remote user name, the remote host and the remote host’s port. The control sockets should be given unique names.
ControlPersist tells ssh how long to leave the master open.
Solution, part 2: Target box
Now that your jump host is setup to accept multiplexed SSH connections, it’s time to tell the SSH how to connect to your target box through the jump box.
Host target ProxyCommand ssh -W %h:%p jump User fraq Hostname 10.10.10.10
As you can see, it looks very similar to a standard config file, except for the
ProxyCommand option. This tells the ssh connection to execute that command first as a prerequisite for connecting to the target machine. In our case, we’re saying that we want to
ssh -W through the machine known to ssh as
With this in place, you can now use
jump as a pivot to get into internal networks that it can access but you cannot, all without having to
ssh twice manually. This means scripts or tools that invoke
ssh can be used locally on your machine as well.
And yes, this can be chained basically indefinitely, so you can create some pretty long and crazy proxy connections.
Also, I very intentionally skipped over the in-depth explanation of
ssh -W and the older
ssh nc implementation. The whole purpose of this post was just to setup ssh multiplexing.