O'Reilly logo

Building Secure Servers with Linux by Michael D. Bauer

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Secure Shell Background and Basic Use

A few years ago, Finnish programmer Tatu Ylönen created a terrifically useful application called the Secure Shell, or SSH. SSH is a suite of tools that roughly correspond to Sun’s rsh, rcp, and rlogin commands, but with one very important difference: paranoia. SSH lets you do everything rsh, rcp, and rlogin do, using your choice of libertarian-grade encryption and authentication methods.

But there was a catch: SSH Version 1 relied heavily on RSA — an excellent but, until very recently, encumbered (patented) technology whose owners required that any application that used it be licensed unless used in noncommercial settings. (Even in noncommercial use, SSH’s legality was murky, especially in the U.S.). But wait, RSA’s U.S. patents expired in September 2000 — problem solved, right?

Almost: Tatu’s got to earn a living, so by the time RSA became less encumbered, SSH itself had become more so as his company, SSH Communications Security, tightened the licensing reins. In fact, beginning with SSH Version 2.0, unlicensed/free commercial use (irrespective of RSA issues) was no longer permitted. All this despite Tatu’s sincere desire that SSH become an Internet standard, one of the requirements of which is that at least one free implementation be available.

SSH Communications Security eventually reloosened the licensing reins with SSH v.2.3, making it free even for commercial use if run on Linux, FreeBSD, NetBSD, and OpenBSD, and returning the right to free use to all noncommercial users regardless of the operating system.

But by this time, Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt, Dug Song, and others on the OpenBSD team had taken matters into their own hands. OpenBSD, of course, is the secure-by-default offshoot of NetBSD, which, in turn, is a free version of BSD Unix. Theo and our open source brethren in the OpenBSD project wanted to include SSH in OpenBSD 2.6, but were wary of SSH’s various encumbrances. When they learned that the Swedish programmer Björn Grönvall had released an improved version of SSH 1.2.12 called “OSSH” (1.2.12 was, at the time, the last completely-free-except-for-RSA version of Ylönen’s SSH), the OpenBSD guys rapidly got to work on updating and adapting OSSH for a larger audience. Their version, OpenSSH, has been part of OpenBSD ever since and is now portable to most Unices.

OpenSSH built on Grönvall’s OSSH work, adding support for later versions of the SSH protocol and modularizing its cryptographic mechanisms in such a way that it’s possible to compile OpenSSH without any patented algorithms whatsoever (i.e., without support for SSH v.1 protocols, which depend on RSA). The other innovation the OpenBSD team brought was the forking of the OpenSSH code base into a “clean” version, which is kept as simple and platform independent as possible, and a “portable” version, which can be compiled for a variety of Unices besides OpenBSD.

This last innovation is of particular note to Linux users: the clean version is kept that way to maximize the code’s “auditability,” ensuring that it’s fundamentally stable and secure. Only after this code is blessed by Theo and Markus (righteous paranoiacs) are portability enhancements added. Thus, we benefit from a software package that is both extremely secure and 100% Linux compatible.

By the way, less than two months passed between the time the OpenBSD crew discovered OSSH and the time they released OpenSSH 1.2.2; in addition, only 6.5 months after that, they released the fully portable and SSH v.2-compatible OpenSSH 2.0. Even considering that they were building on Ylönen’s and Grönvall’s work, this is a remarkable achievement, especially considering the quality of the end product and the fact that nobody gets paid for it!

So that’s the story of SSH and OpenSSH so far. I hope you agree that it’s a pretty compelling one, as notable as is OpenSSH itself. Indeed, OpenSSH has very rapidly become the preferred version of SSH for open source Unices: as of this writing, the latest releases of Red Hat, Debian, and SuSE Linux all ship with binary packages of OpenSSH.


“SSH v.1.x” and “SSH Protocol v.1” refer to SSH’s software release and protocol, respectively, and are not really synonymous. But since the package and protocol major version numbers roughly correspond, from here on in I’ll use “SSH v.1x” to refer to RSA-based versions of SSH/OpenSSH and “SSH v.2x” to refer to versions that support both RSA and DSA.

How SSH Works

Secure Shell works very similarly to Secure Sockets Layer web transactions (it’s no coincidence that the cryptographical functions used by OpenSSH are provided by OpenSSL, a free version of Netscape’s Secure Sockets Layer source-code libraries). Both can set up encrypted channels using generic " host keys” or with published credentials ( digital certificates) that can be verified by a trusted certificate authority (such as VeriSign). Public-key cryptography is discussed further later in this chapter, but here’s a summary of how OpenSSH builds secure connections.

First, the client and the server exchange (public) host keys. If the client machine has never encountered a given public key before, both SSH and most web browsers ask the user whether to accept the untrusted key. Next, they use these public keys to negotiate a session key, which is used to encrypt all subsequent session data via a block cipher such as Triple-DES (3DES), blowfish, or IDEA.


As its name implies, a session key is created specifically for a given session and is not used again after that session closes. Host and user keys, however, are static. You might wonder, why not just use host or user keys to encrypt everything? Because the algorithms used in public-key cryptography are slow and CPU-intensive. Why not use the same session key for multiple sessions? Because unique session keys require more work for an attacker who attempts to crack multiple sessions.

As with typical SSL connections, this initial round of key exchanging and session-key negotiation is completely transparent to the end user. Only after the encrypted session is successfully set up is the end user prompted for logon credentials.

By default, the server attempts to authenticate the client using RSA or DSA certificates (key pairs). If the client (user) has a certificate recognized by the server, the user is prompted by their client software for the certificate’s private-key passphrase; if entered successfully, the certificate is used by the SSH client and server to complete a challenge-response authentication, which proves to the server that the client possesses the private key that corresponds to a public key registered with the server. At no point is the private key itself, its passphrase, or any other secret data sent over the network.

Also by default, if RSA/DSA authentication fails or if there is no client certificate to begin with, the user is prompted by the remote server for a standard Unix username/password combination that is valid for the remote system. Remember, an encrypted session has already been established between client and server, so this username/password combination, while easier to subvert or guess than certificate-based authentication, is at least encrypted prior to being transmitted to the server.


If enabled, rhosts-style host-IP-based authentication with or without RSA keys may be used; OpenSSH also supports authentication using KerberosIV and S/KEY.

Finally, after successful authentication, the session proper begins: a remote shell, a secure file transfer, or a remote command is begun over the encrypted tunnel.

As mentioned earlier, SSH is actually a suite of tools:


The daemon that acts as a server to all other SSH commands


The primary end-user tool; used for remote shell, remote command, and port-forwarding sessions


A tool for automated file transfers


A tool for interactive file transfers


Generates private-public key pairs for use in RSA and DSA authentication (including host keys)


A daemon used to automate a client’s RSA/DSA authentications


Loads private keys into a ssh-agent process


Provides an X Windows interface for ssh-add

Of these tools, most users concern themselves only with ssh, since " encrypted Telnet” is the simplest use of SSH. scp, sftp, ssh-agent, and ssh-add, however, along with the strong authentication and TCP port-forwarding capabilities of ssh itself, make SSH considerably more flexible than that. Since we’re paranoid and want to encrypt as much of the stuff we fling over networks as possible, we leverage this flexibility as fully as we can.

Getting and Installing OpenSSH

The URL for OpenSSH’s web site is http://www.openssh.com. This is the place to go for the latest version of OpenSSH, both in source-code and RPM forms, and also for OpenSSL, which is required by OpenSSH. Also required is zlib , available at ftp://ftp.freesoftware.com/pub/infozip/zlib.

You may or may not get by with RPM packages, depending mainly on whether the RPMs you wish to install were created for your distribution (Mandrake, Red Hat, SuSE, and a number of other distributions can use RPMs, but not always interchangeably). If your distribution doesn’t provide its own OpenSSH RPMs, even in a “contrib.” (end-user contributed) directory, you’re best off compiling OpenSSH from source.

To Linux old timers, “rolling your own” software installations is no big deal; but if you’re not in that category, don’t despair. All three distributions use configure scripts that eliminate the need for most users to edit any Makefiles. Assuming your system has gcc and the normal assortment of system libraries and that these are reasonably up-to-date, the build process is both fast and simple.

In my own case, after installing OpenSSL 0.9.5a and zlib-1.1.3 (all version numbers, by the way, may be outdated by the time you read this!), I followed these steps to build and install OpenSSH 2.9p1:

tar -xzvf openssh-2.9p1.tar.gz
cd openssh-2.9p1
./configure --sysconfdir=/etc/ssh
make install

Note that in the third line of the previous code listing, as per instructions provided by the file INSTALL, I fed the configure script one customized option: rather than installing all configuration files in /etc, I instructed it to create and use a subdirectory, /etc/sshd. Since this version of OpenSSH supports both RSA and DSA keys and since each type of key is stored in its own authorized_keys file, it makes sense to minimize the amount of clutter SSH adds to /etc by having SSH keep its files in a subdirectory.


Be diligent in keeping up with the latest version of OpenSSH and, for that matter, all other important software on your system! Security software tends to bear enough scrutiny to be updated frequently, or at least it’s supposed to be. Over the past year or two, major revisions of OpenSSH have been released every few months.

(Lest you think this is due to sloppy programming in need of frequent fixing, I assure you that in this case, it’s actually indicative of the OpenSSH team’s paranoia, finickiness, and ongoing lust for perfection.)

If you wish to run the Secure Shell Daemon sshd (i.e., you wish to accept ssh connections from remote hosts), you’ll also need to create startup scripts and, in the case of SuSE, edit /etc/rc.config. This has also been thought of for you: the source distribution’s contrib directory contains some useful goodies.

The contrib/redhat directory contains sshd.init, which can be copied to /etc/rc.d and linked to in the appropriate runlevel directory (/etc/rc.d/rc2.d, etc.). It also contains sshd.pam, which can be installed in /etc/pam if you use Pluggable Authentication Modules (PAM), and also openssh.spec, which can be used to create your very own OpenSSH RPM package. These files are intended for use on Red Hat systems, but will probably also work on Red Hat-derived systems (Mandrake, Yellow Dog, etc.).

The contrib/suse directory also contains an openssh.spec file for creating OpenSSH RPM packages for SuSE and an rc.sshd file to install in /etc/rc.d (actually /sbin/init.d in SuSE). In addition, it contains rc.config.ssd, the contents of which must be added to /etc/rc.config for the rc.sshd script to work properly. This is achieved by simply entering the following command:

cat ./rc.config.ssd >> /etc/rc.config

Create a symbolic link in rc2.d and/or rc3.d, and your SuSE system is ready to serve up secured shells! Either reboot or type /etc/rc.d/rc.sshd start to start the daemon.

SSH Quick Start

The simplest use of ssh is to run interactive shell sessions on remote systems with Telnet. In many cases, all you need to do to achieve this is to install ssh and then, without so much as looking at a configuration file, enter the following:


You will be prompted for a password (ssh assumes you wish to use the same username on the remote system as the one you’re currently logged in with locally), and if that succeeds, you’re in! That’s no more complicated yet much more secure than Telnet.

If you need to use a different username on the remote system than you’re logged in with locally, you need to add it in front of the hostname as though it were an email address. For example, if I’m logged on to my laptop as mick and wish to ssh to kong-fu.mutantmonkeys.org as user mbauer, I’ll use the command listed in Example 4-1.

Example 4-1. Simple ssh command

                  ssh mbauer@kong-fu.mutantmonkeys.org

I keep saying ssh is more secure than Telnet, but how? Nothing after the ssh login seems different from Telnet. You may be asked whether to accept the remote server’s public key, it may in general take a little longer for the session to get started, and depending on network conditions, server load, etc., the session may seem slightly slower than Telnet; but for the most part, you won’t notice much difference.

But remember that before ssh even prompts you for a password or passphrase, it has already transparently negotiated an encrypted session with the remote server. When I do type my username and password, it will be sent over the network through this encrypted session, not in clear text as with Telnet. Furthermore, all subsequent shell-session data will be encrypted as well. I can do whatever I need to do, including su -, without worrying about eavesdroppers. And all it costs me is a little bit of latency!

