All About SSH - Part II/II

Replacing telnet/rlogin/rsh with SSH
See also Part I

By Seán Boran (sean at boran.com)
www.boran.com/security/sp/ssh-part2.html

This article is the second in a two part series on SSH, the Secure SHell. The focus here is on the OpenSSH implementation. OpenSSH has developed quickly since it's inception in 1999 and has an expert team of developers behind it. 

  Recent changes:

See also the change history section

It is now a solid alternative to the commercial SSH1 and SSH2. The availability of OpenSSH, the loosening of the U.S. export controls in 2000 and the expiry of the RSA patent allows OS vendors to finally ship SSH on all UNIX-like Operating Systems and put telnet/rlogin/rsh/rcp to rest.

Refer to Part I for a general presentation of SSH and several other implementations.
Italian readers:
please note that this article has also been translated into Italian [9].


  1. OpenSSH Overview
  2. Compiling and installing on Solaris Linux | with SecurID | OpenBSD
  3. OpenSSH on NT/Win2000
  4. Configuration
  5. Prospects
  6. References
  7. Changes to this article

OpenSSH Overview

Secure Shell (SSH) is a secure replacement for Telnet, rlogin, rcp, rsh and provides secured TCP tunnels. It is described in detail in Part I

Where does OpenSSH originate?

Why OpenSSH?

Where can I get OpenSSH?

Why should I use OpenSSH?

Difficulties:



Compiling and installing on Solaris

Preparation

Previously, compiling was tricky with OpenSSH, new versions are much easier. There are lots of ways to compile OpenSSH, here we following Sun's guidelines Building and Deploying OpenSSH for the Solaris Operating Environment (which is a bit old at this stage) compiling with gcc.

Note: SSH is now bundled with Solaris 9. It is an older version of OpenSSH adapted by Sun. Some features such as HostbasedAuthentication are not implemented. The latest version of the SSH patch 113273 (sparc) should be installed to ensure known security issues are updated.

  Note:

Our first package listed here was v2.9p2
- v3.0.1 changes: configuration files in /etc/ssh, tcp wrapper support. 
- v3.1 changes: disable the SUID on the ssh client binary. The SSL and zlib libraries were updated.
- v3.4 changes: sshd_config: disable Protocol v1, CheckMail, TcpForwarding=no. Use Solaris 8 /dev/random. Update to SSL v0.9.6g.

See also  Upgrade notes.

Have a quick read of Sun's document , which we use this as a basis. There are however, some errors:

SSH is compiled below in a similar way to Sun and also installed in /opt/OBSDssh. There are some differences though:

Step by step instructions for compiling and building a package

The following package compiled on Solaris 2.6 worked on 2.6, 7, 8 on both UltraSPARC and SuperSPARCs. If compiled on Solaris 8 UltraSPARC however, it would only work on Solaris 8 UltraSPARC.
The precompiled Solaris package created below can be downloaded [10].

Step 0: 

set umask. If you use a restrictive umask like 077 or 027, this will cause problems when running "make install", often creating files and directories not accessible to others. Therefore it is suggested to allow group and world to read any files generated. In addition make sure ccs in in the path and LD_LIBARY_PATH doesn't cause any lib issues.

