sections in this module City College of San Francisco - CS260A
Linux System Administration

Module: ssh and VNC
module list

ssh key-based authentication

Remember, in this discussion, the client is the system you are connecting from (the one you type ssh on). The server is the system you are connecting to.

Unfortunately, the term key is difficult here. In this page, 'key' refers to the asymmetic key used to authenticate. The session key, which is symmetric, and is being used to encrypt the entire session, was discussed in the previous page.

The basics are very simple: you generate a key pair on the client using ssh-keygen. This key pair is only used for authentication. The session key (which is being used to encrypt the session) is already in use. In keeping with our simple approach, we will assume you are satisfied with a single key pair placed in the default location and want to use the ssh2 key type of RSA. (Note: the DSA key encryption is no longer considered secure and, in fact, it is recommended that you use extra-long RSA keys, which is what we will do.)

[jose42 ~]$ ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/home/jose42/.ssh/id_rsa):
Created directory '/home/jose42/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/jose42/.ssh/id_rsa.
Your public key has been saved in /home/jose42/.ssh/id_rsa.pub.
The key fingerprint is:
50:90:c6:3a:d2:d9:55:3a:3c:f5:50:1f:37:ed:74:f1 jose42@unixguy4.com
The key's randomart image is:
+--[ RSA 4096]----+
|     ..o..+.. .o+|
|      +o.o o . o*|
|   . =..=   . .oE|
|  . = .. o      .|
|   . .  S        |
|                 |
|                 |
|                 |
|                 |
+-----------------+
[jose42 ~]$
 

As you can see, ssh-keygen generated two keys. The private key is what protects your identity. It must be kept secure in a file that is readable only by you (or ssh will refuse to use it). By default, it is placed in ~/.ssh/id_rsa  The public key will be shared with whichever hosts you want to get access to. It is placed in ~/.ssh/id_rsa.pub. We asked ssh-keygen to generate a longer key (4096 bits) than the default (1024 bits) for extra security. This will slow down connections slightly. The addition of this option is up-to-you.

To generate the key, you were asked to give ssh-keygen a passphrase. This is a phrase rather than a password, as spaces are allowed and encouraged. You should always use a passphrase, as, without one, anyone who gains access to your account could ssh to any system you have shared keys with without specifying a password. The passphrase is used to encrypt (and, later, decrypt) the contents of id_rsa so that no one can steal your private key if they gain access to your account. We will discuss the uses of passphrase-less keys later, but the most important reason to use a passphrase is it makes the compromise of your private key inconsequential. Without a passphrase, anyone who can copy your private key can assume your identity. (ssh will refuse to use your key if it is readable by anyone other than you.)

To connect with a server using keys, you must now append the contents of ~/.ssh/id_rsa.pub (on the client) to the file ~/.ssh/authorized_keys on the server. It is highly recommended that you restrict the new key's use by prepending an option to say who can use the key. Suppose the client (on which you generated the keys) is local.com and the server is remote.com. If the contents of ~/.ssh/id_rsa.pub on local.com is XXXX, you should add the following line to ~/.ssh/authorized_keys on remote.com

from="local.com" XXXX

(Note that the key is several hundred bytes long, so it is a little longer than XXXX)

Without the from="local.com" restriction, any client can present the XXXX key to start the authentication process. (You may want this to be the case in some instances.)

If the key is to be used for a single purpose you may want to automate/restrict the command it runs. This can be done by adding the command="command" option.  If both options are used, they should be separated by a comma.

On some linux systems, your umask is set so that data is group-writable. ssh will silently refuse to use keys if your .ssh directory or its contents are writable by anyone but you, the owner. Furthermore, your id_rsa file (the private key) on the client must have permissions 600. It may not be readable by anyone but you.

Now that we understand that the client and server share the public key, whereas only the client has the private key, we get to the center of the technique: The private key must be used to decrypt messages encrypted with the public key. Now let's talk about how authentication proceeds:

Authentication using the key pair

ssh authentication proceeds through several mechanisms. During the process, keys are tried before the server resorts to an account password challenge. In other words, if the server can not find an authorized key that matches the public key, authentication using the password for the user's account on server is still attempted. (This is the usual case. The types of authentication tried and the order in which they are tried are configurable by the system administrator on the server.) Here is the sequence of events when trying to authenticate with a key pair:

