http:// www.jms1.net / ssh.html

SSH Information

A user on my Linux User Group's mailing list recently asked how to use scp to securely copy files from one machine to another, without having to type their password.

I can think of two reasons you would want to do this, and each reason involves its own solution to the problem. However, I'm a firm believer in the idea the people should know how things work. I would highly recommend O'Reilly's SSH book, especially since that's how I learned a lot of this stuff myself.


Software

There are currently two versions of the ssh protocol in use, called (surprisingly enough) ssh1 and ssh2. The ssh1 protocol can be successfully attacked through its connection setup protocol and is therefore not commonly used anymore. The ssh2 protocol has a more robust connection-setup protocol, and is also more flexible.

There are two commonly used packages for the ssh2 protocol- the commercial version, from ssh.com, and OpenSSH, which is more commonly used (probably because it's free.) OpenSSH is included with most Linux distributions.

The rest of this document will assume that you are using OpenSSH.


The SSH2 Protocol

The ssh2 protocol is built on a two-layer model. A "connection" or "tunnel" is a TCP/IP socket between an ssh client program and an ssh server program. The packets being sent through the connection are encrypted with a form of shared-key cryptography, using a random key which is generated for each new connection and thrown away when that connection is over. The client and the server use public-key cryptography to agree on the session key, and either party may request a re-keying of the session at any time.

Each tunnel contains one or more "channels". A "channel" is a connection (between programs) within the connection (between machines). For example, a simple "remote login" ssh connection will have one channel inside of the connection. If you are using X11 forwarding, a second channel within the same connection is used to carry the X11 packets, separate from your remote login session.


Sessions

When an ssh client connects to an ssh server, the client requests one or more sessions, each of which uses a channel. The server uses the type code to determine what program(s) to run in order to provide the services which the client has requested. For example, the "server-session" type will cause sshd to run your login shell over the conenction.

A channel can also be used for "port forwarding", where packets sent to a given port number on the local machine are transferred through the tunnel and appear on the server as if they had originated on the server itself.


Authentication

The whole reason for running a server is to provide access to one or more services. However, you obviously don't want to allow just anybody to access it. When a server accepts an incoming connection, the first thing it does (after setting up the encryption) is verifies that the client is authorized to access the service(s) they're asking for.

There are several ways that a client can prove they are who they say they are. The simplest is by using a password, but other methods exist. The most common method (other than passwords) is by using keys to authenticate.

The idea behind public key cryptography is that you generate a pair of keys, which are matched in such a way that a message encrypted with one key can only be decrypted with the other key. You can give the "public key" to anybody in the world, and this enables them to encrypt a message so that only you can read it. By using other peoples' public keys, you can send messages that only they can read.

By generating a key pair and installing the public key on the server, you can use the secret key to prove that you are who you claim to be. It works like this:


Creating a Key Pair

The ssh-keygen program is used to create key pairs. SSH key pairs are stored in two separate files, usually in the .ssh directory in your home directory.

To generate a key pair, run this command on the machine you will be using as the client (i.e. your workstation):

(user@client) > ssh-keygen -t dsa -b 1024 -f id_dsa_something -C 'Some comment'

This creates a DSA key with 1024 bits of random key material, stores the secret key in a file called "id_dsa_something", and stores the public key in a file called "id_dsa_something.pub" with the indicated comment. The key length, 1024 bits, is currently the "standard" length. I have used keys with 2048 bits, and the ssh-keygen program will accept anything as high as 32768 bits. 4096 bits is considered "military grade", anything above that is probably overkill, since the key isn't protecting the session traffic, only the negotiations for the session key.

After the program has generated the keys it will ask for a passphrase. This passphrase encrypts the contents of the secret key file, so that if somebody else managed to get a copy of your key file, they can't use it unless they know your passphrase.

You notice that it's called a passphrase instead of a password. The reason is that if you use a passphrase, it should be longer and harder to guess than a standard password.

If you are generating a key pair which will be used by a program, you should not put a passphrase on the key (i.e. when it asks, just press ENTER.). However, if you do this, you should generate and install new key pairs periodically, especially if other people have access to the system where the secret key is stored, just on the off chance somebody manages to get a copy of the secret key file.


Installing the Public Key

In order to use the key to access a server, a copy of the public key must be installed on the server, in the .ssh/authorized_keys2 file in the home directory of the userid you will be accessing on the server. This is required no matter what kind of sesion you will be using.

Of course, you must have some method of putting the file there in the first place. This example assumes that you also have password access to the account:

(user@client) > scp id_dsa_something.pub user@server:
user@server's password:
id_dsa_something.pub |********************| 0 0:00
(user@client) > ssh user@server:
user@server's password:
(user@server) > cat id_dsa_something.pub >> .ssh/authorized_keys2
(user@server) > chmod 600 .ssh/authorized_keys2
(user@server) > exit

This is not the only way to get the public key file into place. You could also copy it on a floppy disk, or email it to the system administrator and have them install it for you (remember this is the PUBLIC key, there is no security risk in sending it via normal email.)

Note that you can have multiple keys listed in the .ssh/authorized_hosts2 file- this is why the public keys have comments at the end, so you can easily tell which line in the file corresponds to which key.

You can test it with a command like this:

(user@client) > ssh -o 'IdentityFile2 id_dsa_something' user@server
Enter passphrase for key 'id_dsa_something':
(user@server) >


Use by a Program

There may be times when programs (such as backup scripts) need to securely copy files from one machine to another. The scp and sftp programs were designed for copying files from one machine to another. They work by opening an ssh connection and requesting the sftp service instead of the normal server-session service used for a remote login shell session.

To use these programs without having to enter a password, you can use a key to authenticate. Of course you have to install the public key on the server first (see above.)

This is an example of how to specify a key to use with scp.

(user@client) > scp -o 'IdentityFile2 id_dsa_something' files-to-copy user@server:

This is an example of how to specify a key to use with sftp.

(user@client) > sftp -o 'IdentityFile2 id_dsa_something' user@server
sftp>


Forcing Commands

You may wish to set up a certain key to be able to log into the server, but only for certain things- a backup script, an rdist server, whatever. It's possible to add a "forced command" to the authorized_keys file, so that whenever somebody authenticates with a given key, it runs the forced command no matter what- even if the client asked it to run something else.

To set this up, add command="....." at the beginning of the line containing the public key.


Use with an Agent

An agent is a program which stays in memory on your workstation, holds copies of one or more secret keys, and uses those keys to sign the random numbers sent by the ssh server. SSH client programs (ssh, scp, sftp) are written to use the keys stored in an agent, if one is present, and if one of the keys stored in the agent is able to satisfy the authentication request.

These programs find the key by looking for the environment variable SSH_AUTH_SOCK. If present, this environment variable will contain the filename of a unix socket which is used to request authentication.

There is a feature of ssh called agent forwarding, where you can run an agent program on your workstation, and all of your ssh connections have access to the same agent.

The process works like this:

As long as the various clients and servers are all configured to allow agent forwarding, this "chain" can go on as long as you need. At the ISPs where I used to work, I had one key on my workstation and all of the servers had this key in my userid's .ssh/authorized_keys2 file. I was able to run the agent on my workstation, and didn't need to enter passwords or passphrases to get into any of the servers, or to copy files between the various servers when needed.

While this sounds like a good thing, when writing programs that manipulate or use keys you have to remember that the agent connection is there. I wrote several programs which copied files between machines (backup scripts, automated dns propogation scripts, and so forth) and while testing these scripts, the agent interfered with the keys I was specifying on the command lines. I ended up having to add an instruction into these programs to delete the SSH_AUTH_SOCK environment variable before running any external commands (such as ssh or scp.)


Automating the Agent

On many systems, the process of starting up the agent is already done for you when you log into the system. You can check whether or not this is the case by checking for the existence of an environment variable called SSH_AUTH_SOCK. For example, this session has an agent available...

(user@client) > echo $SSH_AUTH_SOCK
/tmp/ssh-ArQve20135/agent.20135
(user@client) >

and this session does not.

(user@client) > echo $SSH_AUTH_SOCK

(user@client) >

If you don't already have an agent running, you can use the commands listed in the section above to start one up. Coming soon... a script to automate this for systems which don't automatically do it for you.


Recording SSH sessions

It is possible to keep a transcript of the contents of an SSH session, by combining ssh or sshd with other programs which most *nix-like systems have already. http://www.jms1.net/ssh-record.shtml explains how to do it, both from the client end and from the server end, depending on your needs.