Chapter 7. SSL/TLS

This chapter gives you a brief introduction to the concepts behind SSL and provides a step-by-step guide on how to install and configure the mod_ssl Apache module. You will learn how to solve common SSL-related issues as well as how to create, sign, and install your server keys and certificates.

What Is SSL?

The SSL/TLS family of protocols (Secure Sockets Layer/Transport Layer Security) is used to secure communications between two end-points, usually a server and a client. When a browser accesses a web server using the HTTP protocol, the data is transmitted in the open. A third party that is able to intercept that conversation at one point in the network will be able to access and even modify the data being transmitted. A number of applications, such as making electronic payments over the Web and accessing sensitive corporate data, require a level of security that is not available from the HTTP protocol.

The HTTPS protocol or Secure HTTP was developed to address those concerns. It improves the security of the HTTP protocol by providing

  • Confidentiality: Encrypting the data so it cannot be read by others

  • Integrity: Assuring the data was not modified intransit

  • Authentication: Verifying the identity of the server (or client)

HTTPS encapsulates HTTP over the SSL/TLS family of protocols (Secure Sockets Layer/Transport Layer Security), which the rest of the chapters simply refer to as “SSL.” The default port for the HTTPS protocol is 443, and HTTPS URLs are prefixed with https://.

As you probably have experienced, most browsers provide visual feedback, usually in the form of a padlock next to the address bar, when connected to a site using the HTTPS protocol.

How Does SSL Work?

When the user types https://www.example.com, the browser recognizes the https:// prefix and knows that it must use the HTTPS protocol to connect to the server. When no port is specified, the default HTTPS port, 443, is used.

Once a connection is established, the client requests the server certificate. A certificate is an electronic piece of data that describes the identity of an end-point in the SSL communication, and is explained later in the chapter. The certificate is then tested for validity.

Depending on whether the validation process succeeds, the connection process will continue or the user will be informed and asked for confirmation. Optionally, the client can also provide a certificate, and the server will follow a similar validation process.

Once the identity of the server (and of the client, if necessary) has been established, the next step is to agree on a common encryption key. For that purpose, the public keys of each party are used in an algorithm to securely agree on a symmetric key. Later in this chapter, you will learn more about encryption keys and how to generate them. The agreement process is secure against eavesdroppers because when you encrypt information with the server’s public key, only the server will be able to decrypt it.

The handshake phase has concluded and now the client and server can proceed with the regular exchange of information. At this point, most browsers will provide the user with visual feedback that the connection is secure, usually with a closed padlock.

Compiling OpenSSL

# gunzip < openssl*.tar.gz | tar xvf -
# cd openssl*
# ./config --prefix=/usr/local/ssl --
openssldir=/usr/local/ssl/openssl
# make
# make install

mod_ssl is the Apache module that implements HTTPS. The OpenSSL project provides the base cryptographic libraries used by mod_ssl, as well as command-line utilities for creating and manipulating server certificates.

You can download a Windows binary build from the binaries section of the OpenSSL website at http://www.openssl.org. Most modern Unix-like systems include OpenSSL by default, or you can install it using the system package management tools. If that is not the case, or you require a newer version than the one available in your system, you can download the OpenSSL source code and install it as shown at the beginning of this section. The rest of this chapter assumes that you installed OpenSSL in /usr/local/ssl.

The openssl command line tool is included as part of the OpenSSL distribution and will be placed in /usr/local/ssl/bin/.

Encryption Keys

Encryption is the process of converting an existing message, the plain-text, into a new, encrypted message that will be completely unintelligible to an eavesdropper. Decryption is the reverse process, which transforms the encrypted message into the original plain-text.

Usually encryption and decryption processes involve an additional piece of information: a key. If both sender and receiver share the same key, the process is referred to as symmetric cryptography. If sender and receiver have different, complementary keys, the process is called asymmetric or public key cryptography. In public key cryptography, there is a pair of keys: one public and the other private. The public key can be made freely available, whereas the owner keeps the private key secret. These two keys are complementary; a message encrypted with one of the keys can be decrypted only by the other key.

Creating a Key Pair

# ./usr/local/ssl/bin/openssl genrsa -rand
file1:file2:file3 
   -out www.example.com.key 1024
