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.
Tip
“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.
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.
Tip
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.
Tip
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:
- sshd
The daemon that acts as a server to all other SSH commands
- ssh
The primary end-user tool; used for remote shell, remote command, and port-forwarding sessions
- scp
A tool for automated file transfers
- sftp
A tool for interactive file transfers
- ssh-keygen
Generates private-public key pairs for use in RSA and DSA authentication (including host keys)
- ssh-agent
A daemon used to automate a client’s RSA/DSA authentications
- ssh-add
- ssh-askpass
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.
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 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.
Warning
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.
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:
ssh
remote.host.net
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.
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!
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:
username
@remote.host.name:path
/filename
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.
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-name
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
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.
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
Parameter |
Possible values |
Description |
---|---|---|
|
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. | |
|
Whether to accept root logins. This is best set to
| |
|
Whether to allow (encrypted) username/password authentication or to insist on DSA- or RSA-key-based authentication. | |
|
Whether to allow accounts to log in whose system password is empty.
Does not apply if
| |
|
Whether to allow clients to run X Windows applications over the SSH tunnel.[a] | |
[a] There really is nothing to be gained by
leaving |
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.
Get Building Secure Servers with Linux now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.