oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

Secure Mail Reading on Mac OS X
Pages: 1, 2, 3

SSH Tunneling

It may happen that you must retrieve mail from a server that supports POP or IMAP, but not their more secure SSL-enabled counterparts, and you can't (or perhaps would rather not) set up server-side mail forwarding that would push all received mail to a more security-conscious mail host. Fortunately, with a little extra work, you can set up a peculiar structure known as an SSH tunnel from your Mac to the server. Think of it as a rabbit hole with one opening in your machine, and the other at the mail server. You and your password can travel from point to point freely, while being invisible to airborne predatory sorts.

(This section assumes some experience in wrangling with your Mac's Unix command line, by way of the Terminal application.)

Using SSH

Programs that implement SSH, such as the OpenSSH family, are primarily used to log in remotely to other Unix systems. However, unlike Telnet, these programs encrypt every packet that travels between the client and the server, so that eavesdroppers don't see a pretty stream of cleartext, but rather a string of scrambled such-and-such. These nosey folk lack the keys, residing on either machine, necessary to decode (and encode) these transmissions.

In order to build a tunnel -- or, indeed, engage in any SSH shenanigans -- between your Mac and your mail server, it must have an SSH server running, and allow you to log into the machine from it.

As a Mac OS X user, you already have all the client software you need to pull off your end of this trick, through the ssh command-line program, and you can read all about it by consulting your Mac's ssh man page. But for now, let's simply test your mail server. Open up Terminal and try this command (once again using your mail host's actual address):

% ssh

If, after a pause, you get a prompt asking you for a password, congratulations; the server is SSH-savvy. (Type Control-C and then return to kick out of the program for now, or proceed with your password if you want to log in to that machine. (And consider using ssh for all subsequent logins to that server!) If you get a "Secure connection to refused" message (and you're sure that your network connection is functioning properly), you'll need to ask your mail-hosting facility if they have SSH services available at all -- they might be running it on a different port than the default one (port 22) for some reason.

If you're good to go with SSH, read on.

Enabling Passwordless Access

Since this method involves automating ssh connections, our first step involves setting up passwordless access to your mail server. This way, you don't have to let your tunnel-digging script know what your password is, making things a little more convenient and safer for you. (After all, keeping passwords stored in unencrypted text files, even within program code, is a fine example of cleartext that's dangerous without needing network transmittal.)

First, in Terminal, run this command:

ssh-keygen -t rsa

This program creates a pair of encryption keys, public and private, using the RSA encryption scheme. It will prompt you for a filename where it will save the private key. (The public key will be created with the same filename, but with an additional .pub extension.) By default, it will want to save the key as ~/.ssh/id_rsa, which, being one of the default filenames for keys that the OpenSSH client recognizes, would be grand if you meant to make this your principal key for all future SSH use. However, we're going to use this key for the specialized purpose of port forwarding, so we'll save it under a different name. I call mine tunnel.

Related Reading

SSH on Mac OS X for Worry-Free Wireless

Using SSH Tunneling

When it asks for a passphrase just hit return twice, thus specifying a blank passphrase. We'll make up for the insecurity of this maneuver by constraining the usefulness of this key in the following step.

Now make a small edit to the public key from the pair you just made. Open it in any text editor and add the text command="exit", followed by a space, at the very start of the file. For example, here's a public key I just made and modified:

command="exit" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA0Ne0dfmcIc+5/Uonqd2lftpEmN/
ZsxugFGvy1OjxKyHmkbZ8MBdMtgxm30I8UXYqk= jmac@endif

(Everything after the "ssh-rsa" part in your key will be different than mine, of course.) This addition hobbles the key so that if someone, heaven forbid, manages to swipe your private key and then tries to use it to start an interactive shell session with this server -- hence getting access to all your mail and more -- it will successfully authenticate and log in, only to immediate log out again! Since the tunnel we're building isn't going to use a shell at all, this is fine with us, and makes our operations all the more secure.

Next, log into your mail server (using ssh in the usual fashion) and in your home directory create a directory called .ssh if one isn't there already. (Note the leading period, qualifying this as a "dotfile", and thus invisible to normal ls calls; try ls -a or just ls .ssh.)

Now you must copy the public key (the key file you generated that ends in .pub) to your mail server, so that it resides in a file called authorized_keys2 within that .ssh directory. (The '2' specifies that this key collection is for use with SSH.

If it happens that you already have not only an .ssh directory but also an authorized_keys2 file within it -- hmm, have you done this before? Well, regardless, you'll have to copy the public key over to the server, and then concatenate it onto the existing file using the method of your choice, be it a text editor or the cat program.

Otherwise, you can copy it over in one step via scp, yet another useful member of the SSH program family:

% scp

Finally, try sshing into the server. If you find yourself suddenly logged into a remote shell without any password prompt, the operation was a success. (If you still get a password prompt, you can try tracking down the problem by running ssh in verbose mode, with the -v flag.)

Setting up the Connection Script

Now that your Mac is ready to make easy SSH connections, we'll fashion a way to ensure that a tunnel exists whenever you're ready to check your email. Instead of simply launching Mail ourselves, we’ll create a script that launches Mail for you after it makes certain things are set up properly.

First, if you haven't already you'll want to install Apple's Script Menu. This handy menulet provides a way to launch not only AppleScripts, but any Perl or Shell executable existing in special folders on your Mac. Consult Apple's Script Menu Web site to get the software and installation instructions.

One of these special folders exists in your own home directory, under Library/Scripts. Create the following piece of Perl via the text editor of your choice, (customizing its variable values as appropriate) and drop it in that folder when you're done. Once moved there, rename it "Secure Mail" (or whatever you'd like to see it called inside the script menu).


use warnings;
use strict;

# Change the value of $mailserver to your mailserver's address
my $mailserver = "";

# $server_port should be set to whatever TCP port on your mailhost that
# your mail program connects to.
# Typically, IMAP connects to port 143 and POP uses port 110.
# If your mailhost is Very Silly they might use some other port for these services,
# but this is likely not the case.
my $server_port = 143;

# $local_port is the port on your Macintosh that will serve as the near end
# of the SSH tunnel. It has to be a number greater than 1024 (anything less
# than that is reserved for system use). Here, I'm just tacking a '0' onto
# the server's port number.
my $local_port = 1430;

# Set $identity_file to the private RSA key to use for authentication.
my $identity_file = "~/.ssh/tunnel";

# You shouldn't need to change anything after this line.
my $ssh_cmd = "ssh -i $identity_file -C -f -N -L
$local_port:localhost:$server_port $mailserver";
my $ssh_count = "ps ax | grep '$ssh_cmd' | grep -v grep | wc -l";

print "Command is:\n$ssh_cmd\n";

# Only start a new ssh tunnel if we don't have a previous connection
if (`$ssh_count` == 0) { system($ssh_cmd) }
system("open /Applications/");

As soon as the file is in place, it should automatically appear as a choice in the Script menu, as in the above illustration. When run, the script opens a tunnel to your server if one does not already exist, and then launches your Mail application (or brings it to the foreground if it's already launched).

(All the thingies you see above it represent Apple's default and demonstration scripts living in /Applications/AppleScript/Scripts, which is where scripts available to every user of this Mac go. Scripts you place in your personal Library folder, however, are visible to you alone.)

Pages: 1, 2, 3

Next Pagearrow