chaining ssh tunnels

Imagine you're working within a private home network and need to connect to an Oracle database within a corporate network accessible only through a bastion host hidden within the corporate network. Odd as that sounds, it's a typical network configuration, as follows:

The layout is very simple, when you're within the corporate network you must use the bastion host to access the vault (e.g., the Oracle database). The arrows in the above diagram represent the directionality of the various firewall rules, and in this case, these are SSH-only. A workstation within the corporate network would simply create an SSH-tunnel through the bastion to the vault.

Technically, there's a line of (completely separate) SSH connections from the private home network all the way to the vault, but there is absolutely no way for either side to talk directly. And further, there is no way for an Oracle client on the home network to connect all the way to the vault.

Each line could represent an SSH-tunnel, in which case, if we chain these tunnels together, then we could connect to the vault from the home network. This would allow an Oracle client (such as SQL Developer, Toad, or DbVisualizer) on the home network to connect through the SSH-tunnel chain to the vault.

step 1

For starters, we'll need all the arrows pointing the right way, we can use a reverse SSH tunnel from the corporate workstation, as follows

$ ssh -R 54321:localhost:22 user@internet-server

This will allow the internet-server to connect into the corporate workstation. However, this command must be run from within the corporate network. We can persist a reverse tunnel using the approach discussed in a previous article, see reverse ssh tunnel.

Persisting this reverse tunnel effectively points all arrows from the home network to the vault. At this point you could simply SSH from one host to another and eventually get to the vault, but this does not help us connect our Oracle client to the vault. We'll need to chain everything together, and we'll need to do this all from the home network.

step 2

Once an SSH-tunnel has been persisted between the corporate workstation and the internet-server, we can create a new tunnel from the home network into the corporate workstation. From the home network we'll issue the following command:

$ ssh -f user@internet-server -L 12345:localhost:54321 -N

Now we have a local port on the home network that connects into the corporate workstation, effectively chaining the reverse tunnel (tcp/54321) to a new tunnel (tcp/12345).

As an example, we could use this new tunnel as a SOCKS5 proxy, e.g.,

$ ssh -f -N -D 8080 user@localhost -p 12345

From the home network, we could now set our web browser to use a proxy on localhost:8080 to securely access the corporate network. This is already incredibly useful (replacing a VPN with SSH), but we still don't have access from the home network into the vault.

step 3

Now that the home network has a connection into the corporate workstation, we'll need to send a command to the workstation to create a tunnel through the bastion to the vault. From the home network we'll issue the following commands:

$ VAULT_TUNNEL="ssh -f user@bastion -L 1520:vault:1520 -N"
$ ssh user@localhost -p 12345 "$VAULT_TUNNEL"

This gives us a tunnel from the corporate workstation into the vault.

step 4

Now we can link the vault tunnel to the home network tunnel. From the home network we'll issue the following command:

$ ssh -f user@localhost -p 12345 -L 1520:localhost:1520 -N

What this does is create a new tunnel through the local tcp/12345 (which is the doubly-chained tunnel into the corporate network) to tcp/1520 on the other end (which itself is a tunnel into the vault). This new tunnel links everything together such that the home network now has a local port tcp/1520 into the Oracle database.

Simply point Toad (or SQL-Developer or DbVisualizer or whatever) to localhost:1520 on your home network and you'll be accessing the database through a triple-chained forward SSH tunnel.

all together

Since everything (except the reverse SSH tunnel) originates from the home network, we can create one shell command to establish this connection in one go. It's also a good idea to use an ssh agent across multiple hosts, but you could also just forward your auth credentials to avoid having to enter a password multiple times. Although in some cases password prompts may be unavoidable, for example, a decently secure bastion may not allow agent forwarding (or authorized_keys in general) and may even require secure keyfob access- in that case you'll simply have to enter the password when creating the chain of tunnels.

This entry was posted in bash, shell tips, ssh. Bookmark the permalink.