A few years back, I used to SSH into my lab computer from home using the IP address of the Lab computer. Over the years, my university IT personnels restricted inbound access to the networks. I can no longer SSH into my lab computer. I wished that I could use an outbound SSH connection to use the lab computer remotely. A little bit of search brought up a service called openport.io provided a simple way to achieve this. However, it is not a free service and I believed that there hand to be a free alternative to doing this. More researching revealed thing was indeed possible using SSH Reverse Tunnels.

Creating a reverse tunnel using SSH in pretty simple. A reverse tunnel can be created by executing (labcomputer) -

lab_user@labcomputer:~$ ssh -R 65522:localhost:22 myhomecomputer.com

The above command creates an SSH connection to my home computer and maps homecomputer.com:65522 <-> labcomputer:22 I can then SSH into the labcomputer from myhomecomputer by executing the command -

home_user@myhomecomputer:~$ ssh -p 65522

This command effectively establishes an SSH to labcomputer through the tunnel using the mapped ports.

Great! Can I have this reverse SSH tunnel be persistent? Well, SSH connections disconnect all the time. I needed to find a way to reestablish SSH connection on disconnection. Another search revealed that a tool called autossh existed to do exactly that. However, the problem I faced is that myhomecomputer is behind a firewall and needs a port knock sequence to expose port 22 (see Securing with Port Knocking). I initially decided to ditch autossh in favour of a script with an infinite loop.

#! /bin/bash
while :
        knock myhomecomputer.com 64001 && sleep 1 && knock myhomecomputer.com 64002 && sleep 1 && knock myhomecomputer.com 64003 && sleep 1 && knock myhomecomputer.com 64004
        ssh -R 65522:localhost:22 myhomecomputer.com

The problem with this script is that sometimes the SSH connection would freeze but not disconnect. autossh is a script that does more that what the simple bash script above. What I need was a way to execute a local script locally before attempting to establish an SSH connection.

It turns out that openSSH clients do have a directive called ProxyCommand. These are intended to proxy SSH and to effectively create proxy chains. So one can SSH hostSrc > host2 > host3 > hostDst. This is similar to TOR. However, I decided to use ProxyCommand for an entirely different purpose.

My work around was -

Step 1

I edited the ~/.ssh/config on the lab machine to add the following

host myhomecomputer.com
    HostName myhomecomputer.com
    user user_me
    IdentityFile ~/.ssh/user_me.openSSH

host myhomecomputer
    HostName myhomecomputer.com
    user user_me
    IdentityFile ~/.ssh/user_me.openSSH
    ProxyCommand bash -c 'source knock_myhomecomputer_ssh; ssh -TN -R 65522:localhost:22 myhomecomputer.com'

Notice the names - myhomecomputer (alias / shortcut) & myhomecomputer.com (actual host). Attempting to SSH using the alias myhomecomputer executes the ProxyCommand line, which in turn connects to actual host myhomecomputer.com over SSH.

Step 2

The knock_myhomecomputer_ssh is as -

knock myhomecomputer.com 64001 && sleep $SLEEP_T && knock myhomecomputer.com 64002 && sleep $SLEEP_T && knock myhomecomputer.com 64003 && sleep $SLEEP_T && knock myhomecomputer.com 64004

Step 3

Added the following to my crontab on the labcomputer

@reboot autossh -f myhomecomputer

I now have a persistent SSH connection and a Reverse SSH Tunnel from the labcomputer to myhomecomputer.