Cover V13, i12




Sean Mostafavi

These days, it seems that I travel all over the place. When I receive a call that one of the Web servers is down, I find the nearest machine connected to the Internet and establish a Secure Shell connection to see what's going on. In light of recent bugs found in OpenSSL and OpenSSH, I am wary of having an sshd process running and accepting connections from anywhere in the world. So like most other good admins, I limit who is authorized to access the Secure Shell port.

With this in mind, I needed a system that would enable me to be anywhere in the world and yet access my machines through otherwise blocked ports. After researching a number of existing options, I found that none of them fully satisfied my needs. This led me to the development of SSH-Access.

How the System Works

SSH-Access is a two-part system. The first part consists of the sender and the second the receiver. I'll refer to these two components as the client and server for the remainder of this article. The server program runs on the machine I want to access. Its role is to permit or prevent incoming SSH connections from coming through by altering host-based IP filtering rules on the remote host. The client is responsible for providing the server with the client machine's IP address so that the server in turn can allow incoming SSH connections originating from the client's IP address. The mechanism used in the transmission of the information from client to server is email. Rather than using an open port, or monitoring incoming connections for a specific "knocking" sequence for information required for authorization, SSH-Access utilizes the email service already in place to get its authorization requests across.

A specially crafted email message containing the client's IP address is generated on the client machine. I'll call this the authorization request. Two layers of authorization security are provided for in this message. The first line of defense against forgery to gain unauthorized access is the RSA-encrypted string containing the client's IP address. Also, the remainder of the email contains a message that must be acknowledged and matched against by the server.

People familiar with PGP will find that this concept somewhat resembles the hybrid cryptosystem that PGP employs. Whereas the PGP recipient uses a private key to decrypt a session key to in turn decrypt ciphertext into plaintext, the client SSH-Access program uses a single key to decrypt ciphertext (the authorization request). The PGP model is computationally one step more secure; however, I didn't incorporate PGP into SSH-Access. I wanted a self-contained system for access authorization, and I felt that using, at the minimum, a 2048-bit key was more than enough to thwart off a brute-force attack.

Pre-Installation Tasks

Before you begin installing SSH-Access on your remote and client systems, there are a couple of things you need to do. You must create an email account to be used exclusively by the server. This can be an IMAP or POP3 account. Optimally, you'll want the mail server to be located on the local network for the least amount of latency and increased speed in mail polling. Even if the mail server is not located on the local network, the tax on your bandwidth is minimal, as a mail check or mail retrieval of an incoming SSH-Access authorization request is small. Once you establish a mail account to use with SSH-Access, make sure to jot down the email address, mail server host name, user name, and password associated with the account. You'll need this information when configuring the server.


Obtain the SSH-Access tarball from the Sys Admin Web site or from:
Extract the contents of ssh-access.tar.gz into a directory of your preference. This directory will be the location where SSH-Access is installed:

# gzip -dc ssh-access.tar.gz | tar -xf -
# cd ssh-access
Run the setup script found within the server ssh-access directory:

# cd server
# ./setup
This setup will download and install all the necessary Perl modules needed via the CPAN Perl module. Pay close attention to the compilation output to make sure all of the modules are correctly built and installed. The setup script will also optionally make a few minor changes to some of the installed modules if you want to enable support for Windows clients. Finally, the setup script will prompt you to generate the RSA keys. Two keys will be generated -- private.key and public.key. The private.key file is to remain on the server in the server directory and should only be readable by its owner. The public.key file will be copied to the client directory.

Starting the Server

The server portion of the program (ssh_access) may be invoked in several different ways to fit your particular system setup. The most common way of starting ssh_access is in daemon mode through the SysV-style startup script. Copy the startup script to your init.d directory. On most systems the startup script can be copied to the SysV-script startup directory like so:

# cd ..
# cp scripts/ssh-access /etc/init.d
# chkconfig --add ssh-access || \
> ln -s /etc/init.d/ssh-access /etc/rc3.d/S99ssh-access
If you're running SSH-Access on a BSD variant, simply add the full path of the ssh_access program to your rc.local script.

The server may also be called from a cron job, in which case an entry similar to the following would suffice to run the ssh_access every two minutes:

*/2 * * * *  /opt/ssh-access/server/ssh_access
Also, the server may be called directly by Sendmail or any other mailer that supports piping the contents of an email message to a program. For Sendmail, simply add this line to your aliases file (remember to rebuild your aliases file afterwards):

ssh_access: "| /opt/ssh-access/server/ssh_access -s"
I prefer to start ssh_access in daemon mode rather than running it via the "Sendmail method" because I usually don't have Sendmail running on the machines I work with unless absolutely necessary. Also, the server may have all inbound connections blocked or may not have Sendmail installed. However, if you already have Sendmail installed and running on the server, then inserting the ssh_access startup command in the aliases file would be the better choice, because it would discount the slight resource overhead produced by the periodic invocation of a process.

Initiating ssh_access from Sendmail would also eliminate the minor charge in bandwidth needed in polling for mail. If your mail server is located on the local network, then this may not be a benefit. Ultimately, there is a slight tradeoff in resource allocation versus potentially improved security in not having to run Sendmail.

Server Configuration

To configure the server program, edit the server.cfg file found within the server subdirectory. Here you will find configuration directives that need to be changed to reflect your setup. This is where you will enter mail server information with respect to the mail account you just created for use with SSH-Access. Pay careful attention to the subject and custom_message directives, as the values of these directives must be copied into the client's configuration file. The client configuration file contains exact copies of the subject and custom_message values by default. However, you may want to alter these default values to add an additional layer of security. You will also need to list the acceptable originating email addresses that will be used by the client program.

