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.

ssh jump host ssh jump host

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 or sftp 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.

proxy-settings proxy-settings