6. Implementing and using SSL to secure HTTP traffic

Security of the data stored on a file server is very important these days. Compromised data can cost thousands of dollars to company. In the last section, we compiled LDAP authentication module into the Apache build to provide a Authentication mechanism. However HTTP traffic is very insecure, and all data is transferred in clear text - meaning, the LDAP authentication (userid/passwd) will be transmitted as clear text as well. This creates a problem. Anyone can sniff these userid/passwd and gain access to DAV store. To prevent this we have to encrypt HTTP traffic, essentially HTTP + SSL or HTTPS. Anything transferred over HTTPS is encrypted, so the LDAP userid/passwd can not be easily deciphered. HTTPS runs on port 443. The resulting build from the last section's compilation process will have Apache to listen to both port 80 (normal HTTP) and 443 (HTTPS). If you are just going to use this server for DAV, then I will highly suggest that you close port 80. In this section of the HOWTO I will provide some information regarding SSL and maintaining SSL on a Apache HTTP server.

6.1. Introduction to SSL

SSL (Secure Socket Layer) is a protocol layer that exists between the Network Layer and Application layer. As the name suggest SSL provides a mechanism for encrypting all kinds of traffic - LDAP, POP, IMAP and most importantly HTTP.

The following is a over-simplified structure of the layers involved in SSL.

	+-------------------------------------------+
	|   LDAP   |    HTTP    |   POP   |   IMAP  |
	+-------------------------------------------+
	|                   SSL                     |
	+-------------------------------------------+
	|               Network Layer               |
	+-------------------------------------------+
	

6.1.1. Encryption algorithms used in SSL

There are three kinds of cryptographic techniques used in SSL: Public-Private Key, Symmetric Key, and Digital Signature.

Public-Private Key Crytography - Initiating SSL connection: In this algorithm, encryption and decryption is performed using a pair of private and public keys. The Web-server holds the private Key, and sends the Public key to the client in the Certificate.

  1. The client request content from the Web Server using HTTPS.

  2. The web server responds with a Digital Certificate which includes the server's public key.

  3. The client checks to see if the certificate has expired.

  4. Then the client checks if the Certificate Authority that signed the certificate, is a trusted authority listed in the browser. This explains why we need to get a certificate from a a trusted CA.

  5. The client then checks to see if the Fully Qualified Domain Name (FQDN) of the web server matches the Comman Name (CN) on the certificate?

  6. If everything is successful the SSL connection is initiated.

NoteNote:
 

Anything encrypted with Private Key can only be decrypted by using the Public Key. Similarly anything encrypted using the Public Key can only be decrypted using the Private Key. There is a common mis-conception that only the Public Key is used for encryption and Private Key is used for decryption. This is not case. Any key can be used for encryption/decryption. However if one key is used for encryption then the other key must be used for decryption. e.g. A message can not encrypted and then decrypted using only the Public Key.

Using Private Key to encrypt and a Public Key to decrypt ensures the integrity of the sender (owner of the Private Key) to the recipients. Using Public Key to encrypt and a Private Key to decrypt ensures that only the inteded recipient (owner of the Private Key) will have access to the data.(i.e. only the person who holds the Private Key will be able to decipher the message).

Symmetric Cryptography - Actual transmission of data: After the SSL connection has been established, Symmetric cryptography is used for encrypting data as it uses less CPU cycles. In symmetric cryptography the data can be encrypted and decrypted using the same key. The Key for symmetric cryptography is exchanged during the initiation process, using Public Key Cryptography.

Message Digest The server uses message digest algoritm such as HMAC, SHA-1, MD5 to verify the integrity of the transferred data.

6.1.2. Ensuring Authenticity and Integrity