625152 semi-random bytes loaded
Generating RSA private key, 1024 bit long modulus
.....++++++
.........................++++++
e is 65537 (0x10001)

The example shows how to create a key pair using the openssl command line tool.

genrsa indicates to OpenSSL that you want to generate a key pair using the RSA algorithm.

The rand switch is used to provide OpenSSL with random data to ensure that the generated keys are unique and unpredictable. Substitute file1, file2, and so on, for the path to several large, relatively random files for this purpose (such as a kernel image, compressed log files, and so on). This switch is not necessary on Windows because the random data is automatically generated by other means.

The out switch indicates where to store the results.

1024 indicates the number of bits of the generated key.

Creating a Password-protected Key Pair

# ./usr/local/ssl/bin/openssl genrsa –des3 -rand
file1:file2:file3 
   -out www.example.com.key 1024

In this case, the des3 option indicates that the private key should be encrypted and protected by a pass phrase, and you will be asked to provide it. You will be asked for it whenever you want to start the server as shown in the SSLPassPhraseDialog section.

Remove the Password from a Key

# ./usr/local/ssl/bin/openssl rsa -in
www.example.com.key 
    -out www.example.com.key.unsecure

You can choose to unprotect the key by issuing this command. This has some security implications; please see the SSLPassPhraseDialog section.

Certificates

Public key cryptography can be used to digitally sign messages. For example, if you encrypt a message with your secret key, the receiver can guarantee it came from you by simply decrypting it with your public key. But there is a missing step. How can you authenticate people or entities that you have never met in person? In other words, how can you check who a particular public key really belongs to?

The solution involves a trusted third party, the Certification Authority (CA). The CA can be internal to a company or university, or a commercial entity that provides certification services to companies conducting business over the Internet. A CA issues certificates, which are electronic documents that tie a particular public key to information about its owner, such as name and address. The certificates are digitally signed with the CA private key, which certifies that the information is correct.

For this whole process to work, you must trust the CA that issued the certificate. You also need to be able to obtain the public key for that particular CA, which is provided by that CA’s so-called root certificate. Most popular browsers, such as Internet Explorer, Firefox, and Safari, bundle a number of root certificates for commonly trusted certification authorities. This allows the browsers to recognize and validate a great number of websites without the user’s manual intervention.

Creating a Certificate Signing Request

# ./usr/local/ssl/bin/openssl req -new -key
www.example.com.key -out www.example.com.csr

To get a certificate issued by a CA, you must first submit what is called a certificate signing request. As explained earlier, the request contains data about the entity requesting the certificate and the public key. This command creates such a request. You will be prompted to provide several pieces of information, as shown in Listing 7.1.

Example 7.1. Using openssl to Generate a Certificate Request

Using configuration from
/usr/local/ssl/openssl/openssl.cnf
Enter PEM pass phrase:
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]:CA
Locality Name (eg, city) []: San Francisco
Organization Name (eg, company) [Internet Widgits
Pty Ltd]:.
Organizational Unit Name (eg, section) []:.
Common Name (eg, YOUR name) []:www.example.com
Email Address []:[email protected]
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

It is important that the Common Name field entry matches the address that visitors to your website will type in their browsers. This is one of the checks that the browser will perform for the remote server certificate. If the names differ, a warning indicating the mismatch will be issued to the user.

You can now submit the certificate signing request file with a CA for processing. The exact process will vary for each entity. You can find an extensive list of CAs at http://www.pki-page.org/. Verisign, Thawte, GeoTrust, and Equifax are well-known commercial CAs. There are also a number of community CAs, such as http://www.cacert.org/.

Showing the Contents of a Certificate Signing Request

# ./usr/local/ssl/bin/openssl req -noout 
    -text  -in www.example.com.csr

Certificate signing requests are stored in a special, compact form. This command will show the contents of the certificate stored in www.example.com.csr in a human-readable form. As mentioned earlier in the chapter, the certificate will contain information about the entity requesting it, the contents of the public key, and a signature made with the private key.

Creating a Self-signed Certificate

In addition to submitting your CSR to a commercial CA, you can always create a self-signed certificate. That is, you can be both the issuer and the subject of the certificate. Although this is not very useful for a commercial website, it will enable you to test your installation of mod_ssl or to have a secure web server while you wait for the official certificate from the CA.

