OpenSSH: The Swiss Army Knife for Secure Networking
时间:2016-06-15 ┊ 阅读:2,743 次 ┊ 标签: 分享 , 系统 , 配置
Aug 1, 2008 by Scott Klement
In the Linux world, Secure Shell (SSH) is extremely popular. It provides the ability to log on to other computers (similar to Telnet), run commands on other computers from a script (similar to the i5/OS RUNRMTCMD command), copy files over a network (like CRTDUPOBJ over a network), tunnel network traffic (similar to a very simple VPN), and transfer files (like FTP). For all these functions, SSH protects the network transmissions with high-quality encryption and private-key authentication. And it can be run both interactively and from a script or program.
Oh, yeah, did I mention that it's available free of charge? Starting with V5R3, IBM makes OpenSSH available for i5/OS running under Portable Application Solutions Environment (PASE). In this article, I talk about the OpenSSH toolkit with a focus on how you can use it from i5/OS programs.
Getting Started
To install OpenSSH, you use the standard RSTLICPGM CL command, as you do with many other licensed programs. After OpenSSH is installed, you can use it as a client that makes SSH connections or as a server that accepts SSH requests. For details about getting started, please see the sidebar "Installing OpenSSH and Running an OpenSSH Server," below.
Using the OpenSSH Client Programs
OpenSSH comes with many different programs, but these are the main ones that you'll be interested in:
ssh — secure shell, the main client program, used for interactive logons (like Telnet), running remote commands, and creating tunnels
scp — secure copy, a simple way to copy files over a network; the syntax is intended to be similar to the Unix cp (copy) command used to copy files
sftp — secure FTP; despite the name, this tool does not use the FTP protocol but rather uses the SSH protocol; however, it provides a command-line interface similar to what you see with popular FTP clients
Establishing Keys for Client Programs
All the SSH tools were designed to run either interactively or from a UNIX shell script. You can use that script support to automate the SSH applications from a CL program, a PASE shell script, or even an HLL language (e.g., RPG).
One of the basic problems that you face in creating a script is this: Because there's no interactive user, there's nobody to enter the password, so how do you handle this conundrum? Because of the security ramifications, you never hard-code the password into a program or script. Anyone who sees your source code can see the password! SSH provides public- and private-key files to solve this problem.
The idea is that you generate a pair of keys for each person who uses SSH. The key pair consists of a private key (a secret that should never be given to anyone) and a public key that should be installed on the SSH server that you're connecting to. During the connection process, the system verifies that the public key on the server matches the private key on the local machine. If they match, the system skips the password prompt and logs the user on immediately.
You generate the keys once for each user and install them, and from that point forward, the logons are automatic. Scripts can connect, run commands, send and receive files, and so forth without any need to type a password.
Don't get me wrong—using the SSH tools without generating or installing these keys is perfectly possible. However, the keys improve security and make scripting much easier, so I recommend that you generate them.
Here are the steps required to generate keys:
1. Log on to a 5250 session as the user ID that will be running the SSH client programs.
2. Find the name of the user's home directory by typing the following command and paging down to where the home directory is displayed on the screen:
DSPUSRPRF USRPRF(my-user-profile)
3. Type the following to get an interactive PASE command shell:
CALL QP2TERM
4. If the user's home directory (from the preceding step) doesn't exist, you need to create it. For example, if the home directory is supposed to be /home/klemscot, type the following:
mkdir /home/klemscot chmod 750 /home/klemscot
5. Create the public/private-key pair:
ssh-keygen -t rsa -N ""
When the system asks which file to save the key in, press Enter to accept the default. This step creates a directory named .ssh within the user's home directory, and inside that directory are two files named id_rsa and id_rsa.pub. These are your private- and public-key files, respectively.
6. The id_rsa.pub file from the previous step needs to be transferred to the destination SSH server — that is, the server you will be connecting to from your SSH client — and installed in the authorized_keys file on that server.
How the id_rsa.pub file gets installed depends on the policies that the administrator of the destination SSH server has in place. Sometimes the initial key setup on that server is accomplished by e-mailing the public key to the server's administrator. Other times, it is transferred using SSH with password authentication or using an unencrypted file transfer program such as FTP.
In any event, after the file has been transferred to the server, you need to have an .ssh subdirectory in the user's home directory on the SSH server. You can create the directory and add the key to the authorized_keys file by typing the following commands at a Unix command prompt on the server (which will be the PASE shell if it's an i5/OS server):
mkdir /home/my-user-id/.ssh cat id_rsa.pub >> /home/my-user-id/.ssh/authorized_keys chmod 600 /home/my-user-id/.ssh/authorized_keys
Establishing the Server as a Known Host
At this point, even if the public keys have been installed properly on the server, the scp or sftp tools fail because they don't trust the server. For example, here's what happens if I try to copy a file with the scp tool from an interactive PASE prompt:
> scp test.csv ssh.example.com: Host key verification failed. lost connection
This failure happens because the scp utility is designed to trust only the servers in its known_hosts file (and sftp has the same problem). On a UNIX system, if you run the scp or sftp tool interactively and connect to a host that the system is unfamiliar with, it asks the user whether he or she wants to trust the host and add it to the known_hosts file. However, because these tools were created for UNIX, they do not recognize a 5250 terminal as an interactive terminal! In the preceding example, scp thinks I'm running it from a script even though I actually ran it interactively, because it doesn't recognize the 5250 terminal.
The solution is to first connect with the ssh tool to get it to add the server to the known hosts file. To do that, type the following command:
ssh -T -l remote-user ssh.example.com exit
In this example, I connect to the SSH server named ssh.example.com as user ID remote-user (change that to the server name and user ID for the server you're logging on to). After ssh connects, it runs the UNIX exit command on the remote server — which, on UNIX servers, logs you off and ends the connection. The UNIX exit command is analogous to i5/OS SIGNOFF.
Because I'm signing off right away, this connection to the server essentially does nothing — except that it downloads the server's key, and if it's unfamiliar, gives me the chance to add it to my known_hosts file. When this opportunity occurs, I see the following on the screen:
> ssh -T -l klemscot ssh.example.com exit The authenticity of host 'ssh.example.com (192.168.0.1)' can't be established. key fingerprint is DSA. Are you sure you want to continue connecting (yes/no)?
If I type "yes" and press Enter, the system automatically adds this host to my known_hosts file. After that has been done successfully, I can use tools such as scp or sftp without receiving the "Host key verification failed" error.
What If Interactive Logons Are Disabled?
The preceding information about establishing interactive logons requires that the SSH server let you log on to run a remote command (in that example, it was the exit command). But some servers are set up for only scp access or only sftp access and prohibit these interactive logons. Such servers are rare, but they do exist.
In that situation, you have to use the scp or sftp utility to download the host's key into the known_hosts file. As I explained in the previous section, that won't work from a 5250 terminal because those utilities won't realize they're running interactively. Fortunately, you can use a different terminal instead of a 5250. To try that, follow these steps:
Set up the SSH server on your System i, following the steps in this article.
Download putty.exe, a free SSH client for Windows, from the PuTTY home page at chiark.greenend.org.uk/~sgtatham/putty. The only file you need to download is putty.exe. Just download it to your desktop, and double-click it to run it.
Under host name, put the domain name or IP address of your System i on which you just started the PASE server. Make sure SSH is selected, and click Open.
Log on to your System i using the user ID and password that you typically use for a 5250 session. You should now be at a PASE command prompt. From that prompt, type the scp or sftp command needed to connect to the remote server. Because you're no longer using a 5250 terminal (instead, you're using PuTTY, a UNIX-like terminal), you should get the same prompt that the ssh command gave in my previous example.
$ scp test.csv remoteuser@ssh.example.com: The authenticity of host 'ssh.example.com (192.168.0.1)' can't be established. DSA key fingerprint is 68:9d:6e:10:7a:7f:09:d5:21:20:17:4f:e9:1d:fe:92. Are you sure you want to continue connecting (yes/no)?
To add the host to your known_hosts file, answer "yes" to this question. Subsequent attempts to use scp or sftp from the 5250 terminal or from a CL program should now work without any hassle.
Using the SSH Tool
You can use the ssh command to create tunnels between a TCP port on the local computer and a TCP port on the remote one. This setup can be used as something of a "poor man's VPN," providing a means of encrypting and securing TCP channels over Internet connections.
The setup also provides an interactive logon as a UNIX terminal emulation program, as a secure replacement for Telnet. For example, if you want to log on to an SSH server from your System i, you could type the following at a PASE shell:
ssh -l scottk bcserv3.klements.com
This command logs me on to the server named bcserv3.klements.com using scottk as my user ID. The command uses cryptographic keys or a password to ensure that I'm really scottk, and then I get an interactive logon. Unfortunately, this logon is not as useful as it sounds, because I'm usually logged on to i5/OS with the 5250 protocol, and the limitations of the 5250 protocol make this type of interactive logon impractical. Connecting directly to bcserv3.klements.com from my desktop and not going through i5/OS would make more sense
However, you can also use the SSH command to run a remote command, much like the RUNRMTCMD CL command, except it's much more secure. Any text added to the command line after the host name is considered a command to run on the SSH server. For example:
ssh -l scottk bcserv3.klements.com processupload.sh
This command logs on to the SSH server and runs the processupload.sh command on that server.
The SSH command can also be used for tunneling — that is, you can set up a port that's forwarded, with strong digital encryption, across the network. For example, consider the following command:
ssh -l scottk -L 8023:localhost:23
This command opens port 8023 on the local computer. Anything transmitted to port 8023 gets encrypted and forwarded to the remote SSH server at other400.example.com. That SSH server then unencrypts that data and sends it to port 23 on its side of the connection.
Consider a situation in which one System i is running in Chicago and another one is running in Los Angeles, and you need to create a secure 5250 command, using the TELNET CL command from one System i to the other. If you run the preceding ssh command in Chicago, it sets up a tunnel on port 8023. You can then issue the following CL command:
TELNET RMTSYS(localhost) PORT(8023)
Notice that you're not trying to Telnet to Los Angeles directly. Instead, you're connecting to the SSH tunnel on port 8023 on the local host system. The SSH command then encrypts the traffic and forwards it to the server in Los Angeles, where it's decrypted and connected to the Los Angeles server's port 23, which is the Telnet port. Voila, you've added encryption to the TELNET command. During transit over the Internet, it's sent purely through encrypted SSH on port 22, which means that the network admin in Los Angeles doesn't even need to have port 23 open on his or her firewall. Pretty cool, huh?
Using the scp Utility
The scp utility is purely for copying files from one place to another. It's intended to mimic the normal UNIX cp (copy) utility, except that you can prepend a file name with the name of the server that it should be copied from.
For example, to copy the file /tmp/test.csv from my local i5/OS system to a remote SSH server, I could type the following:
scp /tmp/test.csv klemscot@ssh.example.com:/sharedfiles /klement/ test.csv
The first parameter, after the scp command itself, is always the original file that you want to copy. The last parameter always identifies the path name of the file or directory of the destination.
The part that says /tmp/test.csv identifies the file to be sent from my side of the connection. It is a path name in IFS naming format. Anytime you specify a path name (such as this one) that does not contain a colon, it is assumed to be on the local machine.
The part that says klemscot@ssh.example.com: is not an e-mail address. Instead, I'm indicating that I want to copy the file to the ssh.example.com server and that my user name on that server is klemscot. The server name is always followed by a colon to separate it from the file name. After the colon is the path name where the file will be stored on the server; in this example, it's saved under the name /sharedfiles/klement/test.csv on the server.
To receive a file from the server (as opposed to sending it to the server), simply reverse the order of the parameters:
scp klemscot@ssh.example.com:/customers/klement/ edidata.txt
In this example, I prefix the first file name with the host name, followed by the colon, to tell scp that I want to copy from the remote host because it's the source path name that I prefixed with a host name. The destination path name, in this example /tmp/edi.txt, indicates the place that I want to save the file to on my local system.
Note that the user ID in the scp command is optional. If you omit it, the command assumes that your user ID is the same on the remote system as it is on the local system. So if my user name on the local system is scottk, the following command logs on to ssh.example.com as the user named scottk.
scp ssh.example.com:/customers/klement/ edidata.txt /tmp/edi.txt
Similarly, when you're sending a file, you can specify a host name but omit the path name if you want to keep the same file name and upload it into the default directory on the server. For example:
scp test.csv ssh.example.com:
You can use these scp commands in a CL program. To do that, you have the CL program call the QP2SHELL API, which is used to invoke a PASE command shell and run a command in that shell. Figure 1 demonstrates this technique.
The QP2SHELL API that Figure 1 shows takes the path name of the PASE command shell as its first parameter, and each subsequent parameter is passed to that shell. In this case, I tell it to call the program named sh located in the /QOpenSys/usr/bin directory of the IFS—this is the default shell in PASE. I pass a parameter of -c to that shell, which tells it that I want to run a command, and the third parameter contains the PASE command that needs to be run. This is, of course, the scp command.
The &CMD variable in the preceding example code can be built into an expression if necessary. For example, if the server name, file names, and so forth were variables, I could concatenate them in the CHGVAR statement to create the command string that I want PASE to run.
I recommend that you start by determining the exact PASE command that you want to run and trying it interactively (through the QP2TERM program) to make sure it works. When you have the syntax of the command figured out, try coding it in your CL program. Trying it interactively makes it much easier to see what errors are occurring.
After keys are established, scp is simple to use for transferring files over a network. As you can see by my examples, writing a program that uses scp to transfer a file over a network is extremely easy.
Using the sftp Tool
The scp tool is great—but it's limited. Although scp can copy files over a network, it can't rename them, delete them, list directory contents, create directories, and so forth. If you want to do that sort of thing, you need to use the sftp tool. The sftp user interface is designed to look just like the FTP interface, so if you're comfortable using an FTP client, you'll find it easy to adapt to sftp. If you're unfamiliar with FTP, check out "FTP for Techies and Programmers" (System iNetwork Programming Tips, December 11, 2007).
Let me describe the differences between sftp and FTP:
The sftp tool encrypts the connection and can use key pairs (as described earlier) instead of passwords for authentication.
Whereas FTP selects a different port for each transfer, sftp always does everything on TCP port 22; sftp is therefore much easier to use through a firewall.
The sftp tool has no notion of ASCII versus BINARY file transfers. In FTP, this distinction controls whether data gets translated from one character set to another. In sftp, no translation is ever done; therefore, using sftp is similar to using BINARY mode in standard FTP. I recommend that you use tools such as CPYTOSTMF, CPYFRMSTMF, CPYTOIMPF, CPYFRMIMPF, and QShell to convert your databases to/from ASCII and convert them to the required format. That way, you needn't worry about ASCII/EBCDIC translations.
With sftp, you get none of the i5/OS-specific features, such as RCMD, LOCSITE, and NAMEFMT. The naming format is always IFS style. Remote commands are run through the ssh utility rather than through sftp.
Also, sftp does not use OVRDBF for scripting. Instead, if you want to use sftp with a script, you have to put the script in an IFS file and run it with the -b parameter to sftp.
Scripts in sftp stop if a command fails. In FTP, when a command fails, the script continues with the next command. For example, to invoke sftp interactively, I could do the following:
CALL QP2TERM sftp klemscot@ssh.example.com
This sequence of commands would log me on to the ssh.example.com server as user ID klemscot. Now I have an FTP-like command prompt on which I can use commands such as dir, get, put, cd, and mkdir, just like in an FTP session. I can type "help" to get a list of all the available commands.
Script files for sftp have to be ASCII files stored in the IFS. To create one, type the following commands:
STRQSH CMD('touch -C 819 /tmp/myscript.sftp')
This command creates a new IFS file named /tmp/myscript.sftp and sets the CCSID of that file to 819, which is ISO-8859-1, a variant of ASCII that's widely used where I live
EDTF STMF('/tmp/myscript.sftp')
This command invokes a green-screen editor — similar to SEU — that I can use to edit my sftp script. For example, I could create an sftp script like the one that Figure 2 shows.
Now that I've created an sftp script, I can invoke it from a PASE shell as follows:
sftp -b /tmp/myscript.sftp klemscot@ssh.example.com
This command tells sftp to run the script as a batch file. Note that there's no user ID or password in the FTP script. Instead, the user ID is specified on the sftp command line. The password isn't used because the key authentication makes it unnecessary. Naturally, I can run this script from a CL program instead of a command line if I want to. Figure 3 demonstrates how to do that.
Using Password Authentication — Even for Batch FTP
When I discussed public and private keys earlier, I mentioned that hard-coding a password in a script is a bad idea, and I explained why I prefer to use public-key authentication instead of sending a password. I also explained that the scp and sftp utilities verify that they're being called interactively before allowing password authentication and that they require a key when using scripting.
However, sometimes you have to work with business partners that don't give you a choice. Either you use the password authentication that they tell you to use, or you're out of luck.
For such situations, a workaround exists—a program available for AIX (which can run in PASE on i5/OS) called "expect" (expect is also available for other flavors of UNIX). Expect is a scripting tool designed to look like an interactive terminal to the programs that it calls. That way, its scripts can call interactive programs, but instead of getting input from the keyboard, the script sends the key strokes to the program.
The expect utility is free and requires TCL. TCL and Expect for AIX are available for download at the following links:
computer-refuge.org/classiccmp/aixpdslib/pub/tcl/RISC/5.1/exec
computer-refuge.org/classiccmp/aixpdslib/pub/expect/RISC/5.1/exec
I download those files to the /tmp directory of the IFS on my System i. To install them, I type the commands that Figure 4 shows.
With the tools installed, I create an expect script that controls the sftp tool. That expect script can pass the password, so I don't have to set up keys. To create the expect script, I type the following commands:
STRQSH CMD('touch -C 819 /tmp/myexpectscript') STRQSH CMD('chmod +x /tmp/myexpectscript') EDTF STMF('/tmp/myexpectscript')
Before typing in the script, I press F15 and change my stream file EOL option to *LF (the default is *CRLF) to make it more compatible with the way things are done in UNIX. Finally, I type the script that Figure 5 shows. The first line (the one that starts with "#") tells PASE which shell to run the script under. In this case, I want PASE to run it with the shell named /usr/local/bin/expect. The "spawn" line tells expect which program to start. In this case, it starts sftp and passes my user ID and the name of the server to connect to. The script then waits for the sftp client to print "Password:", and when that appears, it sends my password ("bigboy" in this example). It then waits for "sftp>" and sends the "put" command, and so on.
So, expect provides a nice way to create a script that can automate sftp and send a password for authentication instead of having to use a key pair. I can invoke the expect program from a CL program by using the syntax that Figure 6 shows.
Try Out OpenSSH
SSH is not just one tool but a rich suite of tools. It has tools for interactive logons, file transfers, tunneling, and remote command execution, and it does it all with industry-standard cryptography and authentication. What a great suite of tools, and it's free! I hope this article helps you take advantage of them all, and for more information, see Find Out More, below.
Installing OpenSSH and Running an OpenSSH Server
The OpenSSH toolkit is the Secure Shell (SSH) implementation available for i5/OS. It's the most popular SSH implementation on the market today. A November 2005 survey estimates that over 85 percent of the SSH servers on the Internet are using OpenSSH. The fact that i5/OS can run this mainstream implementation of SSH is good news, because it means that i5/OS file transfers that use SSH interoperate properly with all the other systems out there.
On the other hand, if you're not used to the way things are done on UNIX systems, you might find OpenSSH a little cumbersome to use, because it wasn't designed for the CL command interface that you're probably used to.
Running OpenSSH on i5/OS requires the following:
i5/OS V5R3M0 or later
TCP/IP set up and working
Name resolution (the i5/OS DNS Resolver) properly configured
Portable Application Solutions Environment (PASE — 5722-SS1, option 33) installed
IBM Portable Utilities for i5/OS (5733-SC1)
QShell (5722-SS1, option 30) is not required (strictly speaking) but makes it easier to integrate SSH with native applications
When I ordered i5/OS V5R3, 5733-SC1 wasn't included with the CDs. I had to talk to my IBM Business Partner (the same folks I called when I ordered i5/OS) to get this licensed program sent to me. It was sent free of charge.
When I ordered i5/OS V5R4, however, 5733-SC1 was included with the i5/OS CDs. I don't know whether that's standard. In any case, if you don't have the CD, have your business partner send you a copy.
After you install PASE and have the media for 5733-SC1, you can install it on your system by typing the following commands:
RSTLICPGM LICPGM(5733SC1) DEV(OPT01) OPTION(*BASE) RSTOBJ(*ALL) LNG(2924) RSTLICPGM LICPGM(5733SC1) DEV(OPT01) OPTION(1) RSTOBJ(*PGM)
Replace OPT01 in the preceding commands with the name of the optical disk unit that you're using to install 5733-SC1.
Running an SSH Server
On UNIX systems, an SSH server is frequently used for interactive logons, in much the same manner that we use the Telnet server under i5/OS. It lets terminal emulators connect, sign on, and get a command prompt on which interactive commands can be run. However, unlike the i5/OS Telnet server, the SSH one runs in PASE and therefore gives you a PASE command line.
You can use SSH's tunneling support as an alternative to SSL for encrypting 5250 data streams; however, few shops are interested in doing that. They're happy with their SSL.
But running an SSH server on i5/OS is a secure alternative to FTP. Standard FTP is unencrypted and therefore has many drawbacks related to security. Although the FTP server in i5/OS can run FTP over SSL, using SSH works better. FTP over SSL is notoriously difficult to get working through a firewall or Network Address Translation (NAT) gateway. However, as long as the firewall lets port 22 come through, SSH works great.
Generating Server Keys
If you plan to run SSH as a server application, you need to establish public and private keys for the SSH clients that might connect to your server. These keys are used when a client connects so that the client can (cryptographically) know which server it's connected to. The first time a client connects, it downloads your public key and stores it in a database. Subsequent connections verify that the key is unchanged so that the client application can be sure it's connected to the right place and that the connection hasn't been usurped by a hacker.
The server keys need to be generated only once, immediately after installing OpenSSH.
There are three different types of keys available in SSH, so you need to generate server keys for all three of these types. Here are the commands that you need to run to generate the keys. To get a PASE command shell, type the following command:
CALL QP2TERM
Change your current directory (analogous to *CURLIB, the current library that we're used to in i5/OS) to the one in which the OpenSSH configuration is stored by typing:
cd /QOpenSys/QIBM/UserData/SC1/OpenSSH/ openssh-3.5p1/etc
Generate the keys by typing the following three commands:
ssh-keygen -N "" -t rsa1 -f ssh_host_key ssh-keygen -N "" -t dsa -f ssh_host_dsa_key ssh-keygen -N "" -t rsa -f ssh_host_rsa_key
Press F3 to exit the PASE shell and return to the regular i5/OS command line.
Starting the OpenSSH Server
The server program for OpenSSH is called sshd, which stands for "SSH daemon." In Unix terminology, the word "daemon" is synonymous with "server," so "SSH daemon" simply means "SSH server." To start the server, type the following command:
SBMJOB CMD(STRQSH CMD('/QOpenSys/usr/sbin/sshd')) JOB(SSHD) JOBQ(QUSRNOMAX)
To end the SSH server, type the following command:
WRKACTJOB SBS(QUSRWRK)
From that screen, take option 4 next to each of the sshd jobs in the subsystem and press Enter to end them.
Note: Although the preceding options work for me, some people prefer to create a dedicated subsystem for sshd jobs — a good idea if you plan to handle a lot of SSH clients connecting to you. IBM has provided instructions for how to do that in Chapter 2 of the Redpaper titled "Securing Communications with OpenSSH on IBM i5/OS."
At this point, the OpenSSH server should be ready for clients to connect to and use in its default configuration. The default configuration works nicely for most shops; however, if you want to change the way the server works, there's a configuration file that you can edit with the following command:
edtf '/qopensys/QIBM/UserData/SC1/OpenSSH/ openssh-3.5p1/etc/sshd_config'
The OpenSSH website has documentation for the options listed in that file. Go to openssh.org/manual.html and click sshd_config.
After you change the configuration, stop and restart the sshd jobs for the changes to take effect.
— S.K.
Find Out More
IBM Porting Central page about OpenSSH on i5/OS
IFS/File Conversion/File Transfer forum at SystemiNetwork.com
Redpaper: "Securing Communications with OpenSSH on IBM i5/OS"