Encryption Process


            Sender's                 Receiver's
           PrivateKey                 PublicKey
          ,-.                     ,-.
         (   )..........         (   )..........
          `-' ''''|'|'||          `-' ''''''''||
                  | |                    |
                  | |                    |
   .----------.   | |    .----------.    |     .----------.
   |          |   V |    |          |    V     |          |
   |Clear Text|--------->|CipherText|--------->|CipherText|
   |          |  Step1   |    1     |  Step2   |    2     |\
   `----------'     |    `----------'          `----------' \    __
         |          |                                        \   [_'
         |          |                                   step5 \   |
         |Step3     |                                       __  --|--
         |          |                                  _.--'      |
         V          |                            _..-''          / \
    .---------.     |    .---------.       _..-''              Receiver
    |  SHA 1  |     V    | Digital | _..-''
    |MsgDigest|--------->|Signature|'            _
    `---------'  Step4   `---------'         _  (_)
        _____ ____   ____  ____ _   _ ____ _| |_ _  ___  ____
       | ___ |  _ \ / ___)/ ___) | | |  _ (_   _) |/ _ \|  _ \
       | ____| | | ( (___| |   | |_| | |_| || |_| | |_| | | | |
       |_____)_| |_|\____)_|    \__  |  __/  \__)_|\___/|_| |_|
                               (____/|_|
	

  • Step1: In this step the Original "Clear Text" message is encrypted using the Sender's Private Key, which results in Cipher Text 1. This ensures the Authenticity of the sender.

  • Step2: In this step the "CipherText 1" is encrypted using Receiver's Public Key resulting in "CipherText 2". This will ensure the Authenticity of the Receiver i.e. only the Receiver can decipher the Messsage using his Private Key.

  • Step3: Here the SHA1 Message Digest of the "Clear Text" is created.

  • Step4: SHA1 Message Digest is then encrypted using Sender's Private Key resulting in the Digital Signature of the "ClearText". This Digital Signature can be used by the receiver to ensure the Integrity of the message and authenticity of the Sender.

  • Step5: The "Digital Signature" and the "CipherText 2" are then send to the Receiver.

Decryption Process


           Receiver's               Sender's
           PrivateKey               PublicKey
         ,-.                     ,-.
        (   )..........         (   )..........
         `-' ''''''''||          `-' '''''''|||
                |                      |    |
                |                      |    |
  .----------.  |       .----------.   |    | .----------.
  |          |  V       |          |   V    | |          |       .---#1----.
  |CipherText|--------->|CipherText|--------->|ClearText |------>|  SHA 1  |
  |    2     |  Step1   |    1     |  Step2 | |          | Step3 |MsgDigest|
  `----------'          `----------'        | `----------'       `---------'
                                            |                        ||
                                            |                        ||Step5
                                            |                        ||
                                            |                        ||
                               .---------.  |                    .---------.
                               | Digital |  V                    |  SHA 1  |
                               |Signature|---------------------->|MsgDigest|
                 _             `---------'  Step4     _          `---#2----'
                | |                               _  (_)
              __| |_____  ____  ____ _   _ ____ _| |_ _  ___  ____
             / _  | ___ |/ ___)/ ___) | | |  _ (_   _) |/ _ \|  _ \
            ( (_| | ____( (___| |   | |_| | |_| || |_| | |_| | | | |
             \____|_____)\____)_|    \__  |  __/  \__)_|\___/|_| |_|
                                    (____/|_|

  • Step1: In this step the "CipherText 2" message is decrypted using the Receiver's Private Key, which results in Cipher Text 1.

  • Step2: In this step the "CipherText 1" is decrypted using Sender's Public Key resulting in "ClearText".

  • Step3: Here the SHA1 Message Digest of the "Clear Text" is created.

  • Step4: The "Digital Signature" is then decrypted using Sender's Public Key, resulting the "SHA 1 MSG Digest".

  • Step5: The "SHA1 MsgDigest #1" is then compared against "SHA1 MsgDigest #2". If they are equal, the data was not modified during transmission, and the integrity of the Original "Clear Text" has been maintained

6.2. Test Certificates

While compiling Apache we created a test certificate. We used the makefile provided by mod_ssl to create this custom Certificate. We used the command:
# make certificate TYPE=custom

This certificate can be used for testing purposes.

6.3. Certificates for Production use

For production use you will need a certificate from a Certificate Authority (hereafter CA). Certificate Authorities are certificate vendors, who are listed as a Trusted CA in the user's browser. As mentioned in the Encryption Algorithms section, if the CA is not listed as a trusted authority, your user will get a warning message when trying to connect to a secure location.

Similarly the test certificates will also cause a warning message to appear on the user's browser.

6.4. How to generate a CSR

CSR or Certificate Signing Request must be sent to the trusted CA for signing. This section discusses howto create a CSR, and send it to the CA of your choice. # openssl req command can be used to a CSR as follows:


# cd /usr/local/apache/conf/
# /usr/local/ssl/bin/openssl req -new -nodes -keyout private.key -out public.csr
Generating a 1024 bit RSA private key
............++++++
....++++++
writing new private key to 'private.key'
-----
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) [AU]:US
State or Province Name (full name) [Some-State]:California
Locality Name (eg, city) []:San Jose
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Seagate 
Organizational Unit Name (eg, section) []:Global Client Server
Common Name (eg, YOUR name) []:xml.seagate.com
Email Address []:saqib@seagate.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:badpassword
An optional company name []:

Note"PRNG not seeded"
 

If you do not have /dev/random on your system you will get a "PRNG not seeded" error message. In that case you can use the following command:

# /usr/local/ssl/bin/openssl req -rand some_file.ext -new -nodes -keyout private.key -out public.csr 

Replace some_file.ext with the name of a existing file on your file system. Any file can be specified. Openssl will use that file to generate the seed

Solaris 9 comes with /dev/random. However on Solaris you might have to install the 112438 patch to get the /dev/random

At this point you will be asked several questions about your server to generate the Certificate Singning Request

Note: Your Common Name (CN) is the Fully Qualified DNS (FQDN) name of your webserver e.g. dav.server.com . If you put in anything else, it will NOT work. Remember the password that you use, for future reference.

Once the process is complete, you will have private.key and a public.csr . You will need to submit the public.csr to the Certification Authority. At this pointe the public.key is not encrypted. To encrypt:

 # mv private.key private.key.unecrpyted
# /usr/local/ssl/bin/openssl rsa -in private.key.unecrpyted -des3 -out private.key

6.5. Installing Server Private Key, and Server Certificate

Once the Certification Authority processes your request, they will send an encoded certificate (Digital Certificate) back to you. The Digital Certificate is in the format defined by X.509 v3. The following shows the structure of a typical X509 v3 Digital Certificate

6.5.1. Verifying a Digital Certificate

To verify a X.509 Certificate use the following command

# openssl verify server.crt
server.crt: OK 

Where server.crt is the name of the file that contains the Digital Certificate

6.5.2. Viewing the contents of a Digital Certificate

The contents of a Digital Certificate can be viewed by using the # openssl x509 command as follows:

# openssl x509 -text -in server.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 312312312 (0x0)
        Signature Algorithm: md5WithRSAEncryption
	Issuer: C=US, O=GTE Corporation, CN=GTE CyberTrust Root
        Validity
            Not Before: Feb  8 03:25:50 2000 GMT
            Not After : Feb  8 03:25:50 2001 GMT
	    Subject: C=US, ST=New York, L=Pelham, O=xml-dev, OU=web, CN=www.xml-dev.com/Email=saqib@xml-dev.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
		............
		............
                Exponent: 65537 (0x10001)
    Signature Algorithm: md5WithRSAEncryption
    	............
	............

	

6.5.3. Modifying the httpd.conf to Install the Certificates

You will need to place this certificate on the server, and tell Apache where to find it.

For this example, the Private Key is placed in the /usr/local/apache2/conf/ssl.key/ directory, and the Sever Certificate is placed in the /usr/local/apache2/conf/ssl.crt/.

Copy the file received from the Certification to a file called server.crt in the /usr/local/apache2/conf/ssl.crt/.

And place the private.key generated in the previous step in the /usr/local/apache2/conf/ssl.key/

Then modify the /usr/local/apache2/conf/ssl.conf to point to the correct Private Key and Server Certificate files:


#   Server Certificate:
#   Point SSLCertificateFile at a PEM encoded certificate.  If
#   the certificate is encrypted, then you will be prompted for a
#   pass phrase.  Note that a kill -HUP will prompt again.  Keep
#   in mind that if you have both an RSA and a DSA certificate you
#   can configure both in parallel (to also allow the use of DSA
#   ciphers, etc.)
SSLCertificateFile /usr/local/apache2/conf/ssl.crt/server.crt
#SSLCertificateFile /usr/local/apache2/conf/ssl.crt/server-dsa.crt

#   Server Private Key:
#   If the key is not combined with the certificate, use this
#   directive to point at the key file.  Keep in mind that if
#   you've both a RSA and a DSA private key you can configure
#   both in parallel (to also allow the use of DSA ciphers, etc.)
SSLCertificateKeyFile /usr/local/apache2/conf/ssl.key/private.key
#SSLCertificateKeyFile /usr/local/apache2/conf/ssl.key/server-dsa.key

6.6. Removing passphrase from the RSA Private Key

RSA Private Key stored on the webserver is usually encrypted, and you need a passphrase to parse the file. That is why you are prompted for a passphrase when start Apache with modssl:


# apachectl startssl
Apache/1.3.23 mod_ssl/2.8.6 (Pass Phrase Dialog)
Some of your private key files are encrypted for security reasons.
In order to read them you have to provide us with the pass phrases.
Server your.server.dom:443 (RSA)
Enter pass phrase:

Encrypting the RSA Private Key is very important. If a cracker gets hold of your "Unencrypted RSA Private Key" he/she can easily impersonate your webserver. If the Key is encrypted, the cracker can not do anything without brute forcing the passphrase. Use of a strong (ie: long) passphrase is encouraged.

However encrypting the Key can sometimes be nuisance, since you will be prompted for a passphrase everytime you start the web-server. Especially if you are using rc scripts to start the webserver at boot time. The prompt for a passphrase will stop the boot process, waiting for your input.

You can get rid of the passphrase prompt easily by decrypting the Key. However make sure that no one can hold of this Key. I would recommend Hardening and Securing guidelines be followed before decrypting the Key on the webserver.

To decrypt the Key:

First make a copy of the encrypted key

# cp server.key server.key.cryp

Then re-write the key with encryption. You will be prompted for the original encrypted Key passphrase

# /usr/local/ssl/bin/openssl rsa -in server.key.cryp -out server.key
read RSA key
Enter PEM pass phrase:
writing RSA key

One way to secure the decrypted Private Key is to make readable only by the root:

# chmod 400 server.key

6.7. SSL Performance Tuning

6.7.1. Inter Process SSL Session Cache

Apache uses a multi-process model, in which all the request are NOT handled by the same process. This causes the SSL Session Information to be lost when a Client makes multiple requests. Multiple SSL HandShakes causes lot of overhead on the webserver and the client. To avoid this, SSL Session Information must be stored in a inter-process Session Cache, allowing all the processes to have access to to handshake information. SSLSessionCache Directive the in /usr/local/apache2/conf/ssl.conf file can be used to specify the location of the SSL Session Cache:


SSLSessionCache        shmht:logs/ssl_scache(512000)
#SSLSessionCache        shmcb:logs/ssl_scache(512000)
#SSLSessionCache         dbm:logs/ssl_scache
SSLSessionCacheTimeout  300

Using dbm:logs/ssl_scache creates the Cache as DBM hashfile on the local disk.

Using shmht:logs/ssl_scache(512000) creates the Cache in Shared Memory Segment

Noteshmht vs shmcb
 

shmht: uses a Hash Table to Cache the SSL HandShake Information in the Shared Memory

shmht: uses a Cyclic Buffer to Cache the SSL HandShake Informationin the Shared Memory

NoteNote:
 

Not all platforms/OS support creation of Hash table in the Shared Memory. So dbm:logs/ssl_scache must be used instead

6.7.2. Verifying SSLSession Cache

To verify if the SSLSessionCache is working properly, you can use the openssl utility with the -reconnect as follows:


# openssl s_client -connect your.server.dom:443 -state  -reconnect

CONNECTED(00000003)
.......
.......
Reused, TLSv1/SSLv3, Cipher is EDH-RSA-DES-CBC3-SHA
SSL-Session:
.....
Reused, TLSv1/SSLv3, Cipher is EDH-RSA-DES-CBC3-SHA
SSL-Session:
.....
Reused, TLSv1/SSLv3, Cipher is EDH-RSA-DES-CBC3-SHA
SSL-Session:
.....
Reused, TLSv1/SSLv3, Cipher is EDH-RSA-DES-CBC3-SHA
SSL-Session:
.....
Reused, TLSv1/SSLv3, Cipher is EDH-RSA-DES-CBC3-SHA
SSL-Session:
.....

-reconnect forces the s_client to connect to the server 5 times using the same SSL session ID. You should see 5 attempts of Reusing the same Session-ID as shown above.