Security with PKI: SSH, SSL, and Tunneling

by Walt Stoneburner
v1.1b
"Security is a prime solution..."


This article assumes that you are already familiar with public key encryption to the extent you are able to use Pretty Good Privacy (PGP). What it does focus on is Public Key Infrastructre (PKI), creating certificates, certificate authorities (CA), and using them to establish a Secure Socket Layer (SSL) and a Secure Shell (SSH), which can be used to tunnel TCP/IP traffic of various services.

Let's All Get On The Same Page

When the same key can be used to both encrypt and decrypt a plain text message, the key is said to be symmetrical.

PKI works by constructing at least two keys that have the interesting mathematical properties where what one key locks, the other unlocks, and vice-versa (this particular point is important). They are said to be asymmetrical. One key is arbitrarily choosen to be given to the public, the other key is kept private. This allows the public to encrypt plain-text messages to the private key holder, and it allow the private-key holder to authenticate his crypto-identity when he sends a message for public consumption.

Thus it's a good idea to make your public key widely available, such as on a key server.

As such, a hybrid method is introduced. Messages are encrypted with a completely random, one time use, disposable, symmetric key. The symmetric key is then encrypted with PKI, and both the encrypted key and message are delivered. Only someone with the corresponding asymmetric key can obtain the the symmetric key for decoding.

For tamper detection, the plain text message message can be run through a hash algorithm which produces a hash value, also known as a message digest. The resulting value acts as a signature, or fingerprint, of the plain text message. Altering the message, even slightly, results in the message digest substancially changing. Because the hashing algoritm is lossy, it is not possible to reconstruct the original message from the hash.

If the hash is made available with the message it was derived from, then anyone can recompute the hash and determine whether or not the message (or its hash) was altered. Sure, it is possible someone might tamper with the original message and redistribute a revised signature, but the message was most likely obtained by decrypting an opaque message in the first place. Consequently, it would require acecss to a secret key the would-be forger shouldn't have access to.

So, it's possible to conceptually electronically sign something. Encrypt it with our private key, an act that only we are capable of, and the world can validate we did so by using our public key to see what we "signed." Unfortuantely, this can result in big files; the solution is to generate a hash of the message, and encrypt that with our public key. The public can then take the original, still unencrypted message, generate a hash and compare it to the hash they obtained from us by unlocking it with our public key. Instantly they can tell the document is unaltered and that we "signed" it.

Since any piece of data can be "signed," keys themselves are not exempt.

If we take a public key, and some meta data (like when it expires, who signed it, and the critera), we can sign it and package it up into a certificates. Key servers accept these along with revocation lists, for when you wish to announce a key is no longer used or you feel it has been compromised. This lets the public know not to use it and not to trust the things it signed.

Signing someone else's key implies a "trust" relationship in that you believe the newly-signed-key's owner is authentic. This can be nested to any depth, forming a chain of trust. One simply authenticates up the chain until reaching a trusted entity.

The special case is at the end of the chain, effectively the root of the trust tree. This is a key that signed itself and is widely recognized as a trustable entity. Such an entity is called a certificate authority, and with the instructions here, you can be one.

Our Crypto Tools

From the following list of crypto primitives, it's possible to construct higher level protocols and procedures: Messages don't have to come in terms of just files, but can also be streams of data. Consequently, there's enough here to establish a secure line of communication over TCP/IP. This is what enables us to do SSL with web servers and SSH to login or tunnel communication traffic securely between networks.

OpenSSL

OpenSSL is the toolkit that generates symmetric and asymmetric keys, handles encryption and descryption, produces hash values, and constructs certificates and certificate requests.

Compression goes hand in hand with encryption, and as such a compression library is a dependency.

Compiling Zlib

Zlib is a compression library located at www.gzip.org/zlib.

$ wget http://www.zlib.net/zlib-1.2.1.tar.gz
$ tar zxvf zlib-1.2.1.tar.gz
$ cd zlib-1.2.1
$ make clean
$ ./configure --shared
$ make
$ make test
# make install

Compiling OpenSSL

$ wget http://www.openssl.org/source/openssl-0.9.7d.tar.gz
$ tar zxvf openssl-0.9.7d.tar.gz
$ cd openssl-0.9.7d
$ ./config
$ make
$ make test
# make install
    So that OpenSSL can co-exist with other SSL libraries, like ssleay, the library implementors decided to put the package in a subdirectory. When writing software one must now use #include <openssl/ssl.h>

Under this configuration OpenSSL will be placed in /usr/local/ssl. Edit the file /etc/ld.so.conf and add the line /usr/local/ssl/lib to it. Then, as root, run the command /sbin/ldconfig.

Finally, edit the file /etc/profile and add /usr/local/ssl/bin to the PATH. There are also helper scripts in /usr/local/ssl/misc, which you could also add to the PATH if you wanted.

