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'

How to automatically SSH to a non-default port and other cool things of SSH

In the last months I have been working with MPI. In particular, with OpenMPI. The basis of the work of OpenMPI consist in SSH-ing without password to the nodes that are part of a parallel calculation.

The problem is that in my case I was not using the default SSH port because I was trying to use OpenMPI with Docker and the SSH server is mapped to other port (in a later post I will write about this). And so this time I learned…

How to automatically SSH to a non-default port and other cool things of SSH

Yes, I know that I can SSH to a non default port using a syntax like this one:

$ ssh me@my.server -p 4000

But the problem is that in some cases I cannot change the commandline. As an example, when using OpenMPI, it is not possible to modify the port to which the master will SSH the slaves. It will just ssh the slaves.

At the end, SSH has the possibility of creating a ssh-config file that enables to change the port to which the SSH client will try to connect, and also will enable to configure some other cool things. I found a very straightforward explanation about the SSH config file in this post.

So making that a ssh me@my.server will connecto to the port 4000 without including it in the commandline will consist in creating a file named $HOME/.ssh/config with the following content:

Hostname my.server
Port 4000

I am used to use the ssh config file, but I did not know about its potential. In particular, I didn’t know about the possibility of changing the default port. Digging a bit on it, the ssh-config is powerful, as it enables to avoid the annoying messages about the host keys in a internal network, to assign aliases to hosts or even to enable the port forwarding.

An example of config file that I use to SSH the internal nodes of my clusters is the next one:

Host node*
StrictHostKeyChecking no
UserKnownHostsFile /dev/null

And well… now I know that I can change the port of the SSH server (perhaps to avoid attacks from users).