sections in this module | City
College of San Francisco - CS260A Linux System Administration Module: ssh and VNC |
module list |
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 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:
no passwords transmitted between machines. Even the passphrase stays on the client. The only information shared between the machines is the public key.
you can connect to whatever machine(s) you copied your public key to using a single passphrase. (You can override this by using different key pairs for different servers if you wish, but you will have to specify where the key is when you connect.)
your passphrase can be changed independently of the passwords on the server machines and without altering your keys.
allows remote commands to proceed without human intervention if appropriately configured (discussed later)
Cons:
discovery of passphrase and access to client machine compromises all servers you have set up access to. This makes unattended terminals a real security issue, especially if ssh-agent is used (see below).
never having to login to the servers using your password makes remembering these individual passwords more difficult.
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:
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.
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:
When you login via ssh, the .bash_profile is run. This is the only time the .bash_profile is run unless you configure it specially. Unfortunately, linux implementations have been vacillating on this. To get around this, the if statement avoids starting a new ssh-agent if one is already running.
Since we will not be starting a shell as a child process of the agent, we must kill the agent ourselves when we log out so that it does not continue to run. This is very important on hills. You should never leave agents running on hills! The trap command executes the ssh-agent -k command to kill the current agent when the shell exits. This even works if you get disconnected. (We will learn about traps in the section on process control.)
When ssh-agent is invoked at the command line by itself it outputs shell commands to set the appropriate environment variables to contact it. We must execute these shell commands in our shell. This is the reason for the eval statement.
If you configure this as above on RH7 you will have an agent running no matter how you login.
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 |