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
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
Extract the contents of ssh-access.tar.gz into a directory of your
preference. This directory will be the location where SSH-Access is
# gzip -dc ssh-access.tar.gz | tar -xf -
# cd ssh-access
Run the setup script found within the server ssh-access directory:
# cd server
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
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.
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.
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.zip 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
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
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
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
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: firstname.lastname@example.org.