From: www.itworld.com

Make SSH do more

by Jon Lasser

April 10, 2001 —

 

Because Linux is a deep operating system, we often use a miniscule portion of a tool's features. I, for one, use awk primarily to isolate columns that cut can't find, though in fact awk is a full-fledged text-processing language. There's nothing wrong with that approach -- actually it's unavoidable -- but it benefits us to delve more deeply into the advantages a single program can offer.

Presumably you have already installed SSH and are using it to securely log in to remote systems. (If you aren't, please read Jay Beale's article "Stupid, Stupid Protocols: Telnet, FTP, rsh/rcp/rlogin" to see why you should -- see Resources.) However, most people simply connect via SSH, enter their passwords, and type away. They don't realize that SSH has advanced key-management features that allow them to avoid having to retype their passwords; that its port-forwarding options can secure other, normally insecure, packages; and that they can employ little tricks in SSH that would make their lives easier.

There's great confusion at present regarding SSH and the different versions of the software available. (See Resources for more information.) I recommend using the newest version of OpenSSH, 2.5.1p2. At the very least, use OpenSSH 2.3.0p1, as earlier versions had security holes. Several details that I will discuss do not apply to older versions of OpenSSH or to other implementations of the SSH protocol.

Keys to the kingdom

One major benefit of SSH, besides the obvious advantage of cryptographically secure connections, is that it allows you to log on to a server without ever having to type your password. You do have to type a password (only once -- but we'll get to that in a minute), but it doesn't have to be the password for your account on the server, and it will be the same password for every system to which you log in. That is possible through the magic of authentication via cryptographic keys.

Normally, when you log in to a system, you authenticate by entering your password for that system. Your password goes, as it is typed, to the remote system, which authenticates it against the /etc/passwd or /etc/shadow file. By contrast, SSH uses an authentication method with public-key cryptography. (If you are unfamiliar with public-key cryptography, see the link to the PGP Manual in Resources.) Essentially, it's a challenge-response mechanism: You can authenticate against a public key on the server, so when the client connects, the server encrypts a random number with the public key. If the client possesses the private key, then it can decrypt the random number and report it back to the server. That proves to the server that the person logging in has the authorized private key. The private key is further protected when you encrypt it with a password. The password you type to authenticate via public key cryptography is the password for your private key.

That sort of authentication requires you to first generate a pair of public and private keys. The ssh-keygen command does that. Because of the different versions of the SSH protocol out there, OpenSSH 2.5 and higher can generate three different types of keys: rsa1, for compatibility with SSH version 1 clients; DSA, for connecting to SSH protocol version 2 clients using the Digital Signature Algorithm; and RSA, for connecting to SSH protocol version 2 clients using the standard RSA algorithm. You can set the type of key SSH generates with the -t option. Thus to generate your rsa1 public and private key pair, you would run ssh-keygen -t rsa1. For the three key types, the keys generated are by default stored in your .ssh directory beneath your home directory. The rsa1 keys are named identity, DSA keys are named id_dsa, and protocol version 2 RSA keys are named id_rsa. Each key has a corresponding public key with a .pub extension. You want to check the permissions on the private keys and make sure that they're not world-readable; these are secrets not intended for sharing.

LinuxWorld.com links

To allow authentication, you must make the public key available on the computer into which you would like to log in. For rsa1 keys, the name of the file into which you put the public key is $HOME/.ssh/authorized_keys. For SSH protocol version two keys (both RSA and DSA), the file is $HOME/.ssh/authorized_keys2. Each public key is a single line, so you can use scp to copy the public keys to the destination system and then, on the remote system, type cat id_dsa.pub >> .ssh/authorized_keys2. After that you can authenticate without sending any sort of password over the network. (The private key is decrypted on the client only.)

All that is very useful, but as I promised earlier, you can set your system to require authentication only once. You can do that with the SSH authentication agent, ssh-agent. The ssh-agent syntax is rather strange: because it must set some shell variables, you must use eval `ssh-agent`. The ssh-agent tries to determine the shell syntax necessary, but occasionally it fails and you need to pass it the -s option for Bourne shell derivatives such as ksh and zsh, or the -c option for C Shell derivatives.

You must execute the ssh-agent in your top-level shell for maximum usability. For a console or ssh-based session that means in your top login shell or, for X-based sessions, in your .Xclients or another startup script. In either case, you must kill the ssh-agent with ssh-agent -k prior to quitting, or lots of startup files will be left around.

The ssh-agent only manages keys; you have to tell it which keys to use. To do that, you can ssh-add private-key-file, where private-key-file is $HOME/.ssh/id_dsa or one of your other private keys. Once you type the passphrase for your key, ssh-agent remembers it and automatically handles the key requests from new SSH sessions. To handle all contingencies, I add all three of my keys at login time and forget about it until I'm ready to quit. I end up typing three passwords, and then I need not enter any more passwords for the rest of the day.

If I plan on connecting through one server to another server, I connect via SSH to that first server with the -A option, which allows the server to pass any authentication requests it gets back to the initial client. (You can make that operation the default by setting ForwardAgent yes in your ssh configuration file. The per-user configuration file is $HOME/.ssh/config, and the systemwide configuration file is probably either /etc/ssh/ssh_config or /usr/local/etc/ssh_config, depending on how you installed OpenSSH. (In either configuration file, you can set the parameters on a host-by-host basis, so that different options can apply to different target systems.)

Forwarding traffic with SSH

Not only can SSH forward your authentication requests, but it can forward your X Window System traffic as well. And SSH not only forwards the traffic, but also automatically sets X's DISPLAY variable on the remote system, thus simplifying your side of things substantially. Nobody likes messing with the DISPLAY variable, Magic Cookies, or any other part of remote X configuration. SSH can handle all of those at once. You just need to connect SSH using the -X option, or set ForwardX11 yes in the appropriate config files, and run your X application from the remote system's command prompt.

When using X, I always make sure to turn compression on with the -C option (Compression yes in the config file), as X is bandwidth-intensive, to put it politely. With compression on and a fast cipher such as blowfish (the default for recent versions of OpenSSH), Netscape is just about usable over a 10-Mb network. Without compression, it is rather painful, and I would certainly not recommend running any complex X application on less than 10 Mb.

Perhaps even more interesting is SSH's ability to forward arbitrary ports. Maybe you read mail on a server that you can also SSH into, and POP3 mail is running while secure POP3 is not. You therefore wish to forward a port on your workstation to the POP3 port on the server. Let's pick an arbitrary port, such as 2048. Configure your mail client (such as Netscape) to connect POP3 to port 2048 on localhost (that is, your workstation). Then you can run the following command: ssh -N -f -L 2048:mailserver.example.com:110 you@mailserver.example.com and you'll be able to connect securely.

What's happening here? -N tells SSH that you're not interested in running a command on the remote system, only in forwarding the connection, and -f tells SSH to go into the background once you've authenticated your connection. That way, after you've entered your passphrase (or once ssh-agent has authenticated you), you won't need to type more. The magical part is -L 2048:mailserver.example.com:110. That tells SSH to forward the local port 2048 to mailserver.example.com's port 110. (Port 110 is the standard POP3 port.) So you log in to the mail server, and then anything on local port 2048 is sent over the SSH connection to port 110 on the remote side, thus allowing you to safely retrieve your mail.

That method works very nicely for most protocols, including POP3, HTTP, and IMAP, just so long as you're able to tell the client server to use the local system and the appropriate port on your local system. For FTP, be sure to use passive FTP, because active FTP opens a second connection that will not be forwarded via the SSH port forwarding. Recent versions of OpenSSH, and Commercial SSH version 2, support SFTP, which works like FTP and uses SSH without the difficulty of port forwarding and passive mode.

Tricks and traps

Because SSH command syntax descends from the outdated and dangerous rsh syntax, several neat tricks are possible. My favorite is piping data through SSH to a program on the remote side. For example, I haven't configured printing on my laptop, as I can't be sure what device I'll want to print to. Instead, I can run cat /my/file/to/print.txt | ssh jon@my.remote.printhost lpr -Pwhich_printer, which pipes the file to the program lpr on the remote side of things. Essentially, anything after the destination host on the SSH command is passed as a command to the remote server. If disk space is tight, you can also use that trick to tar files to a storage place on a different system: tar cvf - source_directory | ssh user@remote_host 'cat > my-tar-file.tar'. The quotes are necessary to ensure that the remote system, not the local system, redirects output.

One trap associated with executing commands via SSH is that interactive programs tend to die reluctantly. That is generally because they expect a terminal to be available, and SSH does not allocate a terminal for commands that it does not believe to be interactive. For example, I keep nethack on one system and I execute it via a script that calls ssh jon@remote-system nethack. For a long time I did not understand why nethack failed to run properly, but then I discovered SSH's -t option, which forces allocation of a pseudo-TTY. Using ssh -t jon@remote-system nethack does the trick just fine.

Another trap is that dangerous configurations of the SSH client drop back to the notoriously insecure rsh program if the remote system does not have SSH installed. Your SSH client should print out an error message under those circumstances, and you would be ill-advised to ignore it. You can disable that behavior with a line reading FallBackToRsh No in your ssh configuration file.

Although this article hardly covers every facet of SSH, I hope you have learned a few new ways to use it. I've recently freed myself from the annoyance of typing passwords frequently. As a system administrator, I find that using SSH to run commands on remote systems helps me manage them efficiently, both in executing the same command on multiple systems (such as package upgrades) and in collecting remote data (such as running uptime and sending the output to a file). As a user, I find that, once ssh-agent is configured properly, my workday proceeds more smoothly.

Resources

The OpenSSH homepage. The History and Features page briefly explains the differing implementations of the SSH protocol: http://www.openssh.com

Jay Beale's article, "Stupid, Stupid Protocols: Telnet, FTP, rsh/rcp/rlogin," explains why SSH is important and gives an overview of basic and intermediate SSH usage: http://www.securityportal.com/cover/coverstory20000814.html

The PGP Manual includes a good introduction to public-key cryptography: http://www.pgpi.org/doc/pgpintro/