Wednesday, January 22, 2014

Establishing Permanent SSH connection Between Two Linux servers

I recently had a need to create a permanent SSH tunnel between Linux servers. My need was to allow regular non-encrypted POSTGRES connections over an encrypted tunnel, but there could be many other uses as well. Google can identify plenty of resources regarding the fundamental SSH commands for port forwarding but I didn’t ever find a good resource for setting up a connection and ensuring that it remains active, which is what I hope to provide here.

 The SSH commands for port forwarding can be found in the ssh man page. The steps described here will create an unprivileged user named ‘tunnel’ on each server. That user will then be used to create the tunnel and run a script via cron to ensure that it remains up.


 First, select one of the servers that will initiate the SSH connection. SSH allows you to map both local and remote ports, so it doesn’t really matter which end of the connection you choose to initiate the connection. I’ll refer to the box that initiates the connection as dev, and the box that we connect to as dev 1.


 Create a ‘tunnel’ user on dev
[root@dev ~]# useradd -d /home/tunnel tunnel
[root@dev ~]# passwd tunnel ## Set a strong password
 [root@hdev ~]# su - tunnel ## Become the user 'tunnel' Now create a public/private key pair: [tunnel@dev ~]$ ssh-keygen Generating public/private rsa key pair.
Enter file in which to save the key (/home/tunnel/.ssh/id_rsa):
 ## hit enter to accept the default
Enter passphrase (empty for no passphrase): ## don't use a passphrase
Enter same passphrase again: Your identification has been saved in /home/tunnel/.ssh/id_rsa. Your public key has been saved in /home/tunnel/.ssh/id_rsa.pub. The key fingerprint is: 6f:30:b8:e1:36:49:74:b9:32:68:6e:bf:3e:62:d3:c2 tunnel@dev

Now cat out the id_rsa.pub file which contains the public key that we will need to put on dev1b: 

[tunnel@dev ~]# cat /.ssh/id_rsa.pub ssh-rsa

blahAAAAB3NzaC1yc2EAAAABIwAAAQEA......6BEKKCxTIxgBqjLP tunnel@hosta

Now create a ‘tunnel’ user on Host B and save the public key for tunnel@hosta in the authorized_keys file

 [root@dev1 ~]# useradd -d /home/tunnel tunnel
[root@hdev1 ~]# passwd tunnel ## Set a strong password
 [root@dev1 ~]# su - tunnel
 [tunnel@dev1 ~]# mkdir .ssh
 [tunnel@dev1 ~]# vi .ssh/authorized_keys ## Now paste in the public key for tunnel@dev

At this point you should be able to ssh from tunnel@hosta to tunnel@hostb without using a password. Depending on your configuration, you might need to allow the user ‘tunnel’ in /etc/ssh/sshd_config. You might also set some SSH options like the destination port in ~/.ssh/config.

 Now, create this script as dev:/home/tunnel/check_ssh_tunnel.sh
 createTunnel() {
 /usr/bin/ssh -f -N -L13306:dev1:3306 -L19922:dev1:22 tunnel@hostb
 if [[ $? -eq 0 ]]; then
 echo Tunnel to dev1 created successfully
 else echo An error occurred creating a tunnel to dev1 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
Save that file and make it executable
: chmod 700 ~/check_ssh_tunnel.sh

This script will attempt to SSH to localhost port 19922 and run the ‘ls’ command. If that fails, it will attempt to create the SSH tunnel. The command to create the SSH tunnel will tunnel local port 13306 to port 3306 on dev1. You should modify that as necessary for your configuration. It will also create a tunnel for local port 19922 to port 22 on dev1 which the script uses for testing the connection.

 Now just add that script to the user ‘tunnel’s crontab to check every few minutes, and it will automatically create a tunnel and reconnect it if something fails. When it does create a new connection it will send an email to the ‘tunnel’ user, so you can create a .forward file to forward those messages to you.

No comments:

Post a Comment