Securing your SSH keys

My ones of readers may recall that I’ve mentioned “Standalone Sysadmin” by Matt Simmons as one of my favorite blogs.  On Friday, he published a great introduction to SSH keys.  He covered how to set up keys and use them.  One aspect that deserves further coverage, though, is securing your keys.  Sure, a good passphrase will do a lot to keep your key from being used by the bad guys.  But what happens if you have a phraseless key?  It’s a bad idea for interactive use, but for automated tasks, it is nearly a requirement (unless you manually start the SSH agent).  So how can you minimize your risk?

In your authorized keys file (typically ~/.ssh/authorized_keys), you specify the keys you want to be able to log in to your account.  Like most other Unix programs, there is more than just the basic usage available.  If you look at the sshd(8) man page, there is a whole section about options you can specify in authorized_keys.   The documentation is well-written, so I’ll leave most of the discussion of the options to the OpenSSH folks and focus more on real-world examples.

Perhaps one of the first things you can do is restrict where they key can be used from.  If someone cracks your private key, they can use it from anywhere in the world by default.  If you want to restrict that, you can use the ‘from’ option:

from="*.dept.myjob.edu, !nope.dept.myjob.edu,  208.69.36.132" [public key]

This allows connections with the specified key from any host in the dept.myjob.edu subdomain, except nope.dept.myjob.edu, and also from 208.69.36.132.

Of course, it’s not just network geography that you want to be concerned with.  Sometimes you just want to limit what can be done with the key.  Let’s say you only want to allow the key to run updates”

command="/usr/bin/up2date -u" [public key]

Well that’s all well and good, but let’s see a more complicated example.  We have a script that scans Mac OS X computers for Social Security Numbers.  When the scan completes, it copies the output to our main file server.  Now, since we’re giving the code out to faculty, we want to keep the key as tightly controlled as possible.  So what does authorized_keys look like?

command="/usr/local/bin/lim_rsync",no-pty,no-agent-forwarding,no-X11-forwarding,no-port-forwarding,from="*.myjob.edu"

The lim_rsync command forces file transfers only, the from restricts it to only hosts at my employer, and the rest is insurance to keep the connection being used for other purposes.  Here’s lim_rsync:

#!/bin/bash
PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
TERM='vt100'

# Make sure a command is specified (e.g. we're not trying to actually log in)
if [[ $SSH_ORIGINAL_COMMAND == "" ]]; then
exit 1
fi

# Extract the first three bits of the command
TEST_COMMAND=`echo $SSH_ORIGINAL_COMMAND | awk -F" " '{ print $1 " " $2 " " $3 }'`

# If rsync is called with "--server", it means somebody is trying
# to remotely copy files from us.  Allow this.  Deny all others.
if [[ $TEST_COMMAND == "rsync --server ." ]] || [[ $TEST_COMMAND == "/usr/local/bin/rsync --server ." ]]; then
exec $SSH_ORIGINAL_COMMAND
else
exit 2
fi

Of course, there are a lot more SSH tricks.  I highly recommend the O’Reilly SSH book if you’re interested in learning more.

5 thoughts on “Securing your SSH keys

  1. Pingback: Anthony’s Blog » Blog Archive » Intrepid upgrade done!

  2. Pingback: Secure file transfer from (potentially) anonymous users « Blog Fiasco

  3. Christopher, if you use a web-based SSH client, your host will see the traffic coming from the IP of the web server, not the client machine you’re on.

  4. Pingback: Wacky SSH Authorized Keys Tricks | Standalone Sysadmin

Leave a Reply

Your email address will not be published. Required fields are marked *