oreilly.com O'Reilly Network Safari Bookshelf Conferences Sign In/My Account | View Cart   
Book List Learning Lab PDFs O'Reilly Gear Newsletters Press Room Jobs      O'Reilly China O'Reilly Germany O'Reilly Japan O'Reilly Taiwan  

Top Ten Secure Shell FAQs

by Richard E. Silverman
  • SSH-1: Version 1 of the SSH protocol (usually 1.5)

  • SSH-2: Version 2 of the SSH protocol

  • SSH1: The original SSH-1 implementation by Tatu Ylönen; now maintained (bug fixes only) by SSH Communications Security

  • SSH2: The "SSH Secure Shell" product family, SSH-2 implementations by SSH Communications Security

  • OpenSSH: Free software supporting both SSH-1 and SSH-2, from the OpenBSD project

Note that various filenames used in these examples might be different for your installation depending on how you invoke the programs or how the system administrator has configured SSH. These are just typical defaults.

Top Ten Secure Shell FAQs

1) I just installed OpenSSH, but password authentication is not working!

Many modern flavors of Unix use "PAM" for password authentication. PAM stands for Pluggable Authentication Modules. It is an abstract framework for performing accounting, authentication, and authorization (AAA). The idea is that programs can be written to use PAM instead of particular AAA methods. The system administrator can then customize AAA for different programs by changing the host's PAM setup. Existing services can use new AAA methods, without change, simply by reconfiguring PAM or adding a new PAM module to the system. For example, an IMAP server daemon might log its actions to /var/log/imapd.log, and authenticate clients via the Unix passwd map. If the daemon uses PAM for this, the system administrator can direct that PAM instead log its actions via syslog, and employ Kerberos for user authenticatation. The IMAP server software need not have been written with explicit support for either of these features, so long as it uses PAM.

Richard Silverman has also written dsniff and SSH: Reports of My Demise are Greatly Exaggerated on oreilly.com, in response to Kurt Seifried's The End of SSH and SSL? on securityportal.com.

If you are building OpenSSH from source, the configure script automatically turns on PAM for several operating systems, notably Red Hat Linux. But the installation process will not alter the host's PAM configuration to accommodate SSH. You must do that yourself, and until you do, password authentication will fail. There are sample PAM files for several operating systems in the contrib directory of the OpenSSH source distribution. For example: the following commands, executed as root from the top of the OpenSSH distribution tree, will work for Red Hat. They will simply copy the sample SSH/PAM configuration file to the right place. If you are knowledgeable about PAM, you may want to examine this configuration file and customize it yourself.

  # cp contrib/redhat/sshd.pam /etc/pam.d/sshd
  # chown root.root /etc/pam.d/sshd
  # chmod 644 /etc/pam.d/sshd

A couple of notes:

  • You do not have to restart the SSH server (sshd) after installing the SSH PAM file.

  • You might install OpenSSH from a precompiled package, such as an RPM (Red Hat Package Manager) file, rather than compiling and installing from source. Some of these packages floating around the Net do install a PAM file for you as well as SysV-style "init" scripts for controlling sshd and starting it at boot time.

There is sometimes a separate, unrelated problem using password authentication under Slackware Linux. If you have trouble, try building OpenSSH with these options: "LIBS=-lcrypt ./configure --md5-passwords".

2) I use particular combinations of SSH command-line options all the time when connecting to various server hosts. Is there a way to automate this, other than using shell-command aliases?

Yes. Use labeled sections in the SSH client-configuration file. For instance:

# ~/.ssh/config (SSH1 or OpenSSH)
Host foo.bar.com
  User slade
  PasswordAuthentication no
  LocalForward 2143 localhost:143  

# ~/.ssh2/ssh2_config (SSH2)
  User slade
  AllowedAuthentications publickey
  LocalForward "2143:localhost:143"

With this bit of configuration, if you give the command ssh foo.bar.com, SSH will behave as if you had instead typed:

ssh -l slade 
   -L 2143:localhost:143 
   -o PasswordAuthentication=no 

Note that the labeled section is only used if the label matches the hostname you give to SSH on the command line, verbatim. So if your DNS (Domain Name System) search list includes bar.com and you connect by just typing in ssh foo, the special configuration above will not be used.

This technique is useful in other ways as well. You can give a name to a host that doesn't have one:

Host bar

or use different nicknames for the same host, with different options:

Host foome
  HostName foo.bigcorp.com
  User me

Host backups
  HostName foo.bigcorp.com
  User root
  Compression yes
  CompressionLevel 8

This is a useful abstraction mechanism. Scripts or programs that use SSH can use these nicknames instead of actual hostnames. If the actual hosts or the SSH options you want for these connections change, you can just change the SSH client-configuration file, rather than hunt down all the relevant SSH commands and change them.

3) When I try to use scp, I get "scp: command not found" from the remote side.

This happens with the SSH1 and the OpenSSH scp, as opposed to scp2 in SSH2, which uses the sftp-server subsystem. The problem is that underneath, scp actually runs SSH in a subprocess, starting a remote copy of scp to talk to in server mode. The command it uses is just "scp," which means that scp must be in the command search path on the remote side. SSH installations usually ensure that the default remote PATH setting contains the appropriate directory, but since sshd uses the remote account's shell to run programs, any PATH setting made in your remote user or system shell startup files can override this (e.g. ~/.bashrc, /etc/profile, etc.). Make sure that your PATH setting on the remote side contains the directory where the scp executable is installed.

4) X forwarding isn't working!

Things to check:

  • The X forwarding feature must be turned on in both the client and the server (ForwardX11 yes or, with GUI SSH clients, check the appropriate box in the dialog box).

  • If possible, run the session in verbose mode (ssh -v ...) and make sure the client is requesting X forwarding, and check for X-related errors such as the server being unable to find the xauth program.

  • On the remote side, check the DISPLAY environment variable (echo $DISPLAY). It should contain something like server-host:10. sshd sets this to point at its proxy X display. If the server is OpenSSH, also check the XAUTHORITY environment variable; it should contain something like /tmp/ssh-rYY10594/cookies. If either of these variables is not set, or contains the wrong value, X forwarding will not work. Check whether your user or system shell startup files are resetting these variables. It's a common problem.

  • Check that you have a key for the proxy display, using xauth list on the remote side.

5) How do I get public-key authentication working?

Here is a checklist:

  • Make sure public-key authentication is turned on for both the client and server side. It is usually on by default, but for completeness, the following configuration statements will enable it:
      # SSH1, OpenSSH/1
      RSAAuthentication yes
      # OpenSSH/2
      DSAAuthentication yes
      # SSH2
      AllowedAuthentications publickey
  • Generate a key pair using ssh-keygen (or whatever facility your GUI client provides for this).

  • Place your public key in the authorization of the remote account.

    • SSH1, OpenSSH/1: Insert contents of client:~/.ssh/identity.pub in server:~/.ssh/authorized_keys.

    • OpenSSH/2: Insert contents of client:~/.ssh/id_dsa.pub in server:~/.ssh/authorized_keys2 (note the trailing "2").

    • SSH2:

      • Copy ~/.ssh2/id_dsa_1024_a.pub to a file in server:~/.ssh2,, say named foo.pub

      • Insert the line IdKey id_dsa_1024_a in client:~/.ssh2/identification.

      • Insert the line Key foo.pub in server:~/.ssh2/authorization.

  • We assume here that you're using the same SSH implementation on both sides. If not, you may need to convert key formats. The OpenSSH ssh-keygen includes the -y, -x, and -X options for this purpose. This is generally only necessary for DSA keys; RSA keys tend to use the same format everywhere.

    Watch out for differing end-of-line conventions! For example, suppose you generate a DSA key using OpenSSH under Windows/Cygwin, convert the public key to SSH2 format using ssh-keygen -x, and copy the public-key file over to a Unix SSH2 server host for use. Depending on how you do the copying, that file may have carriage-return/linefeed sequences delimiting lines, which is the DOS/Windows convention. If so, the key will mysteriously fail to work with SSH2, which expects the Unix end-of-line convention: a single linefeed.

  • Set appropriate permissions on important files in the remote account. The SSH will refuse public-key authentication if they are too permissive. In particular, the target user's home and ~/.ssh(2) directories as well as the authorization file, must not be group- or world-writable. For example, for SSH1 we suggest:

        chmod 755 ~ ~/.ssh
        chmod 644 ~/.ssh/authorized_keys
        chmod 400 {any private key files}

    You can of course make them more restrictive if you wish. However, you may have trouble if your home directory on the SSH server host is accessed from a different computer via NFS (Network File System), and the authorized_keys file is not world-readable.

6) I'm using SSH2 from SSH Communications Security on one side, with another flavor of SSH software on the other. The connection always dies after an hour.

Beginning with version 2.3.0, SSH2 implements session rekeying. This is a feature of the SSH-2 protocol, which allows either side to force another run of the key-exchange phase, changing the encryption and integrity keys for the session. The idea is to do this periodically: either every so many seconds or after so many bytes of data have passed over the connection. The feature is controlled by the SSH2 configuration parameter RekeyIntervalSeconds, whose default value is 3600 (one hour, on both the client and server sides).

The problem is that currently many other SSH-2 implementations do not support session rekeying, and they die in various ways when they receive the rekeying message from SSH2. Since rekeying is not optional (the receiving side can't refuse to do it), the only way to avoid this is to turn off rekeying in SSH2: Set RekeyIntervalSeconds to 0 (in /etc/ssh2/sshd2_config for the server, or ~/.ssh2/ssh2_config for the client).

SSH-2.4.0 actually contains code to recognize when it's speaking to an OpenSSH partner, and it disables session rekeying in order to play nice with OpenSSH.

7) How do I use sftp from a script? Shell "here-documents" don't seem to work.

A shell-script "here-document" looks like this:

  echo "OK, starting now..."
  sftp remotehost <<EOT
  cd pub
  get foo.tar.gz
  # script goes on to do some other things...

This won't work because sftp expects to read its command input from a terminal, but there's no terminal in sight. Now, sftp has the -b option so it can read its commands from a file instead--but it's nice to keep it all in one place rather than having multiple little files to keep track of. That's the point of a here-document. But if your operating system has a way for processes to refer to their standard input through the filesystem, then you can use a trick like this: sftp -b /dev/stdin (that's for Linux, OpenBSD, etc.; under Solaris, the device file would instead be: /dev/fd/0).

Note that there is a subtle problem with this technique under Linux when using csh and derived shells. To avoid the problem, use sh or bash instead. Read this FAQ for more details.

Aside from this, you must also use an authentication method that does not require user input. You will not be able to feed a password to sftp via the "here-document." SSH will correctly still try to prompt a terminal for that. You could get around that by using Expect, or something else that provides a pseudo-terminal for the subprocess's standard input, but why go to all that trouble to do something terribly insecure anyway? Embedding the password inside the script is not a good idea. If you want to automate an unattended process with SSH, there are better ways to do it. For example, read this FAQ on how to arrange to log in without typing a password or passphrase.

8) I started using an SSH rc file (/etc/sshrc or ~/.ssh/rc). It works, but now X forwarding is broken!

If sshd executes an rc file, it does not run xauth to add the proxy-display key. Instead, it feeds the key to the rc program on its standard input, leaving the program free to deal with the key in a custom fashion, if needed. A simple solution is to use code like this in the rc file (as suggested in the OpenSSH man page for sshd):

 if read proto cookie; 
 then echo "add $DISPLAY $proto $cookie" | xauth -q -; 

9) I'm connecting to a host using a DNS name, with multiple A records, for load sharing. For example, shell.isp.com might return any one of three addresses for the hosts login1, login2, and login3. How do I avoid the constant "host key has changed" warnings?

In SSH1/OpenSSH, the known-hosts list actually associates a set of keys with each server host, meaning that server authentication succeeds if the server proves it holds any of the keys associated with user-specified host name. So you can do this in the known-hosts files (/etc/ssh_known_hosts or ~/.ssh/known_hosts):

login1.isp.com,shell.isp.com 1024 33 1154384130451572942232...
login2.isp.com,shell.isp.com 1024 37 1108041442656325336292...
login3.isp.com,shell.isp.com 1024 33 6656072592185413312026...

This associates the keys of all three login hosts with the name shell.isp.com, allowing any one of them to be a valid host key when connecting to that name.

Note: The scheme used by SSH2 to store host keys unfortunately does not allow this flexibility.

10) I'm using X forwarding with the OpenSSH server. It works for most programs--but not with linuxconf!

linuxconf seems to sanitize its environment before running subprocesses. When it calls /bin/remadmin, the XAUTHORITY variable is no longer set, so the X-based front-end that remadmin starts doesn't find the proxy xauth key.

A quick solution is just cp $XAUTHORITY ~/.Xauthority before starting linuxconf. Beware, though, that if your home directory is not actually on the server host, this may transmit your xauth key in cleartext over the network.

The terms "SSH" and "Secure Shell" are trademarks of SSH Communications Security, Inc.

Sponsored by:

O'Reilly Home | Privacy Policy

© 2007 O'Reilly Media, Inc.
Website: | Customer Service: | Book issues:

All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.