Introduction


This is an article on SSH, the marvelous secure socket shell that can be used a myriad of remote login and file transfer ways. The focus of my article is the OpenSSH software package specifically: it's feature-rich, I am the most familiar with it, and lastly (and most importantly) is very prevalent in the Linux world -- it's installed by default in just about every Linux distribution (and Mac OSX, BSD, etc.) Some other client applications for Windows like PuTTY or SecureCRT have some of these features implemented, but that's beyond the scope of this article.

Within this article, I'm going to focus on SSH keys and their uses, and some tools that we can use to manage these ssh keys. I'm planning to release more articles related to SSH, such as scp usage, port forwarding, and so on as time goes on.

History


SSH came into being as a replacement for the older methods of remotely logging into a terminal, which were telnet, rsh and the like (unencrypted, simple protocols.) These older commands and protocols were not designed for the Internet, as it was easy for a malicious user with network access to sniff the the valid users login credentials (username, password, etc.) Far worse, they could even hijack a remote session of someone (even root) being logged in as they're using it, and not need to sniff your password at all. Dave Dittrich wrote this article to break down how this session hijacking can be preformed: session hijacking.

In the beginning, SSH v1 was developed, and there was great rejoicing. Your communications were now encrypted; your user name, your password; the information being sent and received. However, it was still possible to hijack an existing SSH connection, which brought about the ... *drum roll* ... SSH v2 protocol, which patched that bit of nastiness and allowed SSH to become a de-facto standard for accessing remote terminals. As the OpenSSH software package has grown, so has its feature set, including features like: ssh keys, scp (secure copy), and port forwarding; all things that make it very useful.

SSH keys


To start it off -- I'll talk about SSH keys. In layman's terms, they're a pair of files that match each other with some mathematical mumbo-jumbo, one of the files is a private key (which you never share with anyone) and another is a public key (which you can give to anyone.) They're a keypair you can use for authenticating to other SSH servers, allowing you to store the public key on a server you connect to, and using the private key located on the computer you're connecting from, authenticating. For more information you can check out this simple article at Wikipedia: public-key cryptography. What do ssh keys mean in even simpler terms? They make it possible to have password-less logins to remote servers. While this is not recommended, it is a great way to allow cronjobs to run on remote servers.

Here's an easy way to generate an SSH key (-b 4096 creates a high-security 4096-bit key, -q keeps the messages quiet):
  1. ssh-keygen -b 4096 -q


Press enter twice for each of the password prompts so the key isn't encrypted with a password, and your screen should look like this:
  1. user@server1 [~]# ssh-keygen -b 4096 -q
  2. Enter file in which to save the key (/home/user/.ssh/id_rsa):
  3. Enter passphrase (empty for no passphrase):
  4. Enter same passphrase again:
  5. user@server1 [~]#


We now have an unencrypted private SSH key, and a public key. If you ever create one of these unencrypted SSH keys, and want to encrypt it (ie, put a password on it) you can do it with this command ( -p puts ssh-kegen in a password-setting mode, and -f .ssh/id_rsa is the path to your private ssh key):
  1. ssh-keygen -p -f .ssh/id_rsa


This looks like so:
  1. user@server1 [~]# ssh-keygen -p -f .ssh/id_rsa
  2. Key has comment '.ssh/id_rsa'
  3. Enter new passphrase (empty for no passphrase):
  4. Enter same passphrase again:
  5. Your identification has been saved with the new passphrase.
  6. user@server1 [~]#


Copying your SSH key to servers


Now, we upload your public key to a server so that you can authenticate using your ssh key. Run this from your client computer (-i specifies the path to your public ssh key):
  1. ssh-copy-id -i .ssh/id_rsa.pub user@server2


This looks like:
  1. user@server1 [~]# ssh-copy-id -i .ssh/id_rsa.pub user@server2
  2. user@server2's password:
  3. Now try logging into the machine, with "ssh 'user@server2'", and check in:
  4.  
  5.  .ssh/authorized_keys
  6.  
  7. to make sure we haven't added extra keys that you weren't expecting.
  8. user@server1 [~]#


This great command will copy your public key to the remote server, and automatically add it to the authorized_keys file. It will automatically create the file and needed permissions, if this hasn't been done previously.

If all of the above has worked properly, connecting to a remote host is as easy as this:
  1. user@server1 [~]# ssh server2
  2. Last login: Thu Sep 11 19:59:46 2008 from server1.local
  3. user@server2 [~]#

Tada!

Unless you're using your SSH key to allow cronjobs to execute on remote servers, you should have all of your ssh keys encrypted with a password. This has a few benefits -- to gain access to multiple systems, you can just change the password on the ssh key. Now you don't need to update your user password on all of the systems, since they're not authenticating against the local password, they're authenticating against your ssh key. You can alter the password on your private key without affecting the public key you've distributed.

Keychain


I'll iterate again: you should always have your ssh keys encrypted, unless you have an explicit reason not to. However, here's a great way to keep your keys safe, and it keeps us from having to type passwords all of the time: keychain. This wondrous little tool manages your SSH keys so that you only have to type your password once per reboot (although you can configure how often it times out.) It'll decrypt your ssh key and store in it a secure memory page, so you don't need to worry about that. Add this code blurb to the bottom of your ~/.bashrc:
  1. keychain --nogui -q $(find $HOME/.ssh/ -type f -name 'id_[r,d]sa')
  2. . $HOME/.keychain/$HOSTNAME-sh


Now run:
  1. . ~/.bashrc

You should get a prompt to type the password for each of your SSH keys, decrypting them for reuse. Now you can try logging into those remote servers and not have to type passwords over and over. It's really slick. Just make sure you always lock your workstation after you're finished, otherwise that wouldn't be good (if you don't, anyone sitting at your computer will have access to anything you have ssh keys setup on.) Make sure you're careful with this, always get in the habit of locking your desktop when you're away from it, and having a good password set on your desktop computer.

Hashing your known_hosts file


Last up in our little whirlwind tour is making sure that your known_hosts file is hashed, which is a good step you should take. If someone else gains access to your account, they can view that file to see which servers you connect to, and if you have password-less ssh keys setup on them, they could log into them... that could be dangerous. We can hash this file so an intruder can't determine what servers you're connected to:
  1. ssh-keygen -H


It looks like this:
  1. user@server [~]# ssh-keygen -H
  2. /home/user/.ssh/known_hosts updated.
  3. Original contents retained as /home/user/.ssh/known_hosts.old
  4. WARNING: /home/user/.ssh/known_hosts.old contains unhashed entries
  5. Delete this file to ensure privacy of hostnames
  6. user@server [~]#


It's a good idea to delete that old file:
  1. rm ~/.ssh/known_hosts.old


You've reached the end of this article. You can now go forth, create ssh keys, and be happy.