Sometimes you find yourself stuck behind a firewall or proxy when trying to connect to a remote desktop session of a user or a remote machine.
In this short tutorial I’ll show you how to ‘tunnel’ your way out.
An SSH tunnel is an encrypted tunnel created through an SSH protocol connection. Users may set up SSH tunnels to transfer unencrypted traffic over a network through an encrypted channel. For instance, if you would like to connect to a unencrypted vnc session through the internet or another untrusted network you could create a tunnel and connect to your vnc session via the encrypted tunnel.
First the basics: We would like to setup a encrypted tunnel from “hosta.example.com” to “hostb.example.com” on port 3389
To do this we’ll use the following ssh line on hosta.example.com:
$ssh -L 1234:localhost:5901 hostb.example.com
the command above explained:
-L localport:host:remoteport hostb.example.com
localport = port on the machine we are connecting from (should be above 1024 or you should be a privileged user) in this example 1234 is an unused port.
host = the host we want to be the endpoint of our tunnel. This can be the localhost (which is the host we are connecting to) or a machine which is reachable from the host we are connecting from.
remoteport = the port we want our localport data to be forwarded to. In this example port 5901 (a vnc session).
If everything works as intended you can add the following options to make the tunnel go to the background:
-f = go into the background just before executing the command. This allows for asking for password etc. before going to the background.
– N = Do not execute a remote command.
After successfully setting up the tunnel you can connect to your remote vnc session via the encrypted tunnel with the following command:
That’s it, the very basics of tunnelling.
But what happens when you are on hosta.example.com and the other host is in a different location which is only reachable via the internet through a jumphost called hostc.example.com?
In this case the tunnelling line changes a bit:
ssh -L 1234:hostb.example.com:5901 hostc.example.com
In this situation we are forwarding port 1234 to port 5901 on hostb.example.com via hostc.example.com
Sometimes it’s not possible to directly connect from hosta.example.com to hostb.example.com because of firewall restrictions. If hostb.example.com is allowed to connect to hosta.example.com directly but not the other way round, you can setup a remote port forward.
Of course you need a way to connect to hostb.example.com via either a jumphost or local access etc.
Remote port forward (specified with “-R”) specifies that the given port on the remote host (hostb.example.com) is to be forwarded to the given host and port on the local side (hosta.example.com).
On the remote host (hostb.example.com):
ssh -R 1234:localhost:5901 hosta.example.com
Now it’s possible on hosta.example.com to connect to port 1234 and you will be forwarded to hostb.example.com port 5901
You could even enable the Gatewayports option in sshd_config so that you can connect to the forwarded port on hosta.example.com. Use this with caution: it could mean that you open up a unwanted “hole” in the firewall, especially if the hosta.example.com isn’t firewalled. Also when creating tunnels, keep in mind that other local users on hosta.example.com can also connect on your local port.
In the last example we’ll make it a bit more complicated:
hosta.example.com needs to connect to hostb.example.com.
Hosta.example.com is on a firewalled network only able to connect to the internet via a proxy. hosta.example.com can only connect to hostb.example.com via the jumpserver hostc.example.com (also via the proxy).
A simple overview:
hosta.example.com:1234 -> proxy.example.com:8080 -> hostc.example.com:443 -> hostb.example.com:5901
The hostc.example.com jumphost has a ssh client listening on port 443. (so that the proxy allows the connection)
To connect trough the proxy you could use corkscrew:
After installing corkscrew on hosta.example.com add the following to your .ssh/config:
$vi .ssh/config Host hostc Hostname hostc.example.com ProxyCommand /home/exampleuser/bin/corkscrew proxy.example.com 8080 %h %p
Now we can create the tunnel like this:
hosta$ ssh -L 1234:hostb.example.nl:5901 user@hostc -p 443
Now you can connect to your vnc session on hostb.example.com from hosta.example.com.
These are the most common ways to tunnel via ssh, there are of course a lot more possibilities. For more info check the ssh man pages or google.