# ./usr/local/ssl/bin/openssl x509 -req 
-days 30 -in www.example.com.csr -signkey 
www.example.com.key -out www.example.com.cert

You now need to copy your certificate www.example.com.cert (either the one returned by the CA or your self-signed one) to /usr/local/ssl/openssl/certs/ and your key to /usr/local/ssl/openssl/private/.

Protect your key file by issuing the following command:

# chmod 400 www.example.com.key

Compiling SSL Support in Apache 1.3

$ gunzip < mod_ssl-2.8.23-1.3.33.tar.gz | tar xvf -
$ gunzip < apache_1.3.33.tar.gz | tar xvf -
$ cd mod_ssl-2.8.23-1.3.33
$ ./configure --with-apache=../apache_1.3.33
$ cd ../apache_1.3.x
$ SSL_BASE=/usr/local/ssl/ ./configure --enable-module=ssl --prefix=/usr/local/apache
$ make
# make install

mod_ssl is a very popular module that provides SSL support both for Apache 1.3 and 2.x. Due to historical reasons related to export restrictions on cryptography, the Apache 1.3 version is distributed separately from the server. What is more, the Apache 1.3 source code needs to be patched in order to support mod_ssl. This is done as part of the mod_ssl build process, shown in the previous listing. The example builds Apache 1.3.33 and mod_ssl 2.8.23 and assumes both source directories are located at the same level. The --with-apache command line option points to the location of the Apache 1.3 source code directory, which is later recompiled to include mod_ssl support.

If you are building against the system OpenSSL library, you can remove SSL_BASE=/usr/local/ssl/ from the Apache configure step.

If Apache already contains the EAPI patches and loadable module support, you can use the common APXS build mechanism described in Chapter 1. This is useful, for example, when upgrading an existing mod_ssl installation.

If you try to start Apache now, you will get an error stating that it is unable to read the server certificate. Refer to previous sections for details on how to create your server certificate and keys, and to the “Minimal Apache Configuration” section later in the chapter for details on how to bootstrap your server. Optionally, mod_ssl can create a server certificate for testing purposes during the build process. To do so, you can do a make certificate before the make install.

Compiling SSL Support in Apache 2.x

Apache 2 was released after the US cryptography export regulations were relaxed, so it includes mod_ssl alongside the rest of the modules.

If you are building Apache from source, you can enable mod_ssl at build time with the --enable-ssl configure option. If you are also building OpenSSL from source, you will need to add --with-ssl=/usr/local/ssl/openssl.

Minimal Apache Configuration

Once you have generated your keys and certificates, either self-signed or certified by a third-party CA, the next step is to configure Apache. As part of the installation process, mod_ssl creates a sample SSL configuration. Apache 1.3 adds it to the default httpd.conf file and Apache 2.0 includes a separate ssl.conf file, referenced by an Include directive in httpd.conf. The myriad configuration options can be confusing, but in reality there are only a few options that you need to configure, as shown in the following listing:

Listen 80
Listen 443
<VirtualHost _default_:443>
ServerName www.example.com
SSLEngine on
SSLCertificateFile 
/usr/local/ssl/openssl/certs/www.example.com.cert
SSLCertificateKeyFile 
/usr/local/ssl/openssl/certs/www.example.com.key
</VirtualHost>

One of the Listen directives tells Apache to listen at the default HTTPS port, 443. SSLEngine On enables SSL for that particular host and the SSLCertificateFile and SSLCertificateKeyFile directives point to the certificate and private key.

Starting Apache with SSL Support

Once mod_ssl has been installed and configured, you can start Apache with

apachectl start

If you are using the default SSL configuration files, or the ones supplied by your vendor, the SSL directives will likely be surrounded by an <IfDefine SSL> block.

You can either remove those blocks or start Apache with

apachectl startssl

which will pass the -DSSL flag to the server binary and enable the SSL configuration. This only needs to be done in Apache 1.3 and 2.0, as Apache 2.2 no longer includes a startssl option, and SSL directives are not treated any differently than other directives.

If you protected your private key with a pass phrase, you will need to enter it now. If you installed Apache as a regular user, it may have been configured to listen by default at port 8443. As explained in Chapter 2, port 443 is a privileged port and is only accessible by the superuser.

