As a regular traveller, I have discovered first hand the joys of geo-location using IP address which some sites and services use to decide what services can be offered and/or the language they should be presented in. It’s therefore quite useful to have a UK-based system which I can use from anywhere using SSH, and being able to use SSH port forwarding to allow me to use services as though I’m in the UK.

The one thing I had wanted to sort out, and hadn’t quite achieved, was to implement a simple system for keeping an SSH tunnel running, and re-establishing it automatically if it drops.

I’ve already implemented certificate authentication between the client and server, the question was just how to maintain the SSH connection with the tunnel parameters. I tried using autossh combined with a cron job, but that didn’t seem to work and despite significant poking and playing I just couldn’t get it to work. It turns out there is a simpler solution:

Create the SSH command line you need to use:

ssh -f -N -q -L *:12345:192.168.1.2:12345 mytunneluser@myremoteserver.net -p 22

-f -N -q tells SSH to go into the background, not to execute a command on the remote system and to quiesce any messages.

Create a script which will check to see if SSH is running for that user, and if not, start it:

#!/bin/bash
# Get the  PID of the ssh process run by the SSHTunnel user
rm -f /tmp/pid.SSHTunnel >/dev/null
ps -U mytunneluser | grep -v grep | grep ssh >/tmp/pid.SSHTunnel
# If the file is zero sized, then SSH is not running
if [ ! -s /tmp/pid.SSHTunnel ]
then
  echo "SSH Tunnel not running - restarting" 
  ssh -f -N -q -L *:12345:192.168.1.2:12345 mytunneluser@myremoteserver.net -p 22
fi
rm -f /tmp/pid.SSHTunnel >/dev/null

I’m sure that some bash gurus could make the checking for the process more elegant – you could directly parse the output of the ps via grep and explicitly identify the ssh instance – and I implemented it this way since it was easy for me to get working step by step, and I’m no bash guru 😉

The final step is to add an appropriate entry to the users crontab (crontab -e) to run the script regularly to check for the tunnel:

# m  h  dom mon dow command
*/1  *  *   *   *   /opt/scripts/tunnel-check

And that should be that.