Linux ssh: port forwarding, socks5, jump hosts, ...

Here is how to use openssh to access servers that are not directly reachable from your computer.

The commands presented here do not only apply to native Linux but they work as well in the Windows 10 ubuntu shell.

The idea is that you want access locally on your computer services that are behind another hosts or a chain of hosts and there is no direct routing from your computer to the destination:
|your computer|-----------------|jump host              |----+------|dest server1  |
|     10.0.0.3|                 |10.0.0.10  192.168.1.10|    |      |192.168.1.21  |
                                                             |
                                                             +------|dest server2  |
                                                                    |192.168.1.22  |

All example networks are /24. 
There is no routing between 10.0.0.0/24 and 192.168.1.0/24.  

Web traffic via a dynamic tunnel: firefox and socks5 via ssh

You are on "your computer" and you want to access a web site at any of the destination servers (http://192.168.1.21 or http://192.168.1.22 or https://192.168.1.21, ...)
on your computer your type: ssh -D 3333 user@10.0.0.10

This opens a socks5 proxy at port 3333 and it will allow you to transparently access any of the servers behind jump host as if you had a direct connection. Your firefox web browser must be configured to use a socks5 proxy at localhost and port 3333:
firefox socks5 config

Web traffic via a dynamic tunnel: google-chrome and socks5 via ssh

google-chrome does not have a configuration menu where you can specify to use a socks tunnel. You can however do it via a commandline option:
google-chrome --proxy-server="socks://localhost:3333" http://192.168.1.21

Other ssh sessions via a dynamic tunnel: socks5 via ssh, ssh through the socks5 connection

As above you have already ssh as a socks5 proxy listening at port 3333
on your computer your type: ssh -D 3333 user@10.0.0.10

You can now use this connection to "directly ssh" to any of the 192.168.1.21 and 192.168.1.22 hosts even though they are not directly reachable from your computer. To do this you need a command called socat:
install socat if not there yet: apt-get install socat

Now you can ssh via localhost:3333 to any of the hosts behind jump hosts:
ssh -o ProxyCommand='socat - socks:127.0.0.1:%h:%p,socksport=3333' user@192.168.1.21 You can as well add an entry in our .ssh/config file to abbreviate this: Host 192.168.1.* ProxyCommand socat - socks:127.0.0.1:%h:%p,socksport=3333 With this in .ssh/config you can simply type the following on your local machine. You will be prompted once for the password at destination host. ssh user@192.168.1.21 or ssh user@192.168.1.22 or copy files: scp somefile.txt user@192.168.1.22:

You can open any number of ssh connections via this one socks5 tunnel proxy.

This use of an existing dynamic tunnel works also for other ssh related commands such as scp and sftp. That is: you can run a ssh/scp/sftp command from your computer and the tunnel will allow you to connect directly to hosts behind 10.0.0.10:
ssh: ssh -o 'ProxyCommand socat - socks:127.0.0.1:%h:%p,socksport=3333' user@192.168.1.21 scp: scp -o 'ProxyCommand socat - socks:127.0.0.1:%h:%p,socksport=3333' file_on_you_pc.txt user@192.168.1.21:/tmp sftp: sftp -o 'ProxyCommand socat - socks:127.0.0.1:%h:%p,socksport=3333' user@192.168.1.21 sftp to a different port number (here 31709): sftp -o 'ProxyCommand socat - socks:127.0.0.1:%h:%p,socksport=3333' -P 31709 user@192.168.1.21

Jump host: chaining ssh commands

This is available since ssh version 7.3 (2016). You are basically chaining the ssh commands to save some typing. You will be prompted twice for a password.
ssh -J guido@10.0.0.10 guido@192.168.1.22 guido@10.0.0.10's password: guido@192.168.1.22's password:

static ssh port forwarding

Instead of using socks5 and establish tunnels dynamically to the destination you create static tunnels one port at a time. It's a bit more complicated but you don't have to change anything in your web browser.

We will forward 192.168.1.21:80 such that it is available as http://localhost:2180 If you want to use https then just forward port 443 instead of 80.
ssh -L 127.0.0.1:2180:192.168.1.21:80 guido@10.0.0.10 guido@10.0.0.10's password: This will prompt for the password of 10.0.0.10 and open a shell on 10.0.0.10. After that you can start a web browser on your computer and open: http://localhost:2180 to see the web page at 192.168.1.21:80

The only problem is that the web server at 192.168.1.21 may run a virtual hosts configuration and it will see that you requested "http://localhost:2180". It may serve you only the default virtual hosts content.

If you forward port 22 instead of port 80 the you can as well used this to ssh in one hop or scp/sftp.

The basic syntax for a static tunnel is like this:
ssh -L LocalIP:LocalPort:RemoteIP:RemotePort guido@10.0.0.10 or if you do not want to bind to a specific local IP: ssh -L LocalPort:RemoteIP:RemotePort guido@10.0.0.10

Static tunnels do not require that the application that you use is adapted to socks5. Any application will work. The exception are maybe browsers because the URL included now localhost and the web server may not like that. ssh/scp/sftp/telnet/ftp/... will however all work.
ssh -L 2122:192.168.1.21:22 guido@10.0.0.10 Now use ssh/scp/sftp to work from your local PC as if you were on 10.0.0.10: ssh -p 2122 localhost This will get you to 192.168.1.21 and port 22

References




© Guido Socher,