Keeping ssh Alive for Roll Your Own VPN


This article describes the chaining together of several open source freeware tools to create a secure tunnel between two computer networks. Your employer's security department may or may not get upset with you for trying these techniques. They may get downright hostile. If you decide to apply these techniques, you are accepting responsibility for doing so. No guarantee is made as to the fitness of these techniques for any particular purpose and the author will accept no liability for the use or misuse of these techniques. Everything described here is published elsewhere in the documentation for the tools described.

Keeping ssh Alive

In the enclosing article Roll Your Own VPN with ssh and VNC we describe how to use ssh to create a bidirectional tunnel between two locations called work and home. The tunnel is initiated from the work location where it is assumed you have less control to the home location where you have more control and then becomes bidirectional. It assumes you have a UNIX/Linux box at home and access to a UNIX box at the work location. The process works very nicely unless you are at home and loose the connection. Unless you have a traditional VPN, you cannot get back in to fix it. You could loose the connection for a variety of reasons, such as: network goes down; you reboot your home machine; or the work UNIX machine is rebooted. It would be nice to have the connection reestablished even if you are not at work to initiate it.

As can be seen in the disclaimer, your IT may not approve of you having your own VPN. Often though, IT organizations are orthogonal to getting any work done and this approach does not open gaping holes in security so long as your home network is secure. If you have a UNIX box at home and you can follow this article, you are probably capable of fire walling your home network through a DSL/Cable router/firewall which do remarkably good jobs. The related TCP Wrappers setup article describes setting up the /etc/hosts.allow file on Sun Solaris, but applies to Linux as well. The point to this paragraph is that we are being somewhat clandestine, and wish to escape notice. So we first off want to keep our ssh connection alive and secondly want to keep the processes below the radar.

The easiest way to keep the connection alive is it have a program running on the work side of the link test the connection periodically and restart it if it goes bad. This can be done with a daemon process or a small program started periodically via cron. The cron approach has the additional benefit of being a short lived command and a long running server process. I supply source for a C program which compiles on at least Solaris and Linux (gzip'ed copy) and can be run from cron. The rest of the article assumes you have compiled this program into $HOME/bin/sshr_cron at your work location. You will need to update the #defines for MY_HOME, MY_IDRSA, MY_SSH_TARGET, SSH_PATH, and NOHUP_PATH before you compile.

In the enclosing article ssh port forwarding is used to connect port 7777 at work to port 7 (tcp echo server) on your home machine. You may wish to talk to the daytime server instead of the echo server. The sshr_cron.c program has the ability to call the echo_server or the daytime server. The default is the echo server. Add the -t option to the command line to call the daytime server. If you are using the daytime server, your $HOME/.ssh/config line will need a local forward line like:

   LocalForward  7777

   in place of 

   LocalForward  7777

The sshr_cron program assumes the appropriate port is set up. You can test the connection from the home machine with the command:
telnet localhost 7
Everything you type will be echoed back. Note that the session may not respond to ^c or ^d, so you may have to go into another window and kill the telnet process. With this working you are ready to update your cron job.

From the work machine:
telnet localhost 7777
will test the port over the forwarded connection.

Linux Notes:
On Fedora Core 4, in addition to enabling the echo and/or daytime services using the command system-config-services, I had to go into /etc/xinetd.d and edit the files /etc/xinetd.d/echo and /etc/xinetd.d/daytime to change disable = yes to disable = no.

In addition, both the eche service and the daytime service write to /var/log/secure. This can lead to a lot of irrelevant messages in this log. Adding log_on_success = to the file will suppress the messages (nothing after the equal sign).
On a Fedora Core 4 system, the file would appear as:

service echo
   disable     = no
   type        = INTERNAL
   id          = echo-stream
   socket_type = stream
   protocol    = tcp
   user        = root
   wait        = no
   log_on_success =

Setting Up Cron

At work, logged onto the UNIX box, run the command:
crontab -l > $HOME/mycrontab
It is possible that you do not have a crontab and an empty file will be created. That is OK. Edit the $HOME/mycrontab file and add the lines:

00,15,30,45 * * * *   $HOME/bin/sshr_cron
05 03 * * *    $HOME/bin/sshr_cron  -r

It is suggested that you replace $HOME in the above example with the actual path to your home directory. Some versions of cron will know about $HOME others may not.

The example above runs sshr_cron every 15 minutes. This program tests the connection to your home machine via the echo server. It there is a problem it kills the ssh command if it is running and restarts it. The second crontab line restarts the connection whether it is up or not at 3:05 am every day. This line is optional. If you are on a shared UNIX server at work, they may scan the process table for jobs which have been running a long time. As we want to stay below the radar, we will stop and restart the job periodically. You may want to do this more or less often depending upon the situation. Coffee with some of the UNIX server guys will often result in information about what sort of scans are done.

To reload the modified cron table, run the command:
crontab $HOME/mycrontab

Parting Notes

As already mentioned, this could be a clandestine operation. The ssh cron program contains the ssh command to run. The program is written so you can override the command with command line arguments, but that makes them show up in the process table. Thus it is a good idea to change the code in the program so the default value is the one you want to use.

Additionally, it so happens that the ssh command is not setuid'ed or special in any way. This means you can make a copy of it with a different name and use that instead. Put in a local directory and give it the same name as the X server or something that is expected to run a long time.

If you fiddle with the command strings, remember that cron may not have the same $PATH as your login. Other environment variables may also be missing.

Using this technique requires that you forward a port to the echo server an also that you use ssh_keygen to set up keys to allow you to log in to your home machine without a password.

Having ~/.ssh/id_rsa_a hang around in your process table may be something you don't want. Espcially if you went through the trouble to copy ssh to another name to run it. Having the sshr_cron program run the following three commands on a restart may further obfuscate clandestine activity:

mv ~/.ssh/id_rsa_a ~/.ssh/id_rsa
nohup ssh -N -f homea 
mv ~/.ssh/id_rsa  ~/.ssh/id_rsa_a

Back to Sun At Home Home Page
Last Maintained, 08/18/2005 by R. E. Styma