Using sftp and scp for Encrypted File Transfers

With Version 2.0 of SSH, Tatu Ylönen introduced a new feature: sftp . Server-side support for sftp is built in to sshd. In other words, it’s hardcoded to invoke the sftp-server process when needed; it isn’t necessary for you to configure anything or add any startup scripts. You don’t even need to pass any flags to configure at compile time.

Note, however, that sftp may or may not be supported by hosts to which you wish to connect. It’s only been fully supported in OpenSSH since OpenSSH v. 2.9. If a host you need to transfer files to or from doesn’t support sftp, you’ll need to use scp.

Using the sftp client is just as simple as using ssh. As mentioned earlier, it very closely resembles “normal” ftp, so much so that we needn’t say more about it right now other than to look at a sample sftp session:

[mick@kolach stash]# sftp crueller
Connecting to crueller...
mick@crueller's password: 
sftp> dir
drwxr-x---   15 mick     users         1024 May 17 19:35 .
drwxr-xr-x   17 root     users         1024 May 11 20:02 ..
-rw-r--r--    1 mick     users         1126 Aug 23  1995 baklava_recipe.txt
-rw-r--r--    1 mick     users       124035 Jun 10  2000 donut_cntrfold.jpg
-rw-r--r--    1 mick     users          266 Mar 26 17:40 blintzes_faq
-rw-r--r--    1 mick     users          215 Oct 22  2000 exercise_regimen.txt
sftp> get blintzes_faq
Fetching /home/mick/blintzes_faq to blintzes_faq
sftp> put bakery_maps.pdf
Uploading bakery_maps.pdf to /home/mick
sftp> quit
[mick@kolach stash]#

The scp command, in most ways equivalent to the old rcp utility, is used to copy a file or directory from one host to another. (In fact, scp is based on rcp’s source code.) In case you’re unfamiliar with either, they’re noninteractive: each is invoked with a single command line in which you must specify the names and paths of both what you’re copying and where you want it to go.

This noninteractive quality makes scp slightly less user friendly than sftp, at least for inexperienced users: to use scp, most people need to read its manpage (or books like this!). But like most other command-line utilities, scp is far more useful in scripts than interactive tools tend to be.

The basic syntax of the scp command is:

scp [options] sourcefilestring  destfilestring

where each file string can be either a normal Unix file/path string (e.g., ./docs/hello.txt, /home/me/mydoc.txt, etc.) or a host-specific string in the following format:


For example, suppose I’m logged into the host crueller and want to transfer the file recipe to my home directory on the remote host kolach. Suppose further that I’ve got the same username on both systems. The session would look something like Example 4-2 (user input in bold).

Example 4-2. Simple scp session

crueller: > scp ./recipe  kolach:~
mick@kolach's password: *******
  recipe          100% |****************************>| 13226       00:00
crueller: >

After typing the scp command line, I was prompted for my password (my username, since I didn’t specify one, was automatically submitted using my crueller username). scp then copied the file over, showing me a handy progress bar as it went along.

Suppose I’m logged on to crueller as mick, but have the username mbauer on kolach, and I wish to write the file to kolach’s /data/recipes/pastries directory. Then my command line would look like this:

crueller: > scp ./recipe mbauer@kolach:/data/recipies/pastries/

Now let’s switch things around. Suppose I want to retrieve the file /etc/oven.conf from kolach (I’m still logged in to crueller). Then my command line looks like this:

crueller: > scp mbauer@kolach:/etc/oven.conf .

Get the picture? The important thing to remember is that the source must come before the destination.

Digging into SSH Configuration

Configuring OpenSSH isn’t at all complicated. To control the behavior of the SSH client and server, there are only two files to edit: ssh_config and sshd_config , respectively. Depending on the package you installed or the build you created, these files are either in /etc or some other place you specified using ./configure --sysconfdir (see “Getting and Installing OpenSSH,” earlier in this chapter).

ssh_config is a global configuration file for ssh sessions initiated from the local host. Its settings are overridden by command-line options and by users’ individual configuration files (named, if they exist, $HOME/.ssh/config). For example, if /etc/ssh/ssh_config contains the line:

Compression yes

but the file /home/bobo/.ssh/config contains the line:

Compression no

then whenever the user “bobo” runs ssh, compression will be disabled by default. If, on the other hand, bobo invokes ssh with the command:

ssh -o Compression=yes remote.host.net

then compression will be enabled for that session.

In other words, the order of precedence for ssh options is, in decreasing order, the ssh command-line invocation, $HOME/.ssh/config, and /etc/ssh/ssh_config.

ssh_config consists of a list of parameters, one line per parameter, in the format:

                parameter-value1(,parameter-value2, etc.)

In other words, a parameter and its first value are separated by whitespace and additional values are separated by commas. Some parameters are Boolean and can have a value of either “yes” or “no.” Others can have a list of values separated by commas. Most parameters are self-explanatory, and all are explained in the ssh(1) manpage. Table 4-1 lists a few of the most useful and important ones (italicized text indicates possible values).

Table 4-1. Important ssh_config parameters


Possible values



Yes, No (Default=Yes)

Whether to notice unexpected source IPs for known host keys. Warns user each time discrepancies are found.


3des, blowfish(Default=3des)

Which block cipher should be used for encrypting ssh v.1 sessions.


3des-cbc, blowfish-cbc, arcfour, cast128-cbc

Order in which to try block ciphers that can be used for encrypting ssh v.2 sessions.


Yes, No (Default=No)

Whether to use gzip to compress encrypted session data. Useful over limited-bandwidth connections, but otherwise only adds delay.


Yes, No (Default=No)

Whether to redirect X connections over the encrypted tunnel and to set DISPLAY variable accordingly. Very handy feature!


Yes, No (Default=Yes)

Whether to attempt (encrypted) Unix password authentication in addition to or instead of trying RSA/DSA.

There are many other options in addition to these; some of them are covered in Section 4.3 (later in this chapter). Refer to the ssh(1) manpage for a complete list.

Configuring and Running sshd, the Secure Shell Daemon

Editing ssh_config is sufficient if the hosts you connect to are administered by other people. But we haven’t yet talked about configuring your own host to accept ssh connections.

Like the ssh client, sshd’s default behavior is configured in a single file, sshd_config, that resides either in /etc or wherever else you specified in SSH’s configuration directory. As with the ssh client, settings in its configuration file are overridden by command-line arguments. Unlike ssh, however, there are no configuration files for the daemon in individual users’ home directories; ordinary users can’t dictate how the daemon behaves.

Table 4-2 lists just a few of the things that can be set in sshd_config .

Table 4-2. Some sshd_config parameters


Possible values



1-65535 (Default=22)

TCP port on which the daemon should listen. Being able to change this is handy when using Port Address Translation to allow several hosts to hide behind the same IP address.


Yes, No

Whether to accept root logins. This is best set to No; administrators should connect the server with unprivileged accounts, and then su to root.


Yes, No

Whether to allow (encrypted) username/password authentication or to insist on DSA- or RSA-key-based authentication.


Yes, No(Default=no)

Whether to allow accounts to log in whose system password is empty. Does not apply if PasswordAuthentication= no; also, does not apply to passphrase of DSA or RSA keys (i.e., null passwords on keys is okay)


Yes, No(Default=no)

Whether to allow clients to run X Windows applications over the SSH tunnel.[a]

[a] There really is nothing to be gained by leaving X11Forwarding set to No in sshd_config, since a determined user can simply use generic TCP forwarding to forward X11. The only reason it’s even in the chart is because people usually expect X11 forwarding to be allowed, and you’ll certainly get calls from your users if you have it turned off just because you forgot to change the default value of No.

There are many other parameters that can be set in sshd_config, but understanding the previous concepts is enough to get started (assuming your immediate need is to replace Telnet and ftp). See the sshd(8) manpage for a complete reference for these parameters.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required