Setting up a self-healing SSH tunnel for Raspberry Pi using Debian.

I use quite a few raspberry pi’s in locations that dont have the ability for me do incoming SSH to update / reboot / maintain them.  This is how i set up a reverse SSH tunnel to them, allowing me to access them from anywhere with internet access!

If the site has a proxy, first you’ll need to install a proxy puncher to allow you to bypass it.

sudo http_proxy="http://proxy.ip.address:port" apt-get install corkscrew

Then install screen. Screen allows you to start a process running ‘detached’ from your current shell, so you dont have to be logged in to keep the tunnel up.

sudo apt-get install screen

Create a user for your ssh tunnel. You could just use the default pi user, but i prefer to use a dedicated tunnel user.

sudo adduser --system tunnel

Create tunnel config

sudo -u tunnel mkdir /home/tunnel/.ssh
sudo -u tunnel vim /home/tunnel/.ssh/config

Paste the following into the file. This forwards port 22 (ssh) and 80 (http) on the raspberry pi to ports 8022 and 8080 on your VPS.

ProxyCommand corkscrew 127.0.0.1 3128 %h %p
Host tunnel
        Hostname your.vps.hostname
        Remoteforward 8022 localhost:22
        Remoteforward 8080 localhost:80
        Port 443
        User tunnel
        ServerAliveInterval 10
        ServerAliveCountMax 3

NOTE: If you are not using a proxy, remove the corkscrew line and the port 443 line. The port 443 line above is only needed if you are behind a proxy and firewall that disallows port 22 outgoing. I have set up my SSH daemon on the VPS to listen to port 443 (the https port) as well as the normal 22 as this will manage to punch its way through most proxies.

The ServerAliveInterval and ServerAliveMax variables above basically say “send a packet across the tunnel every 10 seconds. If you don’t get anything back after 3 tries, close the tunnel”

The above config also assumes you have set up a tunnel user on the machine you are SSHing to. If not, either create a tunnel user the same way we did above, or change the user line in the config to the username you will be using on the VPS side.

Generate your RSA key and upload to the VPS

sudo -su tunnel
export HOME=/home/tunnel
ssh-keygen
ssh-copy-id tunnel

At this point, you should be able to SSH to tunnel without typing in any passwords etc.

$ ssh tunnel
Linux thinkl33t 3.2.0-4-686-pae #1 SMP Debian 3.2.65-1+deb7u2 i686
$

Set up our shell scripts to automatically start the tunnel.

sudo -su tunnel
mkdir /home/tunnel/bin
echo 'PATH="$HOME/bin:$PATH"' | tee /home/tunnel/.bashrc
echo '#!/bin/bash' | tee /home/tunnel/bin/monitor_tunnel.sh
echo 'APPCHK=$(screen -ls | grep -c tunnel)' | tee -a /home/tunnel/bin/monitor_tunnel.sh
echo 'if [ $APPCHK = "1" ]; then' | tee -a /home/tunnel/bin/monitor_tunnel.sh
echo '    echo "Starting SSH tunnel"' | tee -a /home/tunnel/bin/monitor_tunnel.sh
echo '    screen -mdS tunnel ssh -N tunnel' | tee -a /home/tunnel/bin/monitor_tunnel.sh
echo 'fi' | tee -a /home/tunnel/bin/monitor_tunnel.sh
echo 'exit' | tee -a /home/tunnel/bin/monitor_tunnel.sh
chmod a+x /home/tunnel/bin/monitor_tunnel.sh

The above script checks for an already open screen session with the name ‘tunnel’. If it doesn’t exist, it creates it. If it does exist it just ends. The screen session is launched in a detached state (in the background), and will automatically end when the SSH tunnel falls over.

Set up the crontab to automatically run our monitoring script once a minute

echo '*/1 * * * * /home/tunnel/bin/monitor_tunnel.sh' | crontab

Your tunnel should come up shortly, woo!

To test it out, from your VPS, type

$ ssh localhost -p 8022
parag0n@localhost's password:
Linux thinkl33t 3.2.0-4-686-pae #1 SMP Debian 3.2.65-1+deb7u2 i686
$

Brill, you can now SSH in from your VPS… But by default SSH tunnel ports are only available from localhost, so you’d have to log into your VPS every time you wanted to get into the pi. So, lets edit the SSH config file on your local machine!

Host pi
        Hostname localhost
        Port 8022
        ProxyCommand ssh your.vps.hostname nc %h %p

This will allow you to type in

ssh pi

on your local machine, and will automatically ssh into your VPS, then SSH into localhost. Sorted.

One thought on “Setting up a self-healing SSH tunnel for Raspberry Pi using Debian.

  1. This didn’t quite work for me.

    if [ $APPCHK = “1” ]; then

    did you mean = “0” here?

    Also, ssh vpstunnel i believe you mean ssh tunnel.

    When I tried this, the screen was started in detached mode and tries to ssh but hangs asking for password. I do have keys setup and if I ssh directly at prompt I can ssh to remote machine without entering in password.

    I’ve settled on using autossh instead to handle the re/connection which appears to work properly.

Leave a Reply

Your email address will not be published. Required fields are marked *