Client Configuration

The client portion of SSH-Access is to run on the client machine in which you are trying to establish an originating SSH connection. All the files needed are located in the client subdirectory. These files are to be copied to the storage medium of your choice:

# cp -R client /mnt/usb_drive
Or, you can simply zip the client directory and its contents for secure transfer to an FTP server or password-protected Web space:

# zip -r client
Six files are located in the client subdirectory: client_auth, client.cfg, public.key, setup, ssh_wrapper, and ssh_wrapper.bat. The client.cfg and public.key files should be closely guarded. These two files should not be stored on publicly accessible storage. I store the client files on a USB keychain drive, which can be purchased for around ten dollars now. On my keychain I have Perl installations for almost every OS I encounter. Almost every modern flavor of Unix gives the administrator the option to install Perl at OS installation, so carrying around Perl binaries for Unix systems is not that essential. I also keep Secure Shell binaries for the systems I work with on my keychain drive.

Once you have secured a location for the client files, the next thing to do is run the setup script found within the client directory:

# cd client
# ./setup
Similar to the server setup script, the client setup script will download all the necessary Perl modules needed for the client program. Next, edit the client.cfg file. In this file you must provide the SMTP server to use, the email address corresponding to the email account you created for the server, the originating email address that must be listed in the server.cfg file, and the optionally customized subject and custom_message directives that must match their respective values in the server.cfg file.

In client.cfg you can use a Web-based mail interface as your SMTP server, such as Gmail or Yahoo. You might want to use this option, for example, when you are on a client machine and cannot find an open mail relay. You might possibly not even know the name of the local SMTP server and cannot find one available by looking at DNS MX records for the network you're on. Once you have the client configured, you can give the system a test run to make sure everything is properly set up.

Using SSH-Access

Make sure that the Secure Shell daemon is running on the remote system and verify that the SSH-Access server program is running on the machine to which you want to establish a connection:

# /etc/init.d/ssh-access start
On the client machine, run the ssh_wrapper script:

$ cd client
$ ./ssh_wrapper user@remote_host
Replace "remote_host" with the remote machine to which you want to connect, and replace "user" with the user name with which you want to log in. ssh_wrapper is a shell script that will automatically invoke the client_auth program and sleep for a minute to wait for the authorization request it just sent to process. You may need to change the value of the WAIT_TIME variable from 60 seconds to however many seconds it takes on average for an email to reach its final destination on the remote mail server. This will depend on how heavily loaded the mail server is. After sleeping for a minute, it will execute the Secure Shell client.

The script will look for the Secure Shell client in the standard locations. If it's not located in any of the directories listed in the PATH variable, be sure to change the SSH variable in the ssh_wrapper script to reflect the location of the program. The Secure Shell client program will execute, and when your session is finished, ssh_wrapper will call client_auth to send an authorization message to the server to disallow access from the client's IP address.

If you're on a Windows machine, you'll want to execute the ssh_wrapper.bat file. Also, if your client machine is running Windows, make sure that the locations of the Secure Shell program and the Perl interpreter are listed in your PATH variable. The Secure Shell installation wizard for Windows and ActiveState's Active Perl for Windows both register their programs in the system PATH variable by default.

ssh_wrapper may not correctly identify your client machine's IP address if your client machine has a private IP address. The ssh_wrapper script calls the client_auth program with the -n switch, which runs client_auth in a non-interactive mode. If your machine has a private IP address, client_auth will detect that it's private and suggest which IP address it thinks your client machine is masking itself as. client_auth will usually identify the correct IP address; however, if it does not, you can call the client_auth script by itself instead of calling the ssh_wrapper script, and the client_auth script will prompt you for the real IP address.


The system and its design are pretty secure. There are four main hurdles an attacker would have to overcome in order to beat the system. First, an attacker would need to know the email address of the account in use with the system. Second, the attacker would need to forge an authorization request using an originating email address approved by the server. Third, the attacker would need to know the secret message and subject shared by client and server. Fourth, the attacker would either have to crack the RSA encrypted message generated by the client, or have a copy of the public.key along with the three other aforementioned pieces of information to generate his or her own approved authorization request message. In the worst-case scenario of the attacker gaining all of these pieces of information; all that the attacker has now is an opportunity to authenticate against the Secure Shell server.

There has been criticism regarding the port knocking authorization system in that a good network packet sniffer can identify the series of knocks used to allow authorized access. SSH-Access is not vulnerable to this type of attack because it relies on a shared key system. An attacker could capture the contents of the originating authorization request, but at best he would have to crack the RSA-encrypted message containing the IP address in order to insert his IP address for authorization.


There are a few authorization systems out there today, most notably the port knocking system. SSH-Access hopes to provide greater versatility while carrying the same level or possibly a higher grade of security than these systems. Currently, SSH-Access knows how to alter Wietse Venema's TCP Wrapper's hosts.allow/hosts.deny files, along with iptables-based firewall rule sets. Future versions will allow for a wider selection of IP filters. I've been using SSH-Access for quite some time and have found it extremely useful and easy to set up. I hope you find that SSH-Access meets your needs.

Sean Mostafavi has been administering and developing applications on Unix systems for the past 11 years. He has also worked for a major security-based software development company. Sean is currently in his last year finishing a B.S. in Computational Mathematics at Arizona State University. He can be reached at: