Skip to content


Understanding and Using SSH

Presented by Moshe Jacobson on September 18, 2001

Table of Contents


1. How SSH Works


1.1. How SSH negotiates an encrypted session

The server has a 1024bit public/private host key pair that remains
constant, as well as a 768bit public/private server key pair that changes
hourly.

When a client connects, the server sends its public host and server keys
to it. To determine if the host is legitimate, the client keeps a cache of
the host keys of all the servers it has ever connected to. If the public
key sent by the server is indeed the same as the one in the cache, all is
good. If not, the client is warned: someone may be trying to intercept the
connection.

The client then generates a random 256-bit key, which it encrypts with
both of the public keys sent from the server, and sends back this
encrypted key. The server unencrypts the 256-bit key with its own private
host key. Now both sides have a common key unknown to anyone else, which
will be used to encrypt the rest of the traffic in the ssh session, with a
cipher such as Blowfish or 3DES.


1.2. Password authentication

Once the encrypted session has begun as described above, the password can
be sent from the client to the server with no worry that it will be
sniffed; it is never sent in plaintext since the session is already
encrypted.

The advantage of password authentication is that it is very secure, prone
only to keylogging. Because of this weakness, however, you should try not
to type any passwords on systems where root may be running a keylogger.
This, of course, is a precaution that applies much more broadly than to
just ssh.


1.3. RSA key authentication

A more secure method of authentication is through the use of RSA keys. The
basic principle is as follows. Each user generates a 1024bit
public/private key pair for himself. Generally, each user has a different
key for every system he is on, but frequently, if he has multiple trusted
hosts, it can be more convenient to use the same key on all the systems to
simplify things.

Any host to which the user wants to connect must be aware of his public
RSA key, as the server uses it during the authentication process. The user
must place his public key living on the originating client machine, into
his own authorized_keys file on the server.

When he wants to connect to that server, ssh will first negotiate an
encrypted session, then send the server the client’s public key. The
server checks that the public key is in the user’s authorized_keys. If so,
the server sends the client a challenge (a random number encrypted with
the user’s public key). If the client can then send back the random number
unencrypted, it has just proven that it has the private key (there is no
other way to unencrypt the challenge number), and is therefore authentic.

The user’s private key is a very sensitive piece of data – with it,
anyone can connect to any host on which the corresponding public key is in
the authorized_keys. Therefore, the user’s private key is never written to
disk unencrypted.

The private key is encrypted using a passphrase made up by the user. The
passphrase should generally be around 20 characters in length to prevent
brute force cracking attempts against it. With a safe passphrase, there is
little risk in exposing the private key.

The advantage of RSA based authentication is that a password is never sent
across the line, even in encrypted form. Additionally, you have to
remember only one passphrase rather than a password for each system you
log into. However, because of the neccessity for a long passphrase on a
private key, it is becomes very inconvenient to type it every time you
connect to another host.


1.4. Authentication agents

To ease the use of RSA keys, one may use an authentication agent such as
ssh-agent. ssh-agent is simply a daemon that caches a user’s unencrypted
private key(s), to save the user from having to type his passphrase every
time he wants to connect to another host.

Every key that the user wishes to be cached must be added to the agent’s
cache by running ssh-add and typing in the passphrase for the key being
added. Multiple keys may be added to a single agent. The agent will
automatically determine which key (if any) can be used to authenticate you
on a host.

When run, ssh-agent creates a named socket file under /tmp, whose
permissions are set to allow only you to read from and write to it. It
places the name of this file into an exported environment variable,
$SSH_AUTH_SOCK. ssh client processes that have this agent running as an
ancestor process will have this variable available to them to inform them
how to communicate with the agent. Communication with the agent is done
by reading from and writing to the named socket in $SSH_AUTH_SOCK.

Once the ssh client has contacted the running ssh-agent, it attempts to
authenticate with the server in the same method as mentioned before.
However, the user does not have to type the passphrase for the private
key, as it is already available from the agent in its unencrypted form.