1. the client sends the server the public key (the contents of ~/.ssh/id_rsa.pub)

2. the server reads the authorized_keys file from ~/.ssh in the user's account and looks for a matching key. If the matching key is restricted (using from=...), the client's identity is checked. If a usable matching key is not found, authentication using keys fails. We will assume a usable key is found

3. the server generates a random string and encrypts it using the public key. It sends it back to the client.

4. the client decrypts the string with the private key. It them combines the resulting (decrypted) string with the session identifer (known to both server and client), creates an MD5 hash of the result and sends the hash value back to the server.

5. the server computes the same hash of the original string and the session identifier and compares it to the client's response. If they match, authentication succeeds. Otherwise, authentication fails.

Remember, use of a passphrase is essential. Besides making it impossible to connect to another system if your account is accessed, it makes id_rsa (your private key) much less valuable if it is compromised, as it is encrypted. (However, compromise of an encrypted key or password provides the opportunity to break the encryption by brute-force attacks on the encryption. Longer, more random passphrases are better.)

You can change your passphrase without regenerating your keys. Simply run ssh-keygen with the option -p . It will ask you for your old passphrase and a new one. It will then decrypt your private key using the old passphrase and re-encrypt it using the new one. Your public key will still work. Note that this does not protect you if the encrypted key has been stolen - the underlying key is the same.

Let's analyze this key mechanism for pros and cons:

Pros:

Cons:

Using ssh-agent

Note: when you are using ssh-agent, never leave your terminal unattended!

When you use ssh keys and establish an ssh connection to a remote site you are asked for your passphrase so that your private key can be decrypted. Although the passphrase is the same for each site that you have copied your public key to, it requires you to enter the passphrase whenever you connect. This is no more convenient than having to type your password:

$ ssh hills.ccsf.edu ls -ld .
Enter passphrase for key '/home/gboyd/.ssh/id_rsa':
drwx--x--x  53 gboyd      cisdept       4096 Jul 20 08:51 .

The alternative mechanism is to use ssh-agent as a repository for your keys. If ssh-agent has been started, ssh will contact it to see if it has the key. If it does, the connection continues unassisted.

Unfortunately, configuring ssh-agent to start and initialize itself automatically at login is a bit complicated. In the remainder of this section we discuss three ways to configure it depending on how you use your machine.

ssh-agent when logging into the GUI

If you want to ssh out of your machine from a terminal started at the GUI, you're in luck. Incorporation of an agent is now automatic! On current versions of linux, ssh-agent has been incorporated into the GNOME keyring. If you are using the GUI, your display-manager already has an agent. The first time you ssh you will be asked for your passphrase, and your key will be stored in it. The GNOME keyring (managed by seahorse) will store your ssh key with any other passwords you want to assign to it. It will even allow you (via a checkbox) to indicate that GNOME should store the passphrase between logins, but do not do this as it defeats the idea of a passphrase! Your key will be used until you log off of the GUI. Unfortunately, this mechanism does not work if you ssh to your machine and then want to ssh out to another machine.

From your home linux box where you always start from the GUI, then, things are now nicely automatic.

We will now continue and talk about how to set up an agent on a machine when you ssh into it. Then we will discuss how to merge the two techniques. First, we need more details on how the agent works.

Communicating with the agent

The problem with ssh-agent is once you start it, all your shells must communicate with it. ssh-agent is contacted by ssh through use of a socket. When you start ssh-agent, it sets up the socket and initializes environment variables, particularly SSH_AUTH_SOCK, which points to the agent's socket and SSH_AGENT_PID, which contains (you guessed it) the agent's process-id. You must get these environment variables into your shell's environment in order for ssh (and any child ssh's) to contact ssh-agent later. Of course, the issue is the old parent-child one. If you start ssh-agent as a child process, it cannot set environment variables in your shell. So, first, we will discuss the manual method that you can use when you login to start and initialize the agent yourself.

Method one: Configuring ssh-agent manually at the command-line when you ssh in.