You can test the installation by accessing your server as https://www.example.com (or https://www.example.com:8443 as just explained).

SSLPassPhraseDialog

SSLPassPhraseDialog builtin

If you have password protected your server’s private key, you will be asked to provide the appropriate pass phrase at startup time. You can control this behavior with SSLPassPhraseDialog. Its default value, builtin, means that Apache will prompt you directly every time the server is started. You can choose not to protect the key. This is convenient because you will not need to manually enter the pass phrase during reboots, but if the server is compromised, the key will be as well. You can also configure SSLPassPhraseDialog to call an external program, which will provide the pass phrase on its standard input when called from Apache.

SSLPassPhraseDialog exec:/usr/local/apache/bin/sslpp

If you write the script correctly, this can offer a bit more security than leaving the key unprotected (but not much either).

Improving SSL Performance

The algorithms involved in SSL are CPU-intensive and may slow down your server significantly, especially if you have many simultaneous client connections. The handshake phase can also impose a delay in the request. There are a number of options you can consider to improve the responsiveness of your site.

Make sure you have enabled session caching. This will speed up multiple connections from the same client. If you are using a cluster of SSL servers, you may want to use distcache, so the connection data can be cached even if the client connects to multiple servers in the cluster. Apache 2.2 includes support for distcache out of the box. You can learn more about this project at http://www.distcache.org.

Consider having a dedicated machine just for SSL processing. Depending on your needs, this may be a commercial hardware load balancer or a dedicated machine running a reverse proxy (a web server that relies on requests to other web servers on behalf of the client). This allows for optimizations in the Apache and OS configuration that would not be possible if the machine is also serving other purposes, such as running PHP, Tomcat, and MySQL. A reverse proxy can provide additional benefits such as load-balancing and single sign-on, possibly using client certificates, across a number of backend websites. See Chapter 10 for details.

Finally, you can install a crypto-card, a piece of hardware that is designed to offload the server from performing most of the SSL processing. Apache 2.2 provides support for this functionality; take a look at the SSLCryptoDevice directive.

Forcing All Content to Be Served Using SSL

<VirtualHost 192.168.200.4:80>
    ServerName private.example.com
    Redirect / https://private.example.com/
</Virtualhost>

If you have a particular website that you want only served under SSL, you can use a Redirect inside a <VirtualHost> container that listens for HTTP requests and redirects them to your secure website, as shown in the example. This is useful because users will not always remember to type https:// instead of http://.

SSL and Name-based SSL Virtual Hosts

A common question from mod_ssl users is whether it is possible to have several SSL-enabled name-based virtual hosts. The short answer is no. The problem is that name-based virtual hosting relies on the information provided by the client in the Host: header of the HTTP request, since all name-based virtual hosts are sharing the same IP address. But the SSL connection takes place at the TCP level, before the HTTP request can be sent. Thus, the server is not able to determine at the time of connection which virtual host the client wants to connect to and, hence, which certificate and key to use. There is indeed a specification (RFC 2817), which allows upgrading an existing HTTP connection to HTTPS. That would get around this issue, but at the time of this writing it is not implemented by any mainstream browser. Apache 2.2’s mod_ssl module implements support for RFC 2817, as does mod_nw_ssl, the Netware Apache SSL module.

Using Apache Auth Modules with SSL

SSLOptions +FakeBasicAuth

When this option is enabled, the Subject Distinguished Name (DN) of the client certificate is translated into an HTTP basic authorization username. This means that the standard Apache authentication methods seen in Chapter 6 can be used for access control. To those authentication modules, it looks as if the user has successfully provided a valid username and password. You will need to modify certain settings in your user databases; see the SSLOptions directive manual page for details.

Warning Messages When Accessing an SSL-enabled Website

Sometimes, when accessing an SSL-enabled website, users get a warning popup window, telling that something is not quite right with the website. These are some of the most common causes:

  • The certificate has expired. Commercial certificates are usually valid for a limited period of time, after which they expire.

  • The domain in the certificate does not match the domain. This will happen if the certificate was issued for a different website.

  • The certificate has been signed by a Certificate Authority that is unknown or not trusted by the browser. This can happen, for example, if you are using a self-signed certificate for testing purposes.