umask 022
export PATH=${PATH}:/usr/ccs/bin
unset LD_LIBRARY_PATH

  1. Download the following and extract the tarballs of the components needed:
    zlib -  www.gzip.org/zlib    or www.cdrom.com/pub/infozip/zlib
    OpenSSL - www.openssl.org/source
    OpenSSH - www.openssh.com/portable.html
    OpenSSH tools for Jass - www.sun.com/blueprints/tools
    TCP Wrappers - tcp_wrappers_7.6.tar.gz
  2. Build and install zlib: [Note that versions prior to 1.1.4 have a security bug]
    cd zlib-1.1.4
    make clean && ./configure && make
    [now su to root]
    make install

  3. Install the Solaris 8 /dev/random patch  [7]

    To check if it's already installed:
    showrev -p | grep 112438
    ls -l /dev/random

      PRNGD: There is no pseudo-random device patch for Solaris versions prior to Solaris8, so a prng needs to be installed.

    To Build and install prngd; first download from  www.aet.tu-cottbus. de/personen/jaenicke/postfix_tls/prngd.html [This site was experiencing some problems when last tried on 11.Mar.02]

    cd prngd-0.9.22
    #Compile for Solaris 7/8:
    make CC=gcc CFLAGS="-O3 -DSOLARIS" SYSLIBS="-lsocket -lnsl"
    #Compile for Solaris 2.6:
    make CC=gcc CFLAGS="-O -DSOLARIS26" SYSLIBS="-lsocket -lnsl"

    #Install: [now su to root]
    cp prngd /usr/local/sbin/prngd
    chown root:bin /usr/local/sbin/prngd
    chmod 755 /usr/local/sbin/prngd
    cp contrib/Solaris-7/prngd.conf.solaris-7 /etc/prngd.conf
    cat /var/adm/messages > /etc/prngd-seed

    To compile SSH with PRNGD:
    cd openssh-3.7.1p1 
    ./configure --prefix=/opt/OBSDssh --with-pam --without-rsh --sysconfdir=/etc/ssh --with-pid-dir=/var/run --disable-suid-ssh --with-prngd-socket=/var/spool/prngd/pool --with-tcp-wrappers=../tcp_wrappers_7.6

    make 

    Patch are downloadable from ftp://sunsolve.sun.com/pub/patches/ 
    - Solaris 8 SPARC: 112438-01
    - Solaris 8 Intel 112439-01

    Important: Reboot after installing the patch, to create the device /dev/random.

  4. Build and install SSL:
    cd openssl-0.9.7a
    make clean
    ./Configure solaris-sparcv7-gcc 
    make
    [now su to root]
    make install

  5. Build and install TCP wrappers
    cd tcp_wrappers_7.6
    make clean
    make REAL_DAEMON_DIR=/usr/sbin sunos5 CC=gcc
    [Note: We don't need to actually install the tcpd binaries for SSH compilation]
  6. Build and install OpenSSH.

    cd openssh-3.7.1p2

    Consider hiding the actual SSH version for key systems exposed to hostile networks: 
    vi version.h

    ./configure --prefix=/opt/OBSDssh --with-pam --without-rsh \
    --sysconfdir=/etc/ssh --with-pid-dir=/var/run --disable-suid-ssh \
    --with-tcp-wrappers=../tcp_wrappers_7.6 --without-rand-helper --with-ssl-dir=/usr/local/ssl 

    make

     

  7. Create a Solaris package
    Note: There is a script to build a Solaris package: ./contrib/solaris/buildpkg.sh included in the distribution, but it didn't work at all for v3.3. Hence we continue to use the script from Sun, adapted to our needs.

    a) Copy Jass scripts
    cd OpenSSH_tools

    b) Tune package settings:
    cd openssh-3.7.1p2
    vi makeOpenSSHPackage.ksh

    Adapt the script to your taste, e.g. see makeOpenSSHPackage.ksh which includes the following changes:
    - installSSHSUID=no  [yes - if you'll need host-based trusts]
    - change configDir=/etc to configDir=/etc/ssh
    - change "primes" to "moduli" in the line:  "for file in moduli ssh_prng_cmds; do"
    - change to install man pages in /usr/local instead of /opt
    - install tcp wrapper man pages

    cp sshd_config.out sshd_config.out.orig
    vi sshd_config.out 
              [adapt the default config to your taste, e.g. see our sshd_config.out]

    c) Make the package
    cp sshd_config.out makeOpenSSHPackage.ksh openssh.server openssh-3.7.1p2/
    cd openssh-3.7.1p2
    ./makeOpenSSHPackage.ksh

    d) Examine the package description:
    pkginfo -l -d OBSDssh.pkg

    f) Rename the package to include architecture & version (This format is also suitable for Jass+Jumpstart installations):
    mv OBSDssh.pkg ../OBSDssh-3.7.1p2-`uname -p`-`uname -m`-`uname -r`.pkg

  8. Testing
  9. Upgrade notes: If you are upgrading, think carefully about the steps involved. Some examples are documented  [10] in the following text files:

    upgrade_checklist_371p2.txt   v3.7.1p1 => 3.7.1p2
    upgrade_checklist_371.txt   v3.4 => 3.7.1p1
    upgrade_checklist_34.txt      v3.1 => v3.4  
    upgrade_checklist_31.txt     v3.0.2p2 => v3.1
    upgrade_checklist_3.txt        v2.9 to v3.0.2