Note: if you use this technique when you are logged in at the GUI, you will have an agent in a single shell. When you login at the GUI your agent must be started by the display-manager so that it communicates with all your shells.

When ssh-ed in, the simplest way to get around the parent-child environment issue is to start the agent by hand (at the command-line) and ask it to start a new shell for you. Later, you add the keys to the agent using ssh-add, and connect as often as you like to whatever machines you share the key with. As long as all connections are made from the shell the agent started (or its children), you will be communicating with your agent using your environment variables. This is simple if you remotely connected, as you will start with a single shell anyway. Here are the commands as executed at your shell prompt:

$ ssh-agent /bin/bash
$ ssh-add
Enter passphrase for /home/gboyd/.ssh/id_rsa: you type your passphrase here
Identity added: /home/gboyd/.ssh/id_rsa (/home/gboyd/.ssh/id_rsa)

Now you can use ssh to connect to the servers with which you have shared your public key. ssh will contact your agent for the (already decrypted) key, so you no longer need the passphrase.

$ ssh hills.ccsf.edu
Last   successful login for gboyd: Tue Jul 20 10:46:37 PST8PDT 2010 
Last unsuccessful login for gboyd: Tue Jul 20 10:54:58 PST8PDT 2010     
Last login: Tue Jul 20 08:51:28 2010 from dsl412-109-332.sfo1.dsl.speakeasy.net
[hills]$

A nice side-effect of this is when you log out of your shell, the agent is killed automatically, although to log out you must type exit twice - once for the agent's subshell and once for your login shell.

Method Two: starting the agent from your .bash_profile at login

It would be nice to be able to start the agent and do an ssh-add at login automatically. Unfortunately, you cannot use the commands above (ssh-agent /bin/bash) in your .bash_profile since your .bash_profile will stop when the agent is started, disregarding any following ssh-add command (until you typed exit!) (Well, you could use the ssh-agent command as the last command in your .bash_profile, but you would have to remember to invoke ssh-add yourself!)

Instead, you must start the agent in your current [login] shell and import the information that the agent produces about how to contact it into your login shell. Then, since your agent did not start your current shell, you must remember to kill the agent when you log off. The following sequence for .bash_profile does this. It also has the added benefit of ensuring it doesn't start a new agent if one is already in your environment. This sequence can be used for a machine on which you login using the GUI as well, since the if statement will avoid launching a second agent.

Here are the lines to add to your .bash_profile. We will discuss them below:

if [ -z "$SSH_AUTH_SOCK" ]; then
    trap 'ssh-agent -k' EXIT
    eval $(ssh-agent)
    ssh-add
fi

Unfortunately, some of this code is a forward reference in this class. The code is explained below:

It's a bit complicated, but fairly compact. You can add the same code to both hills and linux. Remember to edit your .bash_profile carefully, however, as a syntax error could keep you from logging in.

Note: when you login at the GUI on RH7, your .profile is sourced. Whether your .bash_profile is sourced or not has varied as RH7 has progressed. Currently (and I think this will be permanent for backwards compatibility), gnome-session is started from login shell, which sources your .bash_profile.

If you configure this as above on RH7 you will have an agent running no matter how you login.

Note on RH6

On RH6, the best way to get an agent started when you login either at the GUI or via ssh is to disable the ssh-agent in the GUI. Then, since your .bash_profile is sourced at the GUI login, everything works the same. To disable your GUI's ssh-agent on RH6,you must alter the gnome-keyring settings using the gnome configuration editor gconf-editor. You can start gconf-editor from the commandline or access it via the menus. At the time of this writing it was in Applications->System Tools->Configuration Editor. Open the apps tab, then the gnome-keyring tab. Select the daemon components and uncheck ssh.

Do not leave agents running on our linux systems, especially on hills. I don't want to get complaints from the system administrator.

Warning: if you use ssh-agent and enter your passphrase using ssh-add, your login session now has free access to all the servers on which your key is used without entering a password or passphrase. Once again, do not leave your terminal unattended!


Prev This page was made entirely with free software on linux:  
Kompozer, the Mozilla Project
and Openoffice.org      
Next

Copyright 2015 Greg Boyd - All Rights Reserved.