DEV Community

ant Kenworthy
ant Kenworthy

Posted on

SSH: Tunneling to remote servers

When creating our infrastructure, either in the cloud or on prem, we often usually need a way to connect to machines running behind the scenes to do things, such as upgrades or fixing problems.

Typically the tool of choice for most remote system administration work is ssh. openssh is probably the most common version of ssh that is used on systems today and is often pre-built and installed on your operating system.

When we need to connect to our web servers that are safely tucked behind a firewall on local IP addresses ( RFC1918 ) we can use SSH to tunnel through our bastion or jump-host, here's how:

Here's a basic diagram of how I'll be connecting to a web server:

  { Internet } ------ [ Jump-box ] ------ [ Web-server-1 ]

I need to connect to web-server-1 to fix an issue but it doesn't have direct exposure to the internet. I can use the jump-box to make that connection like so:


ssh -J jump-box.example.com web-server-1

That's it. It really is that simple!

You may notice that the webserver isn't using a fully qualified domain name such as web-server-1.example.com. This is because the ssh client will make use of the DNS configuration of the jump host to find web-server-1. If the DNS isn't configured properly on the jump-box, or you make a typo, you'll get an error message back saying it couldn't be found.

You can add as many servers to the -J option as needed in a comma separated format. The highest number of jumps I've made is 3. The client will connect to each of the servers in order to establish a connection to the end point web-server-1. An example maybe:


ssh -J jump-box.example.com,jump-box-2 web-server-1

Note : The -J option was introduced in openssh version 7.3. If you have an earlier version of the client the command line option may not be available to you.

The -J option is a shortcut for the ProxyJump configuration option. That you could find in your ssh client configuration files already ( .ssh/config for user configurations or /etc/ssh/ssh_config for system wide )

Example:
In my ssh client configuration it would look like this:


host web-server-1
 ProxyJump jump-box.example.com

This would create an alias for web-server-1 that the ssh client can use. Now I'd only have to type ssh web-server-1 and ssh would take care of the rest.

But wait, there's more!

An alternative method for doing this would be to use the proxy-command option:


ssh -o ProxyCommand="ssh -W %h:%p jump-box.example.com" web-server-1

This first starts an ssh connection to the jump box and then, with the -W option, requests that standard input and output on the client be forwarded to host on port over the secure channel

Sometimes the ssh client you have may not have these features or they could be restricted in some fashion. For this we have to revert to good old fashioned port forwarding.

In our first terminal we would run this command to setup a connection to the jump box but at the same time we ask it to listen on port 2222 on our local machine and pass those connections through to port 22 on web-server-1:


ssh -L 2222:web-server-1:22 jump-box.example.com

Then in our second terminal we would run this to initiate a connection to port 2222 on our local machine:


ssh -P 2222 localhost

Using port forwards in this way works well but becomes cumbersome if you need to connect to more than one jump-box or more than one endpoint within your network.

Ta-da! \o/

tldr: use ssh -J jump-box.example.com web-server-1 to tunnel ssh connections to web-server-1 via jump-box.example.com

Top comments (0)