Compiling with SecurID Authentication

OpenSSH can provide authentication with SecurID tokens, thanks to a patch from Theo Schlossnagle (www.omniti.com/~jesus/projects ) . I've been using this for several years o Solaris, this sections describes the Solaris build. This patch integrates SecurID authentication services directly into the OpenSSH daemon, allowing users to use SecurID tokens directly as their passwords.

A new how-to page has appeared that is worth reading: http://www.joerg.cc/cgi-bin/wiki.pl?MySecurID-page 
RSA libraries for linux can be downloaded from ftp://ftp.rsasecurity.com/pub/agents/linux.tar 

To compile: extract SSH as usual, download Theo's patch into the OpenSSH directory, then:

Apply patch (using GNU patch tool): 
/usr/local/bin/patch < openssh-3.7.1p2+SecurID_v1.3.1.patch

Read README.SecurID before continuing.

Copy SecurID library to SSH dir:
cp /usr/ace/examples/sdiclient.a .

Consider hiding the actual SSH version for key systems exposed to hostile networks:
vi version.h

Compile (see the Solaris section above for an explanation of the options used), note that an ACE v4 server is used:
./configure --prefix=/opt/OBSDssh_sdi --with-pam --without-rsh --sysconfdir=/etc/ssh --with-pid-dir=/var/run --disable-suid-ssh --with-tcp-wrappers=../tcp_wrappers_7.6 --without-rand-helper --with-cflags=-I/usr/ace/examples --with-securid-old --with-ssl-dir=/usr/local/ssl 

Then make and build a package, as indicated in the  Solaris section for example. Note that the package name should be changed in makeOpenSSHPackage.ksh (I use OBSDssh-sdi).

./makeOpenSSHPackage.ksh
mv OBSDssh.pkg ../OBSDssh-sdi-3.7.1p2-`uname -p`-`uname -m`-`uname -r`.pkg

Comments:

A Binary Solaris 8 package for sun4u, OBSDssh-sdi.pkg can be downloaded [10].


Installation under Linux

NOTE: This (old) section is redundant as more newer versions of Linux include OpenSSH already, but it may be of interest to those who wish to install their own SSH.
We install OpenSSH below in /usr/{bin,sbin,man}, with configuration files in /etc/ssh, since that is what is used in the binary rpms for RH6.1.

Suse Linux 6.3:

Red Hat 6.1 on SPARC:

Red Hat 6.1 on Intel i386:

Download and install packages:
rpm -i openssl-0_9_4-3_i386.rpm
rpm -i openssh-1.2.2-1.i386.rpm
rpm -i openssh-server-1.2.2-1.i386.rpm
rpm -i openssh-clients-1.2.2-1.i386.rpm

Start the daemon:
/usr/sbin/sshd

Problems:


OpenBSD

OpenBSD 2.6 is bundled with OpenSSH v1.2 and works fine, except for a few issues:

That being said it worked well is a mixed environment of SSH1 Solaris Systems and NT Systems with Mindterm SSH.


OpenSSH server on NT/Windows2000


A. OpenSSH with Cygnus

A comprehensive UNIX-like environment, including a port of OpenSSH can be installed by installing Cygwin. The client and server work well and secure copy (scp) also works on client and server side, as did testes with VNC tunnelling.

B. OpenSSH from Network Simplicity

Mark Bradshaw has produced an interesting package for OpenSSH on Windows, based on cygwin.
http://www.networksimplicity.com/openssh

Documentation look promising indeed, I've not yet tested it though. A colleague who has tested it says: "Easy to install, works perfectly as a win service, scp works fine, ssh tunnelling also (stable), rsa/dsa authentication works fine too!".

 



OpenSSH Configuration

OpenSSH supports both the v1 and v2 protocol, this make things quite complex as there dedicated option for each and similar ways of doing the same things.

General tips 
Trusts

Let's say we want to login from host A to B, as root, without a password prompt. This is called a trust and is useful for automated operations, and for saving time when hopping from one machine to another. It is a feature that needs to be used with care, if security weaknesses are not to be opened up. Here we give an overview and some concrete examples on how to set it up.

