Integrating the Secure Shell Software
NOTE
This article is the fifth chapter of the Sun BluePrints_ book Secure Shell in the Enterprise by Jason Reid, which is scheduled to be available in July 2003 through http://www.sun.com/books, amazon.com, and Barnes & Noble bookstores. This article is meant for system administrators who want to integrate Secure Shell technology into their enterprise.
Secure Shell was designed as a replacement for the Berkeley r-protocols. With the exception of key management, it can be used as a simple drop-in replacement. More advanced features that may be appropriate to your environment are also offered.
This chapter discusses integrating Secure Shell into your environment. It covers replacing rsh(1) with ssh(1) in scripts, using proxies to bridge disparate networks, limiting privileges with role-based access control (RBAC), and protecting legacy TCP-based applications. After integrating Secure Shell, insecure legacy protocols can be disabled.
Secure Shell Scripts
Automating actions with the Secure Shell client, ssh(1), is mostly a straightforward replacement of either the rsh(1) or rlogin(1) commands. There are, however, some key differences in how ssh(1) performs compared to its counterparts. Additionally, alternate authentication credentials and host keys must be addressed.
rsh(1) Versus ssh(1)
In basic usage, the ssh(1) command is a direct replacement for the rsh(1) command. The major difference between them is authentication. If an ssh(1) command is issued and a password or passphrase is needed, it will be prompted for, then the command will be executed. In this case, the rsh(1) command will fail with a permission denied error.
$ rsh host -l user cat /etc/passwd permission denied $ ssh host -l user cat /etc/passwd user@host's password: password root:x:0:1:Super-User:/:/sbin/sh daemon:x:1:1::/: bin:x:2:2::/usr/bin: sys:x:3:3::/: adm:x:4:4:Admin:/var/adm: lp:x:71:8:Line Printer Admin:/usr/spool/lp: uucp:x:5:5:uucp Admin:/usr/lib/uucp: nuucp:x:9:9:uucp Admin:/var/spool/uucppublic:/usr/lib/uucp/uucico smmsp:x:25:25:SendMail Message Submission Program:/: listen:x:37:4:Network Admin:/usr/net/nls: nobody:x:60001:60001:Nobody:/: noaccess:x:60002:60002:No Access User:/: nobody4:x:65534:65534:SunOS 4.x Nobody:/:
For background jobs, ssh(1) also supports the -n option to set standard input to /dev/null. Alternatively, -f sets standard input to /dev/null after password or passphrase requests, but before command execution. If no remote execution is required and only port forwarding requested, the -N option can be used (Protocol 2 only).
rcp(1) Versus scp(1)
The rcp(1) command has the same authentication problem as the rsh(1) command. As with ssh(1), the scp(1) command will prompt for passphrases and passwords as needed. Unlike the rcp(1) command, scp(1) displays a progress meter as it copies the file. This behavior can be disabled with the -q option. The scp(1) command can also optionally compress the data stream using the -C option.
The following example shows the rcp authentication problem and the scp command's progress meter.
$ rcp user@host:/etc/passwd /tmp permission denied $ scp user@host:/etc/passwd /tmp user@host's password: password passwd 100% |*****************************| 1044 00:00
telnet(1) Versus ssh(1)
The telnet(1) command is occasionally used to automate connections to systems in situations in which the rlogin(1) and rsh(1) commands cannot be used. Automating a telnet(1) connection requires the script to pass the login, password, and command to the telnet(1) command to execute. The following is a Korn shell script fragment that automates the telnet(1) session:
( sleep 2 echo login^M sleep 2 echo password^M sleep 2 echo command^M sleep 2 ) | telnet hostname
Unlike telnet(1), this will not work with ssh(1). The Secure Shell client was programmed to ignore passwords that are passed in this manner, as shown in the following example.
$ ( sleep 2 ; echo "password^M"; sleep 2; ls; sleep 2 ) | ssh host -l user Pseudo-terminal will not be allocated because stdin is not a terminal. user@host's password: password Permission denied, please try again. Unable to find an authentication method
The ssh(1) command can be tricked around this limitation by using Expect. For more information on Expect, refer to the Expect FAQ at: http://expect.nist.gov/FAQ.html
The following is an example of a short Expect script to automate logins with passwords when using the Secure Shell:
#!/usr/local/bin/expect # # spawn /usr/bin/ssh host -l user expect {*password:} send "password\r" # expect {*home*} exit send "command\r" sleep 2 # expect {*home*} exit
Automated Logins
Automating logins to a system requires the script to either possess or have access to the needed authentication credentials. The problem is protecting the destination host from compromised credentials. This requires safeguarding the credentials. A balance must be struck between security and cost in terms of scalability and maintenance. There is no perfect solution.
Secure Shell provides several choices of credentials:
Embedded passwords
Unencrypted identities (discussed in Chapter 6)
Embedded passphrases for encrypted user identities (discussed in Chapter 6)
Agents
Each choice has a drawback (see TABLE 0-1). The first three choices can be defeated with read access to the secret. The fourth, agents, can be defeated with access to the machine's memory.
TABLE 0-1 Automated Login Issues
Method |
Problem |
Embedded passwords |
Compromised by reading the script source code |
Unencrypted user identities |
Compromised by copying the private identity key |
Embedded passphrases for encrypted user identities |
Compromised by reading the script source code |
Agents |
Requires loading of the agent |
The most resistant solution is to use agents with manually loaded keys. The problem here is twofold: maintenance and scalability. Humans are neither completely reliable nor completely dependable. The operator must be present to reload keys into the agent in the case of a failure (for example, a system crash or power loss). The operator does not scale well either. This solution requires a central machine or small cluster of machines from which remote jobs are started. A potential single-point-of-failure exists.
There is no easy, secure solution to the problem of automated remote access. A compromise solution is to use encrypted user identities in conjunction with RBAC. Secure Shell secures the network connection. The user identity limits the authorization points (the private key and passphrase must be copied first). RBAC also limits the privileges of the account.
Host Keys
The major difference in Secure Shell being a drop-in replacement for the Berkeley r-commands is host key management. Before the user can be authenticated, the destination host's Secure Shell daemon must be authenticated to the client. This is done by matching a locally stored host key copy to the host key offered by the Secure Shell daemon.
When there is no locally-stored copy, both the Solaris Secure Shell software and OpenSSH default to asking whether or not to accept the newly encountered key. This adds complexity to a script, as shown in the following example.
$ ssh host The authenticity of host 'host' can't be established. RSA key fingerprint in md5 is: 7a:71:ff:d9:6d:19:d6:d9:ef:f9:4d:3f:92:7a:77:7b Are you sure you want to continue connecting(yes/no)?
The least secure method to remove this complexity is to turn off host key checking by setting StrictHostKeyChecking to no in ~/.ssh/config. The most secure solution is to acquire all of the host keys ahead of time and place them in ~/.ssh/known_hosts. See "Managing Keys and Identities" on page 71 for more information on the difficulties of key management.