Editor's Note: Bret Jordan of the University of Utah provided some configuration file examples and setup information for this article.
Nearly every day, I find myself in a situation that requires me to perform maintenance on some of my servers. That's just life in the Windows world. Usually the situation isn't critical—I need to move a file or restart a service—but because I administer a sizable number of servers, the tasks can be a real hassle. Administering machines that aren't at my office is even worse. A hassle turns into a security nightmare because of the inherent insecurities of most remote shell utilities.
Windows 2000 contains a beefed-up Telnet server, but earlier Windows versions don't provide any built-in remote-management capabilities for command-line use. Systems administrators responsible for managing Windows servers needed some way to issue commands to their servers across the network without using bulky packages such as Windows NT Server 4.0, Terminal Server Edition (WTS) or Symantec's pcAnywhere, so they resorted to various Telnet servers to get the job done. The idea of remote administration tools is good, but using Telnet is a mistake.
Telnet was developed in the early days of the Internet to let users connect to and work on more powerful remote servers. Telnet was developed with ease of use, not security, in mind, so all authentication and data transfer happens in the clear. Any attacker who can sniff network traffic as Telnet sends it across the network or Internet can gather usernames, passwords, and system information. Microsoft has never revised Telnet to include greater security, so the company's choice to include it in Win2K is unfortunate. Shipping Win2K with Win2K Server Terminal Services as the only remote administration option would have been better than including the inadequate Telnet server.
The Microsoft Telnet server makes one attempt at improved security: It supports native NT LAN Manager (NTLM) authentication, which encrypts passwords. You can force the Telnet daemon to accept only NTLM-authenticated passwords and reject others, but this technique is too restrictive for many shops. Win2K allows NTLM authentication by default, but systems administrators often change this value. In addition, NTLM helps only when you connect two Win2K computers that are both configured to allow NTLM authentication. When you telnet to or from a non-Win2K computer, authentication reverts to clear text and your security goes down the drain.
No matter what kind of authentication the Win2K Telnet client uses, Telnet sends all the commands that you issue and the results of those commands across the network in clear text. Thus, when you use Telnet, an attacker can simply sniff your network traffic to gather a lot of information about your systems and network without leaving a trace of his or her activity.
The UNIX world, which has been performing remote administration tasks for a much longer time than the Windows world, has come up with a great solution to Telnet's security problems while still providing the essential service of remote administration. The solution is Secure Shell (SSH). You can use a Windows version of SSH to secure your remote administration tasks.
SSH is a protocol for establishing secure connections over insecure networks. The second major version of SSH, SSH2, provides for a high level of data encryption and reliable authentication and fixes some of SSH1's inadequacies. SSH2 delivers mechanisms to prevent network sniffing, man-in-the-middle attacks, and encryption cracking. The protocol lets you use a public key infrastructure (PKI) as well as standard password authentication and (most important) is OS-independent. An SSH implementation exists for most major OSs, so you can use the protocol for unparalleled interoperability between platforms.
Several vendors offer implementa-tions of SSH for Windows, but the one I recommend and use is OpenSSH (http://www.openssh.com), which is a free, open-source implementation of SSH1 and SSH2. The OpenBSD Project, which makes the OS of the same name, developed OpenSSH. The OpenBSD programmers have a history of producing extremely secure code, and OpenSSH provides the best current mechanism for seamlessly connecting various platforms in a secure manner. SSH enjoys near universal adoption in the UNIX world, so if you have UNIX computers in your organization, they're most likely using SSH and will be able to talk to any Windows computers running SSH.
Credit for the Win32 port of OpenSSH goes to Cygnus Solutions, the company that originally developed Cygwin (http://www.cygwin.com), a package of popular freeware UNIX utilities that have been ported to Windows. Red Hat purchased Cygnus and now maintains the Cygwin utilities. Cygwin provides intermediary libraries that let code developed for UNIX OSs work in Win2K, NT, or Windows 9x with only minor modifications. Cygwin is an excellent toolkit for any administrator with UNIX experience who is moving into the Windows world.
Get the Tools
You don't need to install the entire Cygwin package on a Windows machine to use OpenSSH. You can download just three packages from one of the Cygwin FTP sites listed at http://www.cygwin.com/mirrors.html: Zlib, Cygwin, and Openssh. Zlib is used for compression. Cygwin contains the file cygwin1.dll, which lets OpenSSH run under Windows, as well as a few useful utilities. Openssh contains the SSH software. Note that this is not a support installation of Cygwin, so your mileage may vary.
On the FTP server, you'll find subdirectories containing the various Cygwin components. Each subfolder holds various versions of both the source and compiled code. The source files (which you don't need) include src in their name. Download the most recent versions of the non&—source code components. At the time of this writing, the files were /latest/zlib-1.1.3-6.tar.gz, /latest/cygwin/cygwin-1.3.2-1.tar.bz2, and/latest/openssh/openssh-2.9p2-3.tar.bz2.
Files ending in .tar.gz are similar to Windows .zip files. They're compressed archives, and recent versions of WinZip Computing's WinZip know how to unpack them. WinZip won’t be able to open files that end in bz2, however. For that, you should go to http://sources.redhat.com/bzip2 and download the bzip2 utility. Once you have decompressed the bz2 file (e.g., bzip2 –d file), you can open the remaining tar file with WinZip. Before unpacking any files, create a base directory to hold the executables. You can put the directory wherever it's most convenient for you; for this article, I use C:\ssh. Open the cygwinxxx.tar.bz2 archive, and extract the cygwin1.dll file to C:\ssh. Then, open the zlibxxx.tar.bz2 archive and extract the cygz.dll file to C:\ssh. Finally, open the opensshxxx.tar.bz2 archive, and extract the ssh-keygen.exe and ssh.exe files to C:\ssh. For server installations, extract sshd.exe, too.
OpenSSH Client Installation
The OpenSSH client requires little in the way of setup. The following steps aren't absolutely necessary for client operation, but they do make OpenSSH easier to use and ensure that some of the security mechanisms function properly. I strongly recommend that you complete the steps to ensure secure use of OpenSSH.
The first step is to add the OpenSSH base directory to your path. To add the directory in NT, right-click My Computer, choose Properties, and click the Environment tab. Add the base directory (C:\ssh) to the beginning of the Path system variable. Create a new user variable, call it HOME, give it the value C:\ssh, apply the change, and click OK. You can find the equivalent Environment dialog box in Win2K under the Advanced tab.
OpenSSH stores the public host key of any OpenSSH server you connect to in the file known_hosts or known_hosts2 and stores these files in the HOME\.ssh directory. Any RSA (the encryption algorithm that SSH1 uses) keys are stored in known_hosts, and any Digital Signature Algorithm (DSA—the encryption algorithm that SSH2 uses) keys are stored in known_hosts2. The OpenSSH client collects an SSH server's public host key the first time you connect to that server and uses the key for verification on subsequent connections to make sure that an attacker isn't trying to hijack the session.
The OpenSSH client uses the HOME variable to determine where to store the known_hosts or known_hosts2 file. However, if you install the server on the same computer as the client and create a Passwd file (I explain below how to create this file), the client will use the Home directory variable from the Passwd file to determine where to store the known_hosts or known_hosts2 file. In this case, use some value other than forward slash (/) for the home directory of any user who will use the client.
OpenSSH Server Installation
Server installation is slightly more involved than client installation. After you've extracted the cygwin1.dll, ssh-keygen.exe, ssh.exe, and sshd.exe files to C:\ssh, you must create the public and private key pair that the OpenSSH server will use to identify itself and to set up encrypted sessions with clients. You can create two types of keys. SSH1 uses the RSA algorithm, which was formerly patented, for key pairs. To make SSH2 as free from patented technology as possible, the SSH2 developers switched from the RSA algorithm to the unpatented DSA algorithm. The RSA algorithm is now unpatented too, but don't create the RSA key pair unless you need to for compatibility. If the OpenSSH server finds an RSA key pair, it will use SSH1 by default instead of SSH2, and SSH1 is less secure than SSH2.
To create a DSA key pair, open a command prompt, change to your base directory, and type
ssh-keygen –d –f
To create an RSA key pair, type
The two commands assume that C:\ssh is the base directory. If it isn't, modify the commands to point to the correct location. By default, the commands create 1024-bit keys, which are sufficient for most security needs. Be sure to manually recreate keys for every server installation; don't copy keys from one server to another, because you don't want two servers to end up with the same keys. If you receive an error that says, "You don't exist. Go away!" determine whether you have a Passwd file in C:\etc. If you do, rename it temporarily or add your username to it.
Next, you need to create a configuration file named sshd_config (no extension) in the base directory on the OpenSSH server. After you create this file, you can copy it without modification to subsequent server installations. The file is composed of variables and their values. You can put many different configuration variables in the sshd_config file, but most installations need only a few.
Listing 1 shows a basic sshd_config file. The HostKey variable specifies the location of your RSA host key pair; the HostDSAKey variable shows the location of your DSA key pair. If you didn't create an RSA key pair, omit the HostKey line. If you put the key pairs in a different location, change the lines in the file to reflect the proper location. Note that the file paths use forward slashes instead of backslashes for compatibility with UNIX naming.
The PidFile variable contains the process identifier (PID) for OpenSSH. In the UNIX world, scripts use the PidFile to kill SSH. Windows systems administrators don't use the PidFile for this purpose, but OpenSSH still requires the file.
The Protocol variable tells the server which SSH protocols it should support. If possible, you should set the value to 2 to allow only SSH2 connections because SSH1 has some serious security deficiencies. If you absolutely must have compatibility with SSH1 clients, remove the Protocol entry or set it to "2,1." For more information about the variables that you can include in the sshd_config file, go to http://www.openbsd.org/cgi-bin/man.cgi?query=sshd.
You also need to create a user database for authentication. The Passwd file is the central authentication method on most UNIX systems, so the Cygwin pseudo-UNIX environment also uses a Passwd file. When ported software such as OpenSSH requests authentication for a user, Cygwin first looks for the username in Passwd. If Cygwin doesn't find the username in Passwd, it denies access even if the user is a local administrator. If Cygwin finds the username, it passes the authentication request to Windows for password verification. The local SAM database is checked first for the password, then the domain database (if available).
Create the directory Etc in the file-system root, then create the text file Passwd with no extension in the Etc directory (C:\etc\passwd). You can extract and use the mkpasswd.exe utility in the Cygwin package to create the Passwd file, or you can use Listing 2 as a guide to create the file.
The Passwd file is a colon-separated list of users and user information. The seven columns of information are, in order, username, password, User ID (UID), group ID (GID), comment, home directory, and logon shell. On Windows machines, only the username, UID, home directory, and shell are important, but you also might want to use the comment field. You should always leave the password and GID fields empty.
The UID field doesn't necessarily equate to the Windows UID. Don't set a UID of 0 or 500 because these numbers are internally reserved. Otherwise, you can randomly assign UIDs. If you want to find out what numbers would typically be in the UID field, you can run the mkpasswd.exe utility to obtain a listing.
To function properly, the Passwd file needs a line for the Administrator. The Administrator line should have no UID. I also omit a shell for the Administrator line to prevent anyone from logging on as the Administrator.
Populate the Passwd file with information for each user who needs to perform remote administration tasks on the server. If the same users will be logging on to other servers, you can copy the Passwd file to other OpenSSH installations. Be sure to adequately protect the file so that only you and LocalSystem have the rights to add users to the file and view its contents.
You can also have the OpenSSH server keep a log of each user's most recent logon date and time. This log can tip you off if someone else uses your account without your permission. Create a directory in the file-system root and name it Var, then create a subdirectory and name it Log. Inside Log, create an empty file and name it Lastlog (C:\var\log\lastlog). When the server sees this file, it will write a timestamp in it for each user as he or she logs on to the system. The next time the user logs on, he or she will see a message indicating the date and time he or she last logged on.
At this point, you're ready to test your OpenSSH installation. You need to open a shell that LocalSystem owns to do your testing because the OpenSSH server needs to run under the security context of LocalSystem to function properly. The easiest way to start a shell is to go to the server's command line and type one of the following commands. If you have Task Scheduler, type
net start "task scheduler"
net start schedule
Then, regardless of which scheduler you have, type
When the specified time comes, the scheduler will launch a command shell that LocalSystem owns. You can then use this shell to type the following command:
C:\ssh\sshd.exe —d —f C:\ssh\sshd_config
The command's -d option causes the OpenSSH server to start in debug mode. If the installation has any problems, you'll see error messages that will help you troubleshoot the problems. The most likely problems are configuration files that aren't accessible to the LocalSystem account and errors in the configuration files. You'll remove the -d option when you run the OpenSSH server in production mode.
To verify that the SSH server is working properly, you must connect to it with a client. At a Windows machine on which you've installed the OpenSSH client, type the command
where user is the username of someone who's allowed to log on locally to the server and who's listed in the server's Passwd file. Make sure that the username is listed in the client's Passwd file, if the client has one. You can use localhost for the server name if you're issuing the command from the server.
After a few seconds, the client will display a message telling you that it can't verify the identity of the server and asking whether you want to continue connecting. This behavior is normal. The client has received the server's public host key and has tried to verify the key against its known_hosts or known_hosts2 file. Because you're connecting to the server for the first time, the client hasn't stored its public key yet. Type "yes" to tell the client to continue. The client will warn you that it has permanently added the key. The warning is nothing to worry about, so you can ignore it. At this point, you'll see a screen similar to the one that Figure 1, page 36, shows.
The client won't prompt you in the future about this server's key unless the client detects a change in the key. If the client does detect a change, someone might have removed or modified your known_hosts or known_hosts2 file or changed the server's host key. Or someone could be attempting to hijack your connection to the server. If you see the key prompt sometime other than at the initial connection to a server, investigate to make sure that no one has compromised your security.
Be sure to also check the server Application log after you log on. The Application log should have entries that show logons and entries that show attempted connections. You can use these entries to watch for illicit activity on the OpenSSH server.
After you've verified that the OpenSSH server is functioning correctly, you might want to turn OpenSSH into a service so that the server loads it whenever the server boots. You can use the Srvany utility from the Microsoft Windows 2000 Server Resource Kit or Microsoft Windows NT Server 4.0 Resource Kit to make OpenSSH a service. For more information about Srvany, see Mark Minasi, This Old Resource Kit, "Srvany," February 2000, and This Old Resource Kit, "More About Srvany," March 2000. If you don't have one of these resource kits, you can use Idetix Software Systems' Invoker utility. Srvany seems to work better, but I've gotten Invoker to work as well, though with minor trouble. You can download Invoker from http://www.idetix.com/support_files.htm.
Regardless of which method you use to create the OpenSSH service, to use OpenSSH effectively as a service, you should run it under the default LocalSystem account. OpenSSH must be able to, in effect, become any user, and LocalSystem has the necessary rights to allow this. If you want to run OpenSSH under another account, look in the OpenSSH documentation for the necessary rights. You should also set an environment variable called CYGWIN equal to tty so that the server interprets input correctly. Create a batch file that contains the command in Listing 3, and place it in your base directory. Instead of starting the OpenSSH server directly, run this batch file to launch the server.
An OpenSSH server requires very little management. The only administration task you should have to perform is adding a user to the server's Passwd file to give the user remote access to a command line on the server. You can use Notepad or any other text editor to add a user to the Passwd file. However, OpenSSH retrieves the Passwd file only when OpenSSH is launched. If you've set up OpenSSH as a service, OpenSSH is launched only when the server reboots or when you restart the service after killing the sshd.exe process. Obviously, you don't want to reboot your server whenever you need to add a user, so you need a way to kill OpenSSH. The sshd.exe process is visible in Task Manager, but you can't kill the process from there.
One answer is to use a couple of other Cygwin utilities, kill.exe and ps.exe, both of which are in the Cygwin package. Place both of them in your C:\ssh directory for ease of use and security. I recommend renaming kill.exe to cygkill.exe if you have the Win2K or NT 4.0 resource kit installed because the kits also have a kill.exe utility.
As I mentioned earlier, to work with the OpenSSH process, you must use a shell that the LocalSystem account owns. Use the procedure I outlined in the section about testing the server to launch a shell. At the command line, type
to obtain a list of all the Cygwin processes running. Look for the oldest OpenSSH process, and note its PID. Then type
where PID is the identifier for the OpenSSH process. The service will relaunch itself, complete with a new Passwd file.
Alternatively, you can use the kill.exe utility from the Win2K or NT 4.0 resource kit. First, use tlist.exe (also from the resource kit) to obtain a list of all processes with their PIDs, then use the Kill command with the first sshd.exe process listed (the first process might not have the lowest number). After killing the process, stop and restart the OpenSSH service, and you're back in business.
Because OpenSSH spawns a separate process for each connection, you can even kill the sshd.exe process from an SSH session on a remote client without dropping your connection. Be sure to close all the old client connections after you restart the service and before you start any new connections.
A Few Precautions
SSH is a great addition to any network or systems administrator's toolkit, but it's not a silver bullet for all your security woes. Properly managed, OpenSSH is a secure tool, but you need to follow a few rules:
- Keep remote access available only to administrators when possible.
- Restrict access to the \ssh, \var, and \etc directories to LocalSystem and the local Administrators group.
- If an SSH client warns at a time other than at the initial connection to an OpenSSH server that the server's host key has changed, investigate the situation.
- Use SSH1 only if you absolutely must have compatibility with older clients.
With SSH, you can remotely issue almost any command that you would be able to issue if you were sitting at the server's console. To make the most of this capability, you should have the Win2K or NT 4.0 resource kit because they include utilities that let you remotely shut down or reboot the server, list the tasks that are running and kill them, and much more.
Now that you've seen how easy it is to set up OpenSSH, you should replace all the Telnet servers in your organization with SSH servers. OpenSSH not only is secure but also has some powerful features, including support for secure file copying, port redirection, and using public and private key pairs instead of passwords for authentication. When you see all that OpenSSH can do, you'll agree that it's an essential part of your administration toolkit.Corrections to this Article:
- "SSH for Windows" (September 15, 2001) describes hot to download three .gz files from a Cygwin FTP site and unpack them with WinZip Computing's WinZip. Red Hat changed two of those files to use the .bz2 format. You can download the .bz2 files from a Cygwin FTP site, but WinZip won't decompress them. Go to http://sources.redhat.com/bzip2 and download the bzip2 utility, which will unpack these files.