You may also want to configure /usr/local/ssl/openssl.cnf.

    You may want to set the default_days from 365 days to 3650 days (10 years). It can get ugly when the certificate authority expires out from under the keys it signs.
      Be sure to make these changes in /usr/local/ssl/misc/CA.pl and /usr/local/ssl/misc/CA.sh, too.

      You may also want to set the CountryName_default to US.

    Making a New Certificate Authority with OpenSSL

    $ /usr/local/ssl/misc/CA.pl -newca

    These instructions will create a subdirectory called demoCA in the current directory. If that directory already exists, then the above command will just return instead of executing.

      CA certificate filename (or enter to create)
      Press Enter
      Making CA certificate ...
      Using configuration from /usr/local/ssl/openssl.cnf
      Generating a 1024 bit RSA private key
      ................................++++++
      ......................++++++
      writing new private key to './demoCA/private/cakey.pem'
      Enter PEM pass phrase: my secret
      Verifying password - Enter PEM pass phrase: my secret
      -----
      You are about to be asked to enter information that will be incorporated
      into your certificate request.
      What you are about to enter is what is called a Distinguished Name or a DN.
      There are quite a few fields but you can leave some blank
      For some fields there will be a default value,
      If you enter '.', the field will be left blank.
      -----
      Country Name (2 letter code) [US]: US
      State or Province Name (full name) [Some-State]:Virginia
      Locality Name (eg, city) []:Ashburn
      Organization Name (eg, company) [Internet Widgits Pty Ltd]:Wizard Workshop and Company
      Organizational Unit Name (eg, section) []:Certificate Division
      Common Name (eg, YOUR name) []:Walt Stoneburner
      Email Address []:wls@wwco.com
      

    The certificate authority private key is then created in ./demoCA/private/cakey.pem (it will require the pass phrase you entered to use it). The public key for the certificate authority resides in ./demoCA/cacert.pem.

    You can verify it by doing:
    $ openssl verify ./demoCA/cacert.pem
    All you are interested in is the OK at the bottom.

    You can also see who issued a certificate:
    $ /usr/local/ssl/misc/c_issuer ./demoCA/cacert.pem

    Should you happen to need a digest (a.k.a. Fingerprint / Thumbprint):
    $ openssl x509 -fingerprint -sha1 < cacert.pem
    $ openssl x509 -fingerprint -md5 < cacert.pem

    OpenSSL's x509 command handles certifiate displaying, signing, and format conversions. For a certificate to be in a form usable to a browser, it needs to be converted from PEM format (base-64 encoding) to DER format (a binary encoding scheme based on ASN.1).
    $ openssl x509 -inform PEM -outform DER < ./demoCA/cacert.pem > ./demoCA/cacert.der

    Installing the CA in a Browser

    Now you'll want to get this certificate loaded into your browser. There's no way (that I know of) to get this to happen, other than by having a web server deliver it. The catch is that your web server is going to want to deliver this content as a regular file. You'll need to instruct your browser to do otherwise by editing your browser's mime times. For Apache, add this line:
    AddType application/x-x509-ca-cert .crt .cert .der .cct

    This tells your web server the files that end in .crt, .cert, .der, and .cct. should be delivered as x509 certificates. Make the change, bounce your webserve, and load the file's URL. You may want to consider renaming the file.

    If your certificate were signed by any commercially established "Certificate Authority," then it'd be quickly accepted by the browser. Instead, you must explictly tell your browser that YOU trust this certificate and the things signed by it. Once a certificate authority is trusted by a browser, then any certificate requests that were signed by that authority are trusted by the browser.

    Making a Keypair Trusted by the CA

    When you generate a certificate request, you're really generating a public/private key with some metadata asking the certificate authority (who is just another public/private key) to sign it for you. For if the certificate authority trusts someone's creditials, and you trust the certificate authority, then implicity you can trust people they trust.
    $ /usr/local/ssl/misc/CA.pl -newreq
    This makes a file called newreq.pem.

    Signing a Certificate Request

    Then the Certificate Authority has to sign your certificate.
    $ /usr/local/ssl/misc/CA.pl -sign
    The certificate authority must enter their password (which unlocks their private key for signing), it validates your request, shows the meta data in your request, and presents an option to the certificate authority to sign. If he does, this generates a signed certificate, which the certificate authority returns to the requestor. This contains their public key, the meta data, additional metadata by the certificate authority, and the whole glop is signed by the certificate authority (who's public key is widely available and ideally installed in your browser). That way software can look at the certificate and check that it's not forged or tampered with.

    What's going on is this: the new public/private key that you generated and had the CA sign now should be installed as your web server's public/private key.

    When someone requests a web page via SSL, their browser can do a quick key exchange with your server and generate a secure channel. But, why should a browser trust the server at the other end to be who they say they are? It shouldn't. That's where the certificate authority comes into play. It's trusted (because you told the computer it was); now via that trust relationship, it tells you that you can trust the guy at the other end because his public key is in a certificate issued by someone we already trust.

    SSH or OpenSSH

    Both SSH and OpenSSH use SSL encryption services to provide a mechanism for secured TCP/IP communcation.

    OpenSSH is free, but has a small history of having some obscure security vunerablities; in all fairness, these were pluged right after the theoritical threat became known. This knowledge should detract you from using OpenSSH over SSH, as OpenSSH has opted to air their dirty laundry for full disclosure, quick resolution, and high quality.

    Compiling OpenSSH From Scratch

    OpenSSH can be obtained from www.openssh.org, however it also has prerequisites of Zlib (not zlibc) and OpenSSL. You will need to have Perl and a C compiler also available.

    Be sure you have the dependencies listed above compiled first. Please see the INSTALL file for additional options you can supply to configure.

    OpenSSH also wants a user named sshd so it can do privilege separation. Create such a user and give it its own group (also called sshd). It should not need to login, have a home directory, or even a working shell (use /bin/false).
    $ wget http://ftp.lug.udel.edu/pub/OpenBSD/OpenSSH/portable/openssh-3.8p1.tar.gz
    $ tar zxvf openssh-3.8p1.tar.gz
    $ cd openssh-3.8p1
    $ ./configure --with-md5-passwords --with-mantype=man --with-tcp-wrappers
    $ make
    # make install

    Compiling Stunnel From Scratch

    Stunnel allows you to encrypt arbitrary TCP connections with SSL. It is available from www.stunnel.org. You will need OpenSSL or ssleay libraries.
    $ wget http://www.stunnel.org/download/stunnel/src/stunnel-4.05.tar.gz
    $ tar zxvf stunnel-4.05.tar.gz
    $ cd stunnel-4.05
    $ ./configure
    $ make
    # make install
      Note: Right after the ./configure step (before Make), you may want to check where the Stunnel wants to put the PEM file. Use:
      $ egrep ^PEM_DIR Makefile
      If nothing is there, configure using:
      # ./configure --with-pem-dir=/usr/local/var/stunnel

    Generating stunnel.pem Manually
    The easiest way to make a new certificate is make cert, however you can do it by hand using OpenSSL.

    Make a new public/private keypair. Store the private key (via keyout) in stunnel.pem. Take the public key, package it in a X.509 certificate signing request (CSR), and also store that in stunnel.pem.

      $ /usr/local/ssl/bin/openssl req -new -x509 -days 365 -nodes -config stunnel.cnf \
          -keyout stunnel.pem -out stunnel.pem

      Generation and Management of Diffie-Hellman Parameters.
      $ /usr/local/ssl/bin/openssl dhparam 512 >> stunnel.pem

    Display the certificate request.
    $ /usr/local/ssl/bin/openssl x509 -subject -dates -fingerprint -noout -in stunnel.pem

    Make sure that /usr/local/lib is in /etc/ld.so.conf and run /sbin/ldconfig.

    Setting up Secure IMAP with Stunnel

    The technique is simple, run stunnel as a daemon and have it listens to SSL traffic on port 993 (the secure IMAP port) and remaps all traffic to the local IMAP port.

    Make sure that you have this entry in /etc/services:

    smtp             25/tcp    mail         # Simple Mail Transfer
    smtp             25/udp    mail         # Simple Mail Transfer
    imap            143/tcp    imap2 imap4  # Interim Mail Access Protocol v2
    imap            143/udp    imap2 imap4  # Interim Mail Access Protocol v2
    imap3           220/tcp                 # Interactive Mail Access Protocol v3
    imap3           220/udp                 # Interactive Mail Access Protocol v3
    smtps           465/tcp                 # smtp protocol over TLS/SSL (was ssmtp)
    smtps           465/udp                 # smtp protocol over TLS/SSL (was ssmtp)
    imap4-ssl       585/tcp                 # IMAP4+SSL (use of 585 is not recommended,
    imap4-ssl       585/udp                 #            use 993 instead)
    imaps           993/tcp                 # imap4 protocol over TLS/SSL
    imaps           993/udp
    

    Start the Stunnel daemon listening for imaps traffic to map to imap4:
    # /usr/local/sbin/stunnel -d imaps -r localhost:imap4 -p /usr/local/var/stunnel/stunnel.pem
    # /usr/local/sbin/stunnel -d smtps -r localhost:smtp -p /usr/local/var/stunnel/stunnel.pem

    You may want to consider adding this line to the appropiate file(s) in /etc/rc.d so the system starts with this daemon running.

    Configure Mail Clients to Use SSL

    An Example Showing How To Configure Outlook 2000

    Outlook 2000 Advanced Settings for SSL Users should then use SSL with their IMAP and SMTP connections.

    For instance Outlook 2000 users should goto Tools / Accounts..., select the mail service, click Properties, and under the Advanced tab, check the Outgoing mail (SMTP) checkbox that says "This server requires a secure connection (SSL"), and make sure the port is 465, then check the Incoming mail (IMAP) checkbox that says "This server requires a secure connection (SSL)", and make sure the port says 993, then click OK.

    While not security related, users that use pine may want to se the Root folder path to mail under the IMAP tab.


SlingCode About     Articles     Links     Search Tips  
SEARCH: