Persistent SSH Tunnel

Overview

An tunnel is a way of providing a connection for which other connections can be made without revealing what they are. An SSH tunnel is using the SSH protocol to create such connection. One of the main benefit to an SSH tunnel is creating a secure tunnel between 2 points. For a tunnel to exist a connection needs to be established but also maintained. A SSH session usually has a timeout if no activity is detected from the server side.

One use I have found is to secure MySQL data. Whilst MySQL does support SSL connections not all applications have the ability to use it. For example WordPress 3.7.x does not support MySQL over SSL out of the box.

Infrastructure

SSH Tunnel
For a tunnel to exist there must be 2 servers running SSH. In this case server A will be initiating server with a IP of 10.0.0.1 to server B which has an IP address of 10.0.0.2. Examples of it’s use could be server B is a source control server, backup server or even a database. These are central services where external applications or servers require access to. It makes it easier to maintain the certificates on server B and revoke them later in one.

Both servers will be running Ubuntu but this should work on all Linux distributions.

Setup Server A & B

This section applies to both servers and can be done in parallel.

Install SSH server:
sudo apt-get install openssh-client openssh-server

Create a new user called tunnel who will initate the connection. Once the connection is created the tunnel will be available to all users.
sudo useradd -m -s /bin/bash tunnel

Set a strong password for the new tunnel user:
sudo passwd tunnel

Setup Server A

Switch to the tunnel user:
su - tunnel

Generate a SSH key with no password:
ssh-keygen

Note down the public key which is needed on Server B:
cat /.ssh/id_rsa.pub

Create a script which will check and keep the tunnel alive. Create a file called check_ssh_tunnel.sh:
touch check_ssh_tunnel.sh

Edit the file and add the following:

createTunnel() {
/usr/bin/ssh -f -N -L13306:hostb:3306 -L19922:hostb:22 tunnel@hostb
if [[ $? -eq 0 ]]; then
echo Tunnel to hostb created successfully
else
echo An error occurred creating a tunnel to hostb RC was $?
fi
}
## Run the ‘ls’ command remotely. If it returns non-zero, then create a new connection
/usr/bin/ssh -p 19922 tunnel@localhost ls
if [[ $? -ne 0 ]]; then
echo Creating new tunnel connection
createTunnel
fi

The above script was taken from Brandon Checketts site. I have created an maintained my own on github.

Replace hostb with server B’s address. The script forwards port 13306 on server A to 3306 on server B.

Server B

Switch to the tunnel user:
su - tunnel

If it does not exist create an authorised key file in .ssh:
mkdir .ssh
touch .ssh/authorized_keys

Add / append the public key from Server A into the authorised key file.

Post Setup

SSH from server A to server B to check the connection. It may prompt you to accept a server finger print which identifies server B is the correct server.
ssh tunnel@10.0.0.2

If successful close the connection by typing exit.

A second port is used to keep the tunnel alive. In the example above this is 19922 and doing a ls command. Run the script to check it works. If no existing tunnel exist then it will create one otherwise no output means the tunnel was checked and still OK.

After checking the script, create a cron entry as the runnel user on server A. It should run the script every so often to check and keep the connection alive.
crontab -e

Add the following to run the check_ssh_tunnel.sh every minute and on boot:
* * * * * /home/tunnel/check_ssh_tunnel.sh
@reboot /home/tunnel/check_ssh_tunnel.sh

Summary

This is a crude but good way to encrypt data between two points. I’ve tested the setup for the past month and it seems to hold up well. I’ve improved on the script from Brandon’s example to parameterise some of the commands to make it easier to configure.

Danny’s bashTunnel
Creating a Permanent SSH Tunnel Between Linux Servers
Running A Python Script At Boot Using Cron

About Danny

I.T software professional always studying and applying the knowledge gained and one way of doing this is to blog. Danny also has participates in a part time project called Energy@Home [http://code.google.com/p/energyathome/] for monitoring energy usage on a premise. Dedicated to I.T since studying pure Information Technology since the age of 16, Danny Tsang working in the field that he has aimed for since leaving school. View all posts by Danny → This entry was posted in Linux, Security and tagged , , , , , , , . Bookmark the permalink.

Leave a Reply