Because the user’s private keys are stored unencrypted in the memory of
the client machine when using ssh-agent, care should be taken that keys
are not added to ssh-agent on systems where root is untrusted, as root has
access to shared memory, and can steal the user’s unencrypted key and
access any hosts to which the added keys grant access.

A drawback of using RSA authentication is that once a key is used to log
into a remote host, they key is no longer available for further
authentication, as it is not available anywhere in the host machine’s
filesystem or memory. To circumvent this problem, an arguably unsafe trick
called agent forwarding is used.


1.5. Agent forwarding

Ssh has the ability to "forward" the ssh-agent it is using, in order to
make it available to the user after he has connected to the remote
machine. Say You have a key on system A that authenticates you on hosts B
and C. The key is not available to you on host B though. With forwarding,
you can ssh into host B and still have a pseudo-agent available to you on
B, which forwards requests back to the real agent running on A. When you
connect to B, the $SSH_AUTH_SOCK is set to point to this pseudo-agent, and
is exported in your environment on B. Now you can authenticate yourself on
C from B without typing a single password or passphrase.

Because agent forwarding provides access to the agent running on system A,
it is now possible for root on system B to connect to the agent on A by
way of the pseudo-agent created for forwarding, and authenticate himself
with the user’s keys. He can then log into to any system allowing one of
the user’s added keys.

Therefore, agent forwarding should never be used when connecting to a
system on which root is untrusted. If the user must connect to multiple
untrusted systems, he should disconnect from one before connecting to
another – forwarded agents can be hijacked and passwords can be
keylogged.


1.6. A Safe Solution

  • Do not forward your agent to untrusted hosts. If you must go through an
    untrusted host B to get to host C, you must then
    trust root on B with access to C, period.
  • If you’re not sure what to do, use password authentication. It requires
    typing a password, but is safer: If someone sniffs your password, they
    only have access to the one system to which you’re connecting, rather
    than all the systems on which your key is authorized. (You are

    using different passwords on each system, right?)


2. Using Secure Shell


2.1. Using the client

To connect to a remote system using ssh, invoke ssh with the following
form:

ssh [user@]host [command]

If your username on the remote system is the same as on the local system,
you may omit the user@, and your local username will be used.

If you would like to execute a command on the remote system and
immediately disconnect (rather than executing a shell and entering an
interactive session), you can specify the command to run after the
hostname specification. Remember that the program may not be in the search
path on the remote system, so it is always a good idea to give the full
path to the program if you’re not sure.

So for example, if I wanted to ssh to acme.gatech.edu and list the
contents of /bin, it would look something like this:

[jehsom@jolt ~]$ /usr/bin/ssh gte741e@acme.gatech.edu ls \~/bin
gte741e@acme.gatech.edu's password:
myindent
vncviewer.exe
[jehsom@jolt ~]$

Notice that I escaped the ~ in ~/bin. Otherwise the local shell would have
expanded it to /home/jehsom, which doesn’t exist on acme. The way I prefer
to pass a command to ssh is to pass the whole thing in quotes:

/usr/bin/ssh gte741e@acme.gatech.edu "ls -l ~/bin"

Special shell characters such as ~ (as well as many others) will be passed
straight through to the remote system and handled by the remote shell.
This is what you want.


2.2. X11 Forwarding

One of the best features of ssh is its automatic X forwarding. If you have
properly set your DISPLAY environment variable on the local machine (this
will be the case if you’re running in a terminal window under X), then ssh
will automatically negotiate the forwarding of the display to the remote
server. This means that when you connect to the remote machine, you may
start graphical X programs, and have them display their interfaces on the
local X server. All X11 traffic is encrypted, of course, which is an added
benefit to the usual method of using xhost and exporting your DISPLAY.


2.3. SSH Client Configuration Options

Your ~/.ssh/config file contains all the client functionality options.
You can restrict settings to specific hosts by preceeding them with a
"Host hostname" line. Put all your global options first, because every
line following a Host declaration will apply only to that host.

Some interesting options (again, ripped from man ssh(1)) are:

Posted in Articles.