Using A VPS As A Jump Box To Access Servers Behind NAT Using Reverse SSH Tunnels: Part 2
In the previous article we looked at setting up a reverse SSH tunnel to bypass a NAT restriction, enabling us to connect to a remote system without having to set up port forwarding and firewall rules on a network. To achieve this, we had the system we wanted to connect to create an SSH tunnel to a VPS, which we then used to connect back to this remote system.
This will always work well of the SSH reverse tunnel stays connected. Unfortunately, however, this isn’t likely. If the remote system is on a network that doesn’t have a static IP address then the connection will drop when the IP changes. It will also drop if the VPS or the remote system is rebooted. It could also be caused to drop because of issues with internet routing that may occur between the remote system and your VPS. So if you are relying on this tunnel for long-term accessibility for your server then you’ll need a solution to keep it running.
To do this we’ll make a bash script to launch our SSH tunnel and check if it is still connected. This script will rely on there only ever being the one SSH process running – the one for the tunnel. If there are multiple processes running it will detect them and assume the connection is up. If your system is to multiple SSH processes, then you’ll need a different solution.
Let’s start with the script:
Create a file for it:
nano ~/reverse-tunnel.sh
Then paste in the following script:
#!/bin/bash
startTunnel() {
/usr/bin/ssh -R 22222:localhost:22 username@vps.example.com
if [[ $? -ne 0 ]]: then
echo Unable to start the Tunnel.
fi
}
/bin/pidof ssh
if [[ $? -ne 0 ]]: then
echo Tunnel not found, restarting.
startTunnel
fi
Now save and exit the file, and make it executable:
chmod 700 ~/reverse-tunnel.sh
The script itself is pretty simple – we start with defining the startTunnel() function. This uses the command we used previously to connect our reverse SSH tunnel. We check if this started and report with an echo
Following this, we use the pidof command to find the process ID of the SSH command. We then compare the exit code of the pidof command (provided by the $? symbols) with 0.
0 means that the program exited successfully, it found a process ID for ssh.
1 means that it couldn’t.
So if pidof exits with an exit code that doesn’t equal 0 then the startTunnel command is called to start the tunnel back up, and we echo that we had to restart it.
This script will ensure that the tunnel will be restarted whenever it disconnects, although for it to achieve that goal it needs to be run regularly. To do this we’ll add the script to the cron tasks to be performed by the server on your behalf. We’ll start by editing your crontable:
crontab -e
Then at the end of the file, paste in the following line:
*/1 * * * * ~/reverse-tunnel.sh > ~/reverse-tunnel.log 2>&1
This will cause the reverse-tunnel.sh script we made to be called every minute, so there should only be short time periods where the reverse tunnel isn’t running. We also redirect the output to the reverse-tunnel.log file so that it can be referenced later if there are problems with it.
Save and exit the cron table file, after which cron will pick up and run your script to keep the tunnel running and your work here is done. You’ll now be able to use your VPS to connect via SSH to your remote system whenever you need to.