## Introduction

In this guide, I will set up secure, keyless SSH access from a test server, server.example.com to a client client.example.com.

I type “secure” since ordinary keyless SSH setups do not involve entering a password for the SSH key. It is easy to see how this is useful for cron jobs, for example, which might need access to client machines. This also means that if the server is compromised, it is trivially easy to gain access to its keyless clients.

This situation can be improved greatly with strong passwords, ssh-agent and its delightful front-end, keychain.

## Pre-flight - Pertinent folders and permissions

Explained later

### Commands

• ssh-keygen - Used to generate keys
• ssh-copy-id - Copy a key from the server to client (CentOS only)

### Files and Folders

• <User Home Folder>/.ssh - Folder which stores all keys for the user
• The access permissions need to be 700!
• <User Home Folder>/.ssh/authorized_keys - Plain text file with public keys authorized to ssh into the machine as this user
• The access permissions need to be 600!

### This is Ridiculously Crucial

• It is vitally important that the permissions on the .ssh folder and authorized_keys are 700 and 600! Save yourself a lot of mental anguish by remembering this outright!

## Generating SSH keys for keyless access

### Generating default keys

This is simple. For typical ‘keyless’ access, you would just hit Enter when asked for a password. Not now! Choose a nice, secure password for your default key and type it in twice.

ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/var/user/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:


You should now have two files in .ssh in your home folder. These are id_rsa, your private key, and id_rsa.pub, your public key. Do not share your private key.

### Copy the Public key to the Client

On CentOS, this is very simple:

ssh-copy-id -i ~/.ssh/id-rsa user@client.example.com


Note: Don’t worry; the command above doesn’t copy the private key of the identity pair. Since the command is a bash script, you can verify this yourself.

On Mac OS X, you do it the traditional way (or you can port the ssh-copy-id script over from CentOS):

scp ~/.ssh/id_rsa.pub user@client.example.com:/var/user/.ssh/server-key.pub
ssh user@client.example.com
cat ~/.ssh/server-key.pub >> ~/.ssh/authorized_keys
rm ~/.ssh/server-key.pub


### Verify Permissions

• Make sure that .ssh and authorized_keys within it have permissions 700 and 600 respectively.
• Make sure that your generated keys (public and private) have permissions of 600.

OpenSSH is picky like that.

### Test the Connection

Assuming you’re logged in as user on the server:

ssh client.example.com
Enter passphrase for /user/.ssh/id_rsa:


Enter the password to your SSH key, and you should be in! Yay!

## Back to Square One? Not with ssh-agent!

### Some background

So here’s the deal: You might think this is pointless since you’ll have to enter a password anyway (for the key in this case.) However, ssh-agent caches private keys (and, in our case, login information to client machines) in memory. From the horse’s mouth:

ssh-agent is a program to hold private keys used for public key
authentication (RSA, DSA).  The idea is that ssh-agent is started in the
beginning of an X-session or a login session, and all other windows or
programs are started as clients to the ssh-agent program.  Through use of
environment variables the agent can be located and automatically used for
authentication when logging in to other machines using ssh(1).

Although there exist many scripting examples which initialize and use ssh-agent, we’ll make that easier with the amazing Keychain. Why I like it is purely because it maintains a single ssh-agent process per system, rather than per session.

### Installation

On CentOS, just issue yum install keychain after installing DAG’s RPMForge repo (see Resources on this page). On OS X, check out the download page.

### Using Keychain

Remember that I’m trying to log in as user on both server and client. I’ll add this to .bashrc on CentOS, or .profile on OS X on the client machine’s user home folder:

eval keychain --eval --agents ssh id_rsa


Now log out and log back into the server. You should see this:

 * keychain 2.6.10 ~ http://www.funtoo.org
* Found existing ssh-agent: 274
* ssh-agent: All identities removed.
* Adding  1 ssh key(s): /var/user/.ssh/id_rsa
Enter passphrase for /var/user/.ssh/id_rsa:


You should have full keyless access to the client after entering the password to the private key at this point. You may now have a drink.

### Not so fast

Remember that Keychain allows ssh-agent to cache private keys per system. This means that the next time you log into the server, Keychain will not ask you for the private key’s password since it’s already cached it in memory. So if you entered the user password to the server, here’s what you get the second time you log in. For a compromised server, this may be as good as a password-less login.

user@server.example.com's password:
Last login: Sun May  2 23:53:38 2010 from 173-30-221-179.client.mchsi.com

KeyChain 2.6.8; http://www.gentoo.org/proj/en/keychain/
Copyright 2002-2004 Gentoo Foundation; Distributed under the GPL

* Found existing ssh-agent (17986)
* Known ssh key: /user/.ssh/rsync-key


### Securing Keychain Further

How do you fix the situation? Simple!

1. You assume that a user is an intruder until s/he has proven otherwise.
2. If the user has not entered the correct passphrase for a private key, flush the key from memory

This works, because keys are cleared by ssh-agent on log out, not log in. Here’s how you’d edit .bash_profile or .profile:

eval keychain --clear --eval --agents ssh id_rsa


At the next login, Keychain will ask you the passphrase for your keypair. Try entering a bad one a few times and logging into the client machine. If you’ve set this up right, you’ll be asked for a password to the machine!

## Working with Multiple Identities

In the example above, we’ve used the server’s default SSH identity. id_dsa/.pub and id_rsa/.pub are the keypair for this identity. It may not be preferable to use this one single identity for multiple clients. You’re able to generate other identities using ssh-keygen, by typing in the name of the keypair when it asks you for one:

ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/var/user/.ssh/id_rsa): sample-ssh-key
Enter passphrase (empty for no passphrase):
Enter same passphrase again:


### Using the key for SSH

When you use the id_dsa/.pub or id_rsa/.pub keypairs, you don’t need to specify the -i (identity) switch with the SSH command since they’re default keys. This is how you’d use another identity to SSH in:

ssh -i ~/.ssh/sample-ssh-key client2.example.com


Note that you used the private key in the example above! This command will ask you for the password to the sample-ssh-key private key, assuming you’ve copied over the public key to authorized_keys on the client (as describe in earlier sections.)

### Using Keychain to Store Multiple Identities

Simple! For each secure identity you create, just add its appropriate line to .bash_profile or .profile and ask Keychain to store this in memory. For the example above:

eval keychain --clear --eval --agents ssh  sample-ssh-key


The next time you log in, you’ll be asked the passphrases to each private key you’ve defined via Keychain. For the id_rsa and sample-ssh-key keypairs above, here’s what I see:

 * keychain 2.6.10 ~ http://www.funtoo.org
* Found existing ssh-agent: 274
* ssh-agent: All identities removed.
* Adding  1 ssh key(s): /var/user/.ssh/id_rsa
Enter passphrase for /var/user/.ssh/id_rsa: