SSH Configuration Notes:

Val Schmidt

February, 2002

 

These notes are compiled to provide guidance regarding configuration of ssh, and intended to further clarify those provided in the O'Reilly manual.  Corrections and comments are apreciated and may be sent to vschmidt@ldeo.columbia.edu. 

 

These notes are tailored for SSH2 and OpenSSH server and client software. 

 

Note the definitions of the terms below as they will greatly aid in what are sometimes difficult discussions of exchanges between client and server..

 

                            Server:  The computer on which the ssh daemon is running, and the daemon itself..

                            Client:  The ssh client software through which users connect to the ssh daemon

                            User: a person.

 

Also note that serious confusion can result from not being entirely clear regarding protocol versions (ssh1 and ssh2) and server and client software (SSH1, SSH2, OpenSSH, etc). For example, SSH1 software only supports the ssh1 protocol.  SSH2 and OpenSSH support the ssh2 protocol and optionally are backward compatable with the ssh1 protocol.  Don't be confused by the fact the most current version of OpenSSH is v3.0 (Mar 2002) and is often written OpenSSH3.0.  There is currently no ssh3 protocol.

 

I have made every effort to use lower case when refering to protocols and some combination of lower and upper case for software. 

 

There is much more than can be very confusing for a first time user.  SSH1, SSH2 and OpenSSH all have different, but very similar configuration file locations and names.  Having multiple types of software installed on a single machine, while possible, is not recommended to reduce the inevitable confusion that results. 

 

File Permissions for User Configuration Files:

 

File permissions have caused so much hair pullying that I'm putting it here right at the top to ensure it's not missed.  All implementations of SSH have the option to require strict access permissions regarding user configuration files.  This requirement is on by default and is set with the following line in the sshd config file /etc/ssh/ssh_config:

StrictModes yes

 

It is a good idea to leave the default setting as it provides considerable enhanced security.  However, you must have your file permissions set as described below for features such as Public Key Authorization to work.  IF YOUR PERMISIONS ARE NOT CORRECT, PUBLIC KEY AUTHENTICATION FAIL AND WILL FALLBACK TO PASSWORD AUTHENTICATION WITH NO HELPFUL INDICATION WHY.

 

The following server configuration files and/or directories must be owned by the account owner or by root and GROUP and WORLD write permission must be disabled.

 

$HOME

$HOME/.rhosts

$HOME/.shosts

$HOME/.ssh

$HOME/.ssh.authorized-keys

$HOME/.ssh/authorized-keys2    #Openssh specific for ssh2 protocol.

 

HINT:  On confuguring a new machine through an ssh session I once set permissions for the .ssh directory in my home directory  on the ssh server as specified above.  Afterward, I found that I no longer had access to the .ssh directory.  The problem was that my GROUPID on the server did not match that of the client computer.

 

Generating Key Pairs:

 

Once ssh client software is installed on a user's machine the user, logged in as him/herself, may run ssh-keygen to create a public and private key pair.  These keys are, by default, located in the users $HOME/.ssh directory. Note the following results with varying ssh software:

 

OpenSSH:

# Create an OpenSSH, RSA-type key pair called identity and identity.pubfor the ssh1 protocol.

>ssh-keygen

# Create an OpenSSH, RSA-type key pair called id_rsa and id_rsa.pub for the ssh2 protocol..

>ssh-keygen -t rsa

# Create an OpenSSH, DSA-type key pair called id_dsa and id_dsa.pub for the ssh2 protocol..

>ssh-keygen -t dsa

# Reformat an OpenSSH key such that it can be read by an SSH2 client or server.  This is required when an OpenSSH client is configured for public key authentication on an SSH2 server.

>ssh-keygen -e <publickeyfile>  >  <newSSH2formattedpublickeyfilename>

 

SSH2:

Unlike OpenSSH, SSH2 client software stores keys and configuration files in $HOME/.ssh2.  Also unlike OpenSSH, SSH2 client software requires an implicit list of the keys used for identification and authorization ($HOME/.ssh2/identification and $HOME/.ssh2/authroization respectfully).  For example, the contents of $HOME/.ssh2/identification might look like the following:

IdKey id.dsa

IdKey my_second_private_key

Similarly, $HOME/.ssh2/authroization might contain:

Key id.dsa.pub

Key my_second_public_key

 

 

Not specifying a pass phrase when prompted will result in your private key being stored in an unencrypted format on your local computer.  In general you should specify a pass phrase to prevent unfrettered access to other computers should your client computer be compromised.  Note however that scripts written envoking ssh commands providing a secure version of rsh type commands, require an unencrypted password.  For client computers operating in this kind of scenario do not enter a pass phrase.

 

 

Authentication:

 

Ssh authentication comes in two forms – authentication of the server to the client and authentication of the client to the server. 

 

Authentication of the Server to the Client:

When a client attempts a connection to a server, the server sends to the client, among other things, it's host public key, it's server key (different from the host key), and a list of encryption, compression, and authentication methods the server supports.  The client compares the server's host key to the user's database of known hosts.  This file can be found in $HOME/.ssh/known_hosts (or known_hosts2).  If  the server's host key is not found, you will be told that the server is not a “known” host and asked if you would like to add this server to your list of known hosts.  If you say yes, the server will send you its host key which will be added to your “known_hosts” file.  

 

In general saying “yes” is not the best thing to do.  The key that is sent is not encrypted.  Anyone listening will be able to capture the server's host key which might be sufficient for a knowledgeable person to impersonate that server.  A more secure method would be for the system administrator to gingerly distribute, in some secure way, the host key for the server which you could then copy into your known_hosts file.  All that said, the hassle of securely distributing a server's public key must be weighed with the relative difficulty of pulling off a “man-in-the-middle” attack.  In general, unless you're working on classified or mission-critical things, allowing transfer of the server's host key is probably ok. 

 

In the ssh connection process, the client and server now negotiate and build a secure encrypted link.  Refer to your handy ssh guide for the gory details.  The next step, authentication of the client to the server, passes over this encrypted link.

 

Authentication of the Client to the Server:

There are several different ways the client (and user) can authenticate with the server.  Discussed here are Password Authentication, and Public-key Authentication.

 

1. Password Authentication:

Password Authentication, is simply passing one's server password over an encrypted link.  Ssh created the encrypted link and the user passes the password of his or her account on the server, which uses it's own standard authenticatoin mechanism (often PAM on Unix systems).  This is the default method of  client authentication and this is what is happening when ssh next prompts you for your server password. 

 

2. Public-key Authentication:

Public-key Authentication differs from Password Authentication in that, rather than passing to the server the user's server account password, during initial setup, the user's public key is placed in the user's authorized_keys file on the server which serves to authenticate the user.  Here's how it works: 

 

In initial setup, the user places a copy of his or her public key on the server by copying the text from within his or her $HOME/.ssh/id_rsa.pub file on the client computer to her or her $Home/.ssh/authorized_keys file on the server.  Ensure the authorized_keys file has the correct ownership and permissions as specifed above.

 

During authentication the ssh client sends to the ssh daemon on the server a unique index of the user's key.  The server uses the index to look up the user's key in the user's authroized_keys file described above.  If a key is found, the server generates a challenge in the form of a random string encrypted  with the users public key, and sends it back to the client.  To answer the challenge, the client must unencrypt the challenge with the user's private key.  However the key itself is encrypted with the user's pass phrase, therefore the user is prompted to enter it.  Once the pass phrase is entered the client unencrypts the private key, which then unencryptes the challenge string.  The challenge string is combined with a session id and the result is hashed by the client who finally sends the result back to the server.  The server does the same calculation with it's own copy of the encrypted challenge string and the session id and if the results match the user is authenticated.  Crazy eh?

 

Ssh agents:

 

In the discussion described above regarding public-key authentication, the user was prompted to enter his or her private key pass phrase which was used to unencrypt their private key which was in turn used to unencrypt the challenge sent by the server.  The would be required for every ssh connection and might be considered a hassle.  Ssh-agents allow the user to enter his or her pass phrase just a single time. 

 

An ssh agent is a small piece of software into which a user's private keys are loaded.  With each private key the user authenticates themselves with the key's corresponding passphrase.  Once initially configured, for subsequent ssh connections, the agent automatically doles out unencrypted forms of the user's private key for authentication purposes in an automated way.

 

If a key pair is generated without a pass phrase, while not the most secure scenario, ssh agents can be used to automate the connection and authentication processes for scripts that might run in cron jobs or other such automated functions.

 

Ssh agents are quirky in that they are applicable only to the shell in which they are run and child shells.  When an ssh agent is created, it requires that two environmental variables be set, which are in fact returned (but not set) by the ssh-agent software when it is initially invoked.  To automatically set these variables, these ssh-agent software can be invoked with the following:

eval `ssh-agent`  #note the backward single quotes

You can see that the environmental variables are set with the following:

echo $SSH_AUTH_SOCK

echo $SSH_AGENT_PID

Killing the ssh-agent process does not also unset these environmental variables, however it is important that they are unset for proper operation.  To ensure these variables are unset, and not have to do it manually, kill ssh-agents with the following:

eval `ssh-agent -k`

Once an ssh-agent is running, the user need only add ssh keys to it with the ssh-add command.  If none are specified the command wiill add the user's default ssh key. 

Ssh-add

 

Xforwarding:

 

Xforwarding is the process by which a remote computer displays Xwindows on the client computer allowing client users the ability to interact with the server computer via a windows interface.  Without getting into the details, Xforwarding requires that the client computer be configured to external connections to its own Xwindows server, and that the server computer is configured to send all Xwindows displays to the client computer.  The first requirment is met by the user specifying, for his client computer, that external Xwindows hosts may connect using the xhosts command. 

Xhosts +           #Allows connections from any external compluter

 The second requirement is met by the user logging into the server and setting the DISPLAY environmental variable such that Xwindows displays point to his client computer, for example:

export DISPLAY=129.236.95.154:0.0

Now that the two requirements are met, the user can invoke any X based application from the command line of their logged in shell and the X windows will display on their local client computer. 

 

Ssh allows for Xforwarding over an encrypted link.  For ssh server software to provide encryption for Xforwarding, the software must be explicitly compiled to support Xforwarding.  Luckily for us Openssh includes this capacity by default with the standard rpm installation.  There's plenty of further instruciton regarding this in the O'Reilly ssh manual.

 

Xforwarding is off by default in Openssh.  To enable it generally add the following line to the server's /etc/ssh/ssh_config file:

X11Forwarding yes

 Disable it on a per user basis by adding the following to the user's $HOME/.ssh/authorized_keys file at the beginning of the key for which it applies:

no-X11-forwarding   .....rest of key.....

Finally, on the user's client computer, the following line must be added to the user's $HOME/.ssh/config file:

X11Forwarding yes

 

Once configured, any subsequent ssh sesssions will result in the ssh server software automatically resetting the user's DISPLAY environmental variable to a value such that any Xwindows sessions will be forwarded over the encrypted link.  Note that the client must still configure the client computer to allow xhost connections as with unencrypted xforwarding.

 

Compression:

 

Openssh allows for the dynamic compresion of data before it is encrypted, sent over a link where it is then unencrypted and uncompressed on the other side.  Behind the scenes, the gzip compresion utility is used and the user may specify one of 9 different compression levels.  Higher compression levels (near 9) result in a smaller number of bytes sent, but may increase the overall time required to send the information.  Consider that for fast connections or connections in which the user is charged by the minute, compression will be the limiting factor and should be set to lower numbers.  Conversely for connections that are slow or are charged by the byte transferred, data transfer itself will be the limiting factor and compression values should be set ot higher numbers.  There's a nice table of values for reference on page 281 of the O'Reilly manual.  If unspecified, the default compression leveel is 6.

 

Compression in Openssh is off by default.  It may be invoked on a per-session basis with the -C flag as below:

ssh -C grampus.ewing.ldeo.columbia.edu

Or turn on compresssion for all sessions by addding the following line to the ssh sever's configuration file /etc/ssh/ssh_config:

Compression yes

Specify compresssion level with:

CompressionLevel 2

 

Port Forwarding:

 

Port Forwarding is a great trick to allow standard tcp based services to be tunnelled over an encrypted ssh link.  Local forwarding is used when the client appplication connection is initiated from the ssh client computer, while Remote forwarding is used when the client application connection is initiated from the ssh server computer. 

 

Port Forwarding is enabled by default in Openssh, however it may be globally diabled on the ssh server by specifying the following in the /etc/ssh/ssh_config file:

AllowTCPForwarding no 

 

As an example, lets look at port forwarding for secure imap connections to an imap mail server that is also an ssh server.  Since the imap client software initiates the connection to the imap server we use local port fowarding.  The general syntax to create the ssh tunnel for an IMAP client looks like this:

ssh -L2001:localhost:143 targetsshserver.edu

This lines says “Listen for connections to my local machine (implied) on port 2001, create a tunnel from port 2001 on my local machine to the sshd target server using the ssh server's standard ssh port – 22 (implied), then map this connection to port 143 (the IMAP server port) on the target sshd server, in this case also the imap server  (specified by 'localhost').”  This is confusing, but note that the localhost entry in the line above refers not to the client computer, but to the imap server (and in this case the ssh server as they are one and the same).  One could replace 'localhost' with the ip address of the target ssh server or it's domain name, however for reasons discussed in the O'Reilly manual localhost is recommended.  Alternatively, it is possible that the imap server could be located on another computer altogether.  In this case 'localhost' would be replaced with the domain name of the imap server computer and the result would be a secure connection between the imap client computer, and the ssh server with a non-secure connection on to the imap server.  This scenario is provided in the O'Reilly manual as ideal for remote login to an imap server located on a secure network through a firewall/bastion host.

 

With the line above executed, an ssh session is created between your local computer and the ssh server, and a shell prompt is returned from the ssh server.  For the purposes of this IMAP tunnel, this shell is not really necessary, however to terminate it would also terminate the ssh session and your tunnel.  While other versions of ssh have a built in way to push this shell into the background, Openssh only provides for pushing connections into the background if a remote command is executed with the connection.  So one needs a command that does nothing and takes a long time (at least the duration of the required imap connection) to execute.  The following will push the ssh session into the background sucessfully:

ssh -f L2001:localhost:143 targetsshserver.edu sleep 1000000

 

Now that the tunnel is created and your client software is listening for connections on your local computer's port 2001, you need only to configure your imap client software to look to your local computer port 2001 for it's imap connections.  Place localhost:2001 in the 'imap server' enrty in your imap client software and you're all set.

 

Note: An incompatibility exists between OpenSSH client software versions <3.0 and SSH2 server software such that connections over forwarded ports fail.  If you find this to be the case upgrade your OpenSSH client software – it's has a security hole and should be upgraded anyway.

 

 

 

In a nutshell:

Basic Configuration:

1.Install Openshh client software, ssh-keygen, ssh-add, ssh-askpass and ssh-server (on the server)

2.Generate a public/private key pair for your user account and ssh version.

ssh-keygen -r  #for ssh2 with rsa key

3.Copy the server's host key to your $HOME/.ssh/known_hosts file.  (Done automatically the first time you log in, but by passing it over the network in a non-secure way.  Best to do via disk.)

4.For Public-key Authentication, copy your public key (in $HOME/.ssh/id_rsa.pub or id_dsa.pub) to

the server.  Put it in your $HOME/.ssh/authorized_keys file.

Agents:

5.Add an ssh-agent for a shell

eval `ssh-agent`  #note backward single quote

or delete an agents

eval `ssh-agent -k`

6.Add your private key to that agent.

ssh-add

or add another specific key to that agent:

ssh-add id_rsa_key2

or remove a key from the agent

ssh-add -d id_rsa_key2

or remove all the keys from the agent

ssh-add -D

7.Modify your .profile (.bash_profile) and .bashrc files to automatically add an agent at login and have it effective for all shells, xwindows, etc. spawned from that login.

.bash_profile:

#Create a default ssh agent if ther's not an agent running already.

#This should be the last line in your .profile (.bash_profile) unless .bashrc

#is invoked explicitly, in which case this line should proceed it.

test -z “$SSH_AUTH_SOCK” && exec ssh-agent $SHELL

 

 

.bashrc

# SSH CONFIG

# The following checks to see if the shell is attached to a tty.

# If so, and if the currently running ssh-agent has no identities loaded

# (see .bash_profile), it loads my default private key.

 

if /usr/bin/tty > /dev/null

then

 ssh-add -l | grep 'no identities' > /dev/null

 if [ $? -eq 0 ]

 then

   ssh-add      # Load default identity

 fi

fi

 

8.Create a key pair with no pass phrase to allow spawned processes or cron jobs to ability to run in an automatic fashion without requiring a pass phrase from a user.

ssh-keygen -N “” -r id_rsa_2

Copy the public version (id_rsa_2.pub) to the server's authorized_keys file (see 4 above).

Create an agent in the cron job or process

...

exec ssh-agent $SHELL

....

Add the new key

ssh-add id_rsa_2

 

9.Configure secure email via ssh tunnel to an IMAP server

# Create an ssh tunnel between a random port on the local host and the IMAP port on the server.  This could be made an alias to facilitate easy connections,but should not typically be part of a login script  as it will create a persistant tunnel to the server.  WILL MANY MULTIPLE SSH TUNNELS TO AN IMAP SERVER CAUSE PROBLEMS? HOW TO CONNECT AND NOT SPAWN SHELL.

ssh -L2001:localhost:143 imapserverFQDN

#Configure email clients to use IMAP server 'localhost 2001'

 

10.Configure X11 Forwarding (tunneling of the X windows display of applications running on a remote server)

 

Server: 

Xforwarding is off by default in Openssh.  To enable it generally add the following line to the server's /etc/ssh/ssh_config file:

X11Forwarding yes

 Disable it on a per user basis by adding the following to the user's $HOME/.ssh/authorized_keys file at the beginning of the key for which it applies:

no-X11-forwarding   .....rest of key.....

 

Client:

Add the following line to the user's $HOME/.ssh/config file:

X11Forwarding yes

 

To connect:

The following lines are taken from an actual connection and xterm.  This connection used private-key authentication with an ssh-agent running with the user's private key loaded.  (note the user was not prompted for his account password, nor his private key passphrase).  The X11Forwarding configuration above caused the server software to automatically set the DISPLAY environmental variable to one reserved for X11 tunneling via ssh (the echo line is included only to demonstrate this fact). The ensuring xterm passes through the tunnel.

 

% ssh grampus.ewing.ldeo.columbia.edu

Last login: Mon Feb 11 04:31:11 2002 from ewing-dhcp-154

Sun Microsystems Inc.   SunOS 5.8       Generic February 2000

 

---------------------------------------------------------------

 

Try the ewing web page: http://www/

 

---------------------------------------------------------------

 

% echo $DISPLAY

grampus:12.0

% xterm