How to use SSH with Proxies and Port Forwarding to get access to my Private Network

In my work, I have one single host with public access to ssh port (i.e. 22). The rest of my hosts have the ssh port filtered. Moreover, I have one cloud platform in which I can create virtual machines (VM) with private IP addresses (e.g. I want to start one web server in a VM and have access to that web server from my machine at home.

The structure of hosts is in the next picture:


So this time I learned…

How to use SSH with Proxies and Port Forwarding to get access to my Private Network

In first place I have to mention that this usage of proxy jumping is described as a real use case, and it is intended for legal purposes only.


$ ssh -L 10080:localhost:80 -J -J root@web.internal

My first attempt to achieve this was to chain ssh calls (will forget about port forwarding for the moment):

$ ssh -t ssh -t ssh root@web.internal

And this works, but has some problems…

  1. I am asked for a password at every stage (for main-ui, cloud-ui and web.internal). I want to use passwordless access (using my private key), but if I try to use ‘-i <private key>’ flag, the path to the files is always relative to the specific machine. So I would need to copy my private key to every machine (weird).
  2. I need to chain port forwarding by chaining individual port forwards.
  3. I will not work for scp.

I tried SSHProxyCommand options, but I found easier to use ProxyJump option (i.e. -J). So my attempt was:

$ ssh -J -J root@web.internal

And this works, but I have not found any way to provide my private key in the command line but for the target host (web.internal).

And now I figured out how to configure this by using ssh-config files (i.e. $HOME/.ssh/config). I wrote the next entries in that file:

IdentityFile ~/.ssh/key-for-main-ui.key

IdentityFile ~/.ssh/key-for-cloud-ui.key

Host *.internal

Using that configuration I can access to web.internal by issuing the next simple command:

$ ssh -i keyfor-web.key root@web.internal

And each file with each identity key written in the .ssh/config file y relative to my laptop, so I do not need to distribute my private key (nor create artificial intermediate keys).

The config file is also for the scp command, so I can issue commands like the next one:

$ scp -i keyfor-web.key  ./myfile root@web.internal:.

And ssh will make the magic!

Port forwarding

But remember that I also wanted to access to my web server in web.internal. So the easies way is to port forward port 80 to a port (e.g. 10080) in my laptop.

So using the previous configuration I can issue a command like the next one:

$ ssh -i keyfor-web.key -L 10080:localhost:80 root@web.internal

And now I will be able to open other terminal and issue the next command:

$ curl localhost:10080

and I will get the contents from web.internal.

Flag -L can be interpreted as (using the previous ssh call): connect using ssh to root@web.internal and forward to ‘localhost:80’ any traffic received in port 10080 from the client host.

If I had no ssh access to web.internal, I could issue the next alternate command:

$ ssh -L 10080:web.internal:80

In this case, -L flag will be interpreted as: connect using ssh to and forward to ‘web.internal:80’ any traffic received in port 10080 from the client host.

Final words

Using these commands I will need to keep the ssh session opened. In case that I wanted to forget about that session, and run port forwarding in background, I could use -f flag:

$ ssh -i keyfor-web.key -f -L 10080:localhost:80 root@web.internal 'while true; do sleep 60; done'