SSH has two kinds of trust, one based on host keys - "host based", the other on user keys - "RSA or publickey".

Why host based and not RSA/public key trusts? 

- The server depends on the client protecting it's private key and passphrase properly.
- The normal server login, and account management/aging mechanisms may be bypassed.
- IP based access control was not possible with RSA keys in v1.
- Users have more freedom to setup trusts if RSA is allowed (this is good or bad depending on the server scenario)

Why RSA/publickey trusts?

- RSA/publickey is convenient for usage with ssh-agent on workstations to avoid multiple logins.
- Configuration is simpler and less error prone (Host based trusts can use /etc/shosts.equiv, hosts.equiv, .rhosts and .shosts. RSA/DSA/publickey  just uses .ssh/authorized_keys  and .ssh/authorized_keys2 for v2.x)

- Newer SSH versions allow controls to be placed on public key logins, via 'options' in authorized_keys:

  1. The source IP/name can be restricted:
    from="176.17.17.*"
    from="server1"
  2. Port forwarding can be disabled, or ports controlled:
    no-port-forwarding
    no-X11-forwarding
    no-agent-forwarding
    permitopen="10.1.1.3:80"
  3. Interactive shells can be disabled:
    no-pty
  4. A specific command can be executed, any other commands passed are ignored. Typically
    Note to the OpenSSH crew: It would have been nice to specify a list of allowed commands, for situations where several automated tools use the same trust.

     used for backups.
    command="df -k"

We recommend of Publickey trusts with protocol v2 only, mainly because:

 

Host-based trusts

And assume we want to use host trust, rather than RSA/publickey trust. The following was tested from OpenSSH v3.02p1 to v3 and v1.2.27. The v1 method also works between older SSH1 servers.

In the examples below, absolute path names are not given, your SSH config may be in /etc,  /etc/ssh, /opt/openssh/etc, /usr/local/etc ..... I recommend using /etc/ssh where possible..

With v1 protocol:

On host B
- Add the Host Publickey of A in ssh_known_hosts (permissions 644, owner root). A's public key can be found in ssh_host_key.pub on host A. When you copy the line from ssh_host_rsa_key.pub, add the name of hostA and a space before it, as you paste to the known hosts file.
- Add "serverA root" to /root/.shosts to allow login as user root. (permissions 600, owner root) 
- Add an entry for A to /etc/hosts
- Possibly restrict login accounts in sshd_config:  "AllowUsers"
- In sshd_config (permissions 644, owner root), set:

  IgnoreRhosts no 
  PasswordAuthentication yes 
  RhostsAuthentication no 
  RhostsRSAAuthentication yes 

On host A:
- The sshd client binary must be suid root, to enable it to read the host A's private key.
- To ensure that the ssh client selects the correct protocols, add to ssh_config:

Host serverB
  RhostsAuthentication no
  RhostsRSAAuthentication yes
  RSAAuthentication no
  PasswordAuthentication yes
  Protocol 1
  LogLevel DEBUG
  #UsePrivilegedPort yes

- If serverB has SSHv1 (e.g. v1.2.27), then you will also need to add "UsePrivilegedPort yes" to ssh_config

With v2 protocol:

On host B
- Add the Host Publickey of A in ssh_known_hosts (permissions 644, owner root). A's public key can be found in ssh_host_rsa_key.pub on host A. When you copy the line from ssh_host_rsa_key.pub, add the name of hostA and a space before it, as you paste to the ssh_known_hosts file.
- Add "serverA root" to /root/.shosts to allow login as user root. (permissions 600, owner root) 
- Add an entry for A to /etc/hosts
- Possibly restrict login accounts in sshd_config:  "AllowUsers"
- In sshd_config (permissions 644, owner root), set:

  IgnoreRhosts no 
  PasswordAuthentication yes 
  RhostsAuthentication no 
  RhostsRSAAuthentication no
  RSAAuthentication no
  HostbasedAuthentication yes

On host A:
- The sshd client binary must be suid root, to enable it to read the host A's private key.
- To ensure that the ssh client selects the correct protocols, add to ssh_config:

Host serverB