Creating Client Certificates

When using client certificate authorization, the server will verify during the handshake phase that the client presents a valid certificate and that it has been signed by a CA that the server trusts. Although cumbersome to manage and distribute, client certificates are useful for protecting access to company websites or web services. They tend to be more secure than user names and passwords, as they cannot be guessed or intercepted.

If you want to be your own CA, the first step is to create your root CA. You can do so directly using the ca argument to the command line tool, or using the convenient CA.pl wrapper script bundled with openssl. To create a new certificate authority, you can issue the following command:

CA.pl -newca

The script will now create a private key, server certificate, and so on, and create a directory structure (demoCA) that contains the generated files.

You can now create a CSR and sign your certificate with

CA.pl -newreq
CA.pl -signreq

The generated CA file will be in PEM format. To convert it to another format that makes it more convenient to import in browsers, execute the following command:

CA.pl -pkcs12

The exact method to import the certificate in the end-user machine varies depending on the browser type. Internet Explorer users can simply click on the certificate file and follow the instructions.

Authentication Using Client Certificates

SSLVerifyClient require
SSLCACertificateFile 
    /usr/local/ssl/openssl/certs/ca.crt

Once you have installed certificates in your clients, you need to instruct Apache to enable SSL validation for clients. This SSLVerifyClient directive requires clients to provide a valid client certificate to be able to connect. The SSLCACertificateFile provides the path to the file containing the trusted CA certificate that will be used to verify the client certificate validity.

Alternatives to mod_ssl

There are a number of alternatives to mod_ssl. For Apache 1.3, you can use Apache-SSL, the module from which mod_ssl originally derived. You can find it at http://www.apache-ssl.org. A number of commercial vendors, such as IBM, include their own SSL modules with their Apache-based web server packages, usually based on toolkits other than OpenSSL.

Finally, you can use a standalone utility, such as stunnel, to proxy SSL connections to an existing Apache server as described at http://www.stunnel.org. Though not as flexible as mod_ssl, it can be a handy tool for certain scenarios where it is not possible or desirable to modify a running server configuration.

Testing SSL-enabled Websites from the Command Line

# openssl s_client -connect www.ibm.com:443

You can use openssl or other SSL based tools, such as stunnel (http://www.stunnel.org), to test secure web servers. For example, you can use this command to connect to IBM’s website using HTTPS. It will display details about the SSL protocol and server certificate for the connection. You can then issue a GET / HTTP/1.0 command and press Enter and get a response back, just as if you had used Telnet to connect to a regular web server on port 80 to issue HTTP requests by hand, as shown in Chapter 1.

Working Around Buggy SSL Implementations

SetEnvIf User-Agent ".*MSIE.*" nokeepalive 
    ssl-unclean-shutdown downgrade-1.0 
force-response-1.0

Some browsers (or servers, if operating in a reverse-proxy configuration) have known problems with specific versions of the SSL protocol or certain features. Certain environment variables can be set to force specific behaviors. This is especially useful if you have a commercial site and need to support older browsers. For example, this configuration snippet is included in the default configuration file and is a workaround for bugs in the SSL implementation of Internet Explorer browsers. If the client browser contains the MSIE string then no keep-alive support will be enabled and an earlier version of the HTTP protocol will be used.

Complex Access Control with mod_ssl

SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)-/ 
and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." 
and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"}
and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 
and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 ) 
or %{REMOTE_ADDR} =~ m/^192.76.162.[0-9]+$/

This example shows how to use the SSLRequire directive to implement arbitrary access restrictions based on a number of parameters. As it happens with mod_rewrite, SSLRequire can be complex to configure, but it provides nearly unlimited possibilities. The configuration snippet above checks that

  • The SSL connection does not use an export (weak) cipher or a NULL cipher, the certificate has been issued by a particular CA and for a particular group, and the access takes place during workdays (Monday to Friday) and working hours (8:00 a.m. to 8:00 p.m.).

  • The client comes from an internal, trusted network (as specified by REMOTE_ADDR).

Please refer to the SSLRequire documentation for in-depth information.

Related Chapters

If you are using Apache as a reverse proxy, SSL-related connection and certificate information for clients is not available to the backend servers. How to solve this issue is discussed in detail in Chapter 10 .

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.24.106