- Published on
SSH Gymnastics - Jump Hosts and Port Forwarding
- Jarred Kenny
SSH Jump Hosts connections to be chained and routed via many servers and is often useful for connecting to servers where firewall restrictions may prevent you from connecting directly.
These proxy hosts have many names but are refereed to officially by SSH as "Jump Hosts" however the term "Bastion Host" is also very common.
Using Jump Hosts
Jump hosts are simple to use and can be set using
ssh on the command line or permanently within your users SSH configuration. (
1. Command Line
SSH can be instructed to route a connection via a jumphost using the
-J command line option.
For example, lets say we have two servers running known as
hostA is available on the public internet as well as a private network or VPC, while
hostB is only available on our private network or VPC.
We can connect to
hostA with the following command:
ssh -J user@hostA user@hostB
2. Using ~/.ssh/config
In cases where you want every connection you make to a server to be routed via a jump host or many jump hosts, you can permanently configure behaviour for a server in
Let's continue with
hostB. We know that
hostB can only be reached via
hostA. In this case, your
~/.ssh/config would look something like this:
Host hostA Hostname hostA Port 22 User root Host hostB ProxyJump hostA
This configuration is equivalent to our command line example, however there is far greater flexibility offered when using
~/.ssh/config to configure connections. For example, you can use wildcards to match hosts whose connections you may want to route via a jump host.
Lets say we wanted to route
anything could be the hostname of any one of your servers on that domain. We simply need to make one change to the configuration above.
Host hostA Hostname hostA Port 22 User root Host *.mydomain.com ProxyJump hostA
Adding Port Forwarding
Combining Jump Hosts with SSH's build in port forwarding is an incredibly useful tool for connecting to remote services with complicated firewall restrictions.
You have a database server running in a VPC and due to firewall rules you have in place the DB server can only be connected to from your application server. Your application server is also on a secure private network and can only be accessed via SSH from a dedicated SSH bastion which has both a public IP address and a private IP address on your internal network.
Your goal, use SSH to create a local tunnel to the database server from the application server via the bastion host. We can use SSH port forwarding here to forward a local port to the database server via the tunnel.
We will say the database server is
db1, the application server is
app1, and the bastion host is
Consider the following command:
ssh -N user@app1 -J user@jump1 -L 3306:db1:3306
What does it do?
-Ninstructs SSH not to open an interactive shell and in this case only establish the connection for port forwarding
user@app1specifies the user and server we are establishing a connection to
-J user@jump1instructs SSH to use
jump1as a jump host to establish our connection
-N 3306:db1:3008tells SSH that when the connection is established forward port 3306 on your local system to port 3306 on
db1via the SSH tunnel.
In this example, you can now talk to the database at
localhost:3006 and the network traffic is actually routed to
jump1 and then
Jump hosts are an incredibly powerful feature of SSH and are so easy to configure that you can often set it and forget it. You can combine this features with SSH port forwarding, X11 session forwarding, or SSH agent forwarding and navigate any number of restricted or complicated network setups.
I have to admit there has been a number of times I could no longer to connect to one of my servers because I forgot that there was a jumphost configured in my SSH configuration and I had actually taken the jump host down. Luckily, you can take management of your SSH configuration to any extreme you desire, from making local edits on your system to pushing our a shared SSH configuration to your entire team.