RhostsAuthentication no
RhostsRSAAuthentication no
HostbasedAuthentication yes
RSAAuthentication no
PasswordAuthentication yes
Protocol 2
PreferredAuthentications hostbased,password
# Only during initial debugging:
LogLevel DEBUG

Publickey trusts

And assume we want to use a RSA/publickey trust from hostA to hostB, using protocol v2 only. The following was tested with OpenSSH v3.02p1 on both sides. 

On host A
- Log in as the appropriate user and generate a v2 rsa key (~.ssh/id_rsa and ~.ssh/id_rsa.pub), and set a passphrase.
ssh-keygen -t rsa

- In ssh_config (or .ssh/config), set:

Host hostB
  Protocol 2
  PubkeyAuthentication yes
  PreferredAuthentications publickey,keyboard-interactive,password

On host B
- Possibly add an entry for hostA to /etc/hosts

- In sshd_config (or .ssh/config), set:

PubkeyAuthentication yes

- in ~/.ssh/authorized_keys add the contents of hostA:~.ssh/id_rsa.pub, for example:

ssh-rsa AAAAB3NzaC1yc2EAAAASOMEBIGLONGKEYOROTHERmdklQM= root@server1

- Possibly restrict the trust, e.g.

from="10.1.2.3",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAASOMEBIGLONGKEYOROTHERmdklQM= root@server1

Publickey trusts with ssh-agent/ssh-add

Now the previous section allows us to setup an Publickey session between the two hosts. If we want to have an automated login, without passphrase prompting, then we have two options:

  1. Enter no passphrase when generating the RSA key.
    Advantages: simplicity.
    Disadvantages: security. If an attacker could gain access to the private key file, it is not encrypted and thus he can quickly gain access to any system depending on this key for Publickey logins. If this key is used to logon on to several system, and will be used for an extended period of time, it would much better to encrypt the key.
  2. Enter a passphrase such that the private keys is stored in encrypted form.
    Advantages: security
    Disadvantage: simplicity. Some effort is required, which we explain in this section.

SSH provides an optional daemon ssh-agent, which can be used to store keys during a login session, only asking for passphrases once and passing keys as need to SSH when loggings into other hosts. For example, if we setup the trust from hostA to hostB in the previous section, as we do "ssh hostB" on hostA, we'll be prompted for the passphrase, which is then used to decrypt the private keys and authenticate. Assuming we logon on frequently to hostB, we can start ssh-agent, add a key to it and then logon as often as desired without having to enter a passphrase:

Start SSH agent:
[root@hostA]# ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-QaSI4226/agent.4226; export SSH_AUTH_SOCK;
SSH_AGENT_PID=4227; export SSH_AGENT_PID; 
echo Agent pid 4227;

Set the environment variables as given by the output of the ssh-agent:
[root@hostA]# SSH_AUTH_SOCK=/tmp/ssh-QaSI4226/agent.4226; export SSH_AUTH_SOCK;
[root@hostA]# SSH_AGENT_PID=4227; export SSH_AGENT_PID;
[root@hostA]# echo Agent pid 4227;
Agent pid 4227

Add the key to the agent:
[root@hostA]# ssh-add ~/.ssh/id_rsa
Enter passphrase for /root/.ssh/id_rsa: XXXXXX
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)

Now logon as often as you like to hostB, without the need to re-enter the passphrase each time
[root@hostA]# ssh hostB

A quicker version of the above would be:

ssh-agent > .ssh-env
. .ssh-env
ssh-add ~/.ssh/id_rsa

Notes

Don't forget to kill the ssh-agent when logging out:
pkill ssh-agent

Daemons & automated Publickey trusts

The above examples work fine for interactive sessions, but what about daemons that run on the system, or jobs that run from cron, that need to be able to access trusts, for example a root trust? 
For this case, 

Advantages: This type of trust has quite a high security, since even if the SSH private key is somehow stolen, the passphrase still needs to be cracked, before the be can be misused. 
Disadvantage: If the system is rebooted, the administrator must do an "ssh-add", before trusts will function.

A concrete example of how this works:

Copy /etc/init.d/ssh-agent to /etc/init.d and setup links to make it auto-start:
ln -s /etc/init.d/ssh-agent /etc/rc3.d/S99ssh-agent
ln -s /etc/init.d/ssh-agent /etc/rc2.d/K99ssh-agent

