Jump Hosts and OpenSSH
The Problem
If you have used
ssh
to create a remote terminal session into a Linux or Unix machine, or if you have used related file transfer tools such as scp
or sftp
to transfer files between machines, you’ll be familiar with the idea that you’re establishing a point-to-point network connection, using the SSH protocol, from one machine (the client) to another (the server).
In the picture below, the laptop on the right is on the same network as the three servers (alvin, simon and theodore). It is able to establish that client-server connection, authenticate, and you have your ssh session.
But what about the laptop on the left? Due to the firewall and probably some stuff called NAT, it’s unlikely that the laptop on the left is able to establish network connectivity to the servers (alvin, simon and theodore) directly. When you’re at home or at the office, you can access those local resources, but when you’re remote, you can’t.
In these cases, it may be that the manager of the firewall might enable ssh on the firewall (or a machine near it in a DMZ) to act as a jump host. This would allow you to ssh from the laptop on the left, into the firewall machine and from there ssh to alvin, simon or theodore behind the firewall.
Here’s what an example session might look like:
mg@laptop$ ssh mg@jump-host.incomplete.io
mg@jump-host.incomplete.io's password:
mg@jump-host$ ssh mg@simon.incomplete.io
mg@simon.incomplete.io's password:
mg@simon$
This approach works, but does have some serious limitations:
- Using ssh public key authentication becomes more difficult (more below).
- Transferring files using
scp
orsftp
might mean copying to the jump host first and then to the real destination, where the jump host may not have the capacity or a writeable filesystem. - Escaping ssh
~
commands needs a~
per ssh hop, which can be difficult to keep track of after a few hops. - It’s very interactive, making it difficult to use with automation.
A ProxyJump Tunnel
It is possible to have the ssh
command handle the extra step for us by wrapping the SSH session we want inside an SSH session to the jump host. Using the ProxyJump
configuration option (or the -J
short option on the command line), we can have ssh
automatically establish the session to the jump host. From there, ssh
will tunnel our session to the servers over the jump host session. For example:
mg@laptop$ ssh -J mg@jump-host.incomplete.io mg@simon.incomplete.io
mg@jump-host.incomplete.io's password:
mg@simon.incomplete.io's password:
mg@simon$
This has many advantages over the two manual steps above, many stemming from the fact that the session to simon in the above example is from laptop to simon, being tunnelled through jump-host. This allows us to use tools like scp
to transfer files without having to store them on the jump host as part of the process. For example:
mg@laptop$ scp -o 'ProxyJump mg@jump-host.incomplete.io' ./some-file mg@simon.incomplete.io:
mg@jump-host.incomplete.io's password:
mg@simon.incomplete.io's password:
....
The scp
command doesn’t have the short -J
option, so we specify the long-form configuration option using -o
.
You can use the -J
option multiple times if you have multiple jump hosts to pass through.
Tunnelling Your Browser
As mentioned, the -J
option establishes a session to a jump host and then tunnels our SSH session to the remote server.
OpenSSH is able to tunnel all kinds of things, including web browser traffic. By using the -D
option and specifying an unused port number, ssh
can listen on your local client machine (laptop in the example above) as a SOCKS5 proxy. It will then tunnel any web requests it receives over the SSH session to the jump host, and make the request on the remote network.
For example:
mg@laptop$ ssh -D3128 -J mg@jump-host.incomplete.io mg@alvin.incomplete.io
mg@jump-host.incomplete.io's password:
mg@simon.incomplete.io's password:
mg@simon$
Then simply configure your web browser to use localhost as a SOCKS5 proxy with the port number specified with the -D
option. From there, you ought to be able to browse content inside your private network (perhaps hosted on simon, alvin and theodore), with the web browser traffic being tunnelled (encrypted) over your SSH session through the jump host.