The 101 Uses of OpenSSH: Part I
It's story time here in the Paranoid Penguin. Don't worry—the story is a preface to the nuts-and-bolts sort of stuff you've come to expect in LJ. In fact, there are so many nuts and bolts to play with in OpenSSH that this article spills over into next month's issue!
This month we'll cover ssh's background and architecture, how to build and/or install OpenSSH, how to use ssh as an encrypted replacement for Telnet, how to set some basic ssh configuration options and how to use scp for encrypted file transfers. Next month I'll cover RSA/DSA authentication, local port-forwarding, remote-command-execution and other more advanced, and extremely powerful functions of ssh/OpenSSH.
In order to do this magnificent software justice, I'd like to begin by talking about how it got here and some of the people who brought it to us.
One of the coolest things about UNIX has been that there is not one but several different ways to administer systems from remote consoles. Sad to say, most of these methods (Telnet, rsh and X, to name a few) send everything over the network in clear text, including passwords. The combination of our reliance on the Internet with the proliferation of script kiddies and other packet-sniffing deviants has made administrative clear-text network applications obsolete.
But a few years ago Finnish über-hacker Tatu Ylonen created a mind-blowingly cool thing 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 wait—there's a catch—ssh version 1 relies heavily on RSA, an excellent, but as we say, encumbered (patented) technology that requires any application that uses it to be licensed (paid for) unless it's used in noncommercial settings (even in noncommercial use ssh's legality has always been murky, especially in the US). But wait, you say, RSA's US 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 F-Secure tightened the licensing reins. In fact, beginning with ssh version 2.0, unlicensed/free commercial use (regardless 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.
Enter Theo de Raadt and the OpenBSD team. OpenBSD, of course, is the ultra-secure offshoot of NetBSD, 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 Bjoern Groenvall had released an improved version of ssh, 1.2.12 (the last completely free-except-for-RSA version of Ylonen's ssh), the OpenBSD guys rapidly got to work on updating and adapting it for a larger audience. OpenSSH has been part of OpenBSD ever since and is now portable to most version of UNIX.
OpenSSH built on Groenvall's work (his version, called OSSH, is still available), 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 is 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 versions of UNIX besides OpenBSD.
This last innovation is of particular note to us Linux geeks: 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 (a righteous paranoiac) 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; and only six and a half months after that they released the fully-portable and ssh v.2-compatible OpenSSH 2.0. Even considering that they were building on Ylonen's and Groenvall'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 OpenSSH itself, which in all likelihood will very rapidly become the preferred version of ssh for open-source versions of UNIX.
Are you all fired up about OpenSSH and ready to install it on every UNIX system you control? Good. Let's get busy!
By the way: “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. And if you don't know the difference between RSA and DSA, suffice it to say that both do the same thing but DSA has no patent- or license-restrictions.
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). Here's how connections are built.
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 to negotiate a session key that is used to encrypt all subsequent session data via a block cipher such as Triple-DES (3DES), blowfish, or idea.
Then, the server attempts to authenticate the client using RSA or DSA certificates. If this isn't possible, the client is prompted for a standard username/password combination (optionally, “rhosts” host-IP-based authentication with or without RSA keys may be used; OpenSSH also supports KerberosIV and skey). Finally, after successful authentication the session proper begins: either a remote shell, a secure file transfer, a remote command, etc., is begun over the encrypted tunnel.
As I mentioned earlier, ssh is actually a suite of tools:
sshd—dæmon that acts as a server to all other commands
ssh—primary end-user tool: remote shell, remote command, and port-forwarding sessions
scp—tool for automated file transfers
sftp—tool for interactive file transfers—COMMERCIAL SSH ONLY
ssh-keygen—generates private-public key pairs for use in RSA and DSA authentication (including host keys)
ssh-agent—dæmon used to automate client's RSA/DSA authentications
ssh-add—loads private keys into ssh-agent process
ssh-askpass—X interface for ssh-add
Note that sftp, which is essentially an ftp client with encryption and strong authentication grafted on, is available only in F-Secure's commercial versions of ssh version 2—I only mention it here because you may come across a reference to it elsewhere and wonder why you've only got scp.
Of these tools, most users concern themselves only with ssh, since “encrypted Telnet” is the simplest use of ssh. Scp, 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 the networks as possible, we really groove on this flexibility.
The OpenSSH web site (see Resources) 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 the freesoftware.com site (see Resources).
Note that you may not be able to get by with RPM packages. When I tried to install the RPMs from OpenSSH.com on my laptop, running SuSE Linux, everything worked except sshd, which wouldn't install due to SuSE's lack of a “chkconfig” package. Your preferred flavor of Linux may or may not have the same problem (unless it has chckconfig), or it may have its own RPM of OpenSSH (for all I know, by the time you read this somebody may have published RPMs for SuSE).
If RPMs won't work, you'll need to build OpenSSH (and possibly OpenSSL and zlib) from source. To Linux old-timers, “rolling your own” software installations is old hat, 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.1.1p4:
tar -xzvf openssh-2.1.1p4.tar.gz cd openssh-2.1.1p4 ./configure --sysconfdir=/etc/ssh make make install
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, it makes sense to minimize the amount of clutter ssh adds to /etc.
For a client-only installation, this is all you need to do. Note that one or more of the version numbers cited above may already be dated by the time you read this article; be sure to check the OpenSSH and zlib web sites for the latest versions.
If you wish to run the Secure Shell Dæmon 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 Red Hat 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 “openssh.spec”, which can be used to create your very own OpenSSH RPM package. These files are, obviously, intended for use on Red Hat systems but will probably also work on Red Hat-derived systems (Mandrake, Yellow Dog, etc.).
The suse directory also contains an “openssh.spec” file for creating OpenSSH prpm 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 in order for the rc.sshd script to work properly. This is achieved by simply entering the 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 dæmon.
What if all you need are interactive shell sessions on remote systems à la Telnet? Chances are that even without so much as looking at a configuration file, you need to simply enter:
You will be prompted for a password (ssh will assume you wish to use the same user name on the remote system as the one you're currently logged in with locally), and if that succeeds, you're in! That's arguably simpler and indisputably much more secure than Telnet.
If you need to use a different user name on the remote system than the one you're logged in with locally, you need to add the flag -l followed by your remote username. 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:
ssh -l mbauer kong-fu.mutantmonkeys.org
What is this doing for me? Nothing seems much different from Telnet. I may be asked whether to accept the remote server's public key, it may take somewhat 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 I won't notice much difference.
But I will have logged in without sending my username and password over the network in clear text, and all 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 tiny bit of latency!
Configuring OpenSSH isn't complicated either. To control the behavior of the ssh client and server there are only two files to edit: ssh_config and sshd_config. 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's -sysconfdir directory.
ssh_config is a global configuration file for ssh client sessions initiated from the local host. Its settings are overridden by command-line options and by users' individual configuration files (kept, if they exist, in $HOME/.ssh/config). For example, if /etc/ssh/ssh_config contains the line:
but the file /home/bobo/.ssh/config contains the line
Compression yesthen whenever the user “bobo” initiates a ssh session, compression will be enabled by default, even though for users without this setting in their own $HOME/.ssh/config files compression will be turned off. If, on the other hand, bobo invokes ssh with the command:
ssh -o Compression=no remote.host.netthen compression will not 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:
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) man page. Table 1 shows a few of the most useful and/or important ones (italicized text indicates possible values).
There are many other options in addition to these; some of them will be covered in Part II of this article. Refer to the ssh man page for a complete list.
All of that's fine 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. As it happens, this is very simple.
As with 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 the ssh's configuration directory. And as with the ssh client, settings in its configuration file are overridden by command-line arguments. Unlike the ssh client, however, there are no configuration files for the dæmon in individual users' home directories; ordinary users can't dictate how the dæmon behaves.
Table 2 describes a few of the things that can be set in sshd_config.
There are many other parameters that can be set in sshd_config. We'll cover some of those next month, but understanding the above is enough to get started (assuming your immediate need is to replace Telnet and ftp).
We'll cover one more ssh topic before we adjourn for this month. 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 of what you're copying and where you want it to go.
This noninteractive quality makes scp a bit less user-friendly than ftp: like it or not, to use scp you need to read its man page (or articles like this) and memorize a few flags. But like most other command-line utilities, scp is far more useful in scripts than interactive tools tend to be. Using scp “on the fly”, though, is easy to learn. The basic syntax of the scp command is
scp [ options ] sourcefilestring destfilestring
where the source and destination file strings can either be a normal UNIX file/path string (e.g., "./docs/hello.txt", "/home/me/mydoc.txt", etc.) or a host-specific string in the format
email@example.com:path/filenameFor example, suppose you're logged into the host “crueller” and want to transfer the file “recipe” to your home directory on the remote host “kolach”. Suppose further that you've got the same user name on both systems. The session would look something like this (user input in bold):
crueller: > scp ./recipe kolach:~ mick@kolach's password: ******* recipe 100% |**************>| 13226 00:00 crueller: >After typing the scp command line, we were prompted for our password (our username, since we didn't specify one, was automatically submitted for us using the username we're logged on to crueller as). scp then copied the file over, showing us a handy progress bar as it went along. And that's it!
Suppose you're logged on to crueller as “mick” but have the username “mbauer” on kolach and wish to write the file to kolach's directory data/recipes/pastries. Then our command line would look like this:
crueller: > scp ./recipe mbauer@kolach:/data/recipies/pastries/
Now let's switch things around. Suppose we want to retrieve the file /etc/oven.conf from kolach (we're still logged in to crueller). Then our 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.
Although most users use ssh and scp for simple logins and file transfers, respectively, this only scratches the surface of what ssh can do. Next month we'll examine how RSA and DSA keys can be used to make ssh transactions even more secure, how “null-passphrase” keys can allow ssh commands to be included in scripts, how to cache ssh credentials in RAM to avoid unnecessary authentication prompts and how to tunnel other TCP services through an encrypted ssh connection.