Then edit this file and change the patches near the top if needed.

Start the daemon:
/etc/init.d/ssh-agent start

You (root) should get a reminder via email saying ssh-add needs to be run, so we run it as follows:
. /tmp/ssh-agent.info
ssh-add ~/.ssh/id_rsa

Now lets say we have a cron entry that uses an ssh trust to host B:
0 * * * *  /bin/do/something

We now change it to load the ssh-agent environment and then run:
0 * * * *  . /tmp/ssh-agent.info; /bin/do/something

Or if we need to login interactively via the trust we would:
. /tmp/ssh-agent.info
ssh
hostB


Prospects for the Future

Given the current speed of development, the interest & expertise shown by the developers and the easing of U.S. export restrictions, OpenSSH is definitely the one to use.

Consider getting your organisation to contribute cash or people to help in the testing, development, packaging or documentation of excellent open source projects like OpenSSH.

Like all community efforts though, the success of OpenSSH depends active users and active developers. The more help the existing team get, the better.

 


References

[0] Getting OpenSSH:

See www.OpenSSH.com for the original BSD version and www.openssh.com/unix.html for Linux/UNIX ports.
Other sites for source tarballs: thermo.stat.ncsu.edu/pub/openssh/files/
 www.openssl.org/source

Note that the domain openssh.org does NOT belong to OpenSSH and should not be used.

[1] Part I of this Article.

[2] Schneier and Kelsey's Yarrow - A secure pseudo random number generator:  www.counterpane.com/yarrow.html

[3] SSH Communications and DataFellows.

[4] OSSH ftp.pdc.kth.se/pub/krypto/ossh

[5] openssh-unix-dev Discussion list
      www.progressive-comp.com/Lists/?l=openssh-unix-dev&r=1&w=2

[6] www.OpenBSD.com

[7] /dev/random for Solaris

[9] This article has been translated into Italian:

Tutto su SSH - Parte II/II, Sostituire telnet/rlogin/rsh con SSH
http://www.ziobudda.net/Recensioni/ssh-part2.php  

[10] A copy of the precompiled Solaris packages, migration notes and config examples described above can be downloaded for SPARC and x86. See www.boran.com/security/sp/ssh or the mirror sean.boran.com/security/sp/ssh.

[11] Other links:


Changes to this article

28.Feb'00 First Publication
01.Mar'00 G.Cope & putty tests. C.Mason & 3DES key lengths. Update: Installation under Linux

8.May'00 Update: add notes on v1.2.3 which support Protocol V2.0.
16.Jun'00 Note on Security bug in versions prior to v2.1.1.
24.Jul'00  Fix for using scp when openssh installed in /opt/openssh on Solaris.
19.Sep'00 Feedback from Erek Adams: add link to Solaris /dev/random module.
24.Oct'00  Links to Italian translation.

1.Feb'01 Update links
31.May'01 Update. Add section OpenSSH on NT/Win2000
08.Aug'01 Compiling latest 2.9p2 on Solaris according to Sun's Guidelines.
24.Sep.01 Add links to precompiled Solaris pkg.
27.Sep.01 Adapt for openssh-2.9.9p2, create x86 &sparc packages [10]
17.Oct.01 Add section host-based trusts. Improve references.
13.Dec.01 Add Keychain, update host-based trusts for v1 server.

23.Jan'02 Adapt Solaris for openssh-3.0.2p1, New trusts section.
14.Feb'02 Add Publickey trusts with ssh-agent/ssh-add
11.Mar'02 Update Solaris packages & instructions for OpenSSH v3.1: openssl-0.9.6b->v0.9.6c, zlib-1.1.3->zlib-1.1.4, remove ssh client suid. Add upgrade notes.
27.Mar'02 Add  OpenSSH for NT from Network Simplicity
27.Jun.02: Solaris packages & instructions for OpenSSH v3.4
22.Sep.02: SecurID

31.Jan.03 Improve Solaris /dev/random notes [7].
20.Oct.03 Several tweaks on Solaris section.


Seán Boran is an IT security consultant based in Switzerland and the author of the online IT Security Cookbook.

Copyright 2002, Seán Boran, Last Update: 21 octobre, 2003