Nuts and Bolts Apache SSL 
 

Setting up SSL connections on Apache 2

Safe Service

To spoil the day for lurking data thieves, Apache administrators only need three additional directives – and a handful of commands. By Tim Schürmann

An attacker who captures the credentials for a blog can both spy on the user and break into the blog. By breaking into the blog, that attacker has actually broken into the web server. As an administrator, you should take all possible steps to secure sensitive areas of a website. Transport Layer Security (TLS) lets the web server and browser conduct their communication over an encrypted connection. TLS is a later version of Secure Sockets Layer (SSL), and this kind of connection is often still called an SSL connection. The box titled "Tap-Proof" shows how to set up an encrypted connection.

SSL actually forms a separate intermediate layer in the protocol stack but is typically seen as belonging to the transport or TCP layer.
Figure 1: SSL actually forms a separate intermediate layer in the protocol stack but is typically seen as belonging to the transport or TCP layer.

The Apache web server module mod_ssl takes care of encryption via SSL and TLS. mod_ssl has been included in the package since Apache version 2, and it relies on the OpenSSL package [3]. The OpenSSL libraries implement the SSL protocol, thus performing the actual encryption. OpenSSL is included with most Linux distributions out of the box. Windows users should go for the Apache binary package with built-in OpenSSL. The file is named -openssl and can be found on the Apache Foundation download page [4] in Other files, below the binaries/win32 directories. In CentOS 6.4, the mod_ssl module is not part of the Apache2 package; you have to install the mod_ssl package explicitly.

Face Check

So that browsers know who is at the other end of an encrypted connection, the web server sends a certificate. Administrators can quickly create a certificate using the openssl command-line utility from the OpenSSL package. Windows users of the Apache binary package can find it in the bin directory of their Apache installations. Certificates are based on asymmetric cryptography (public key cryptography), in which each party has two keys. To create a certificate, you must first generate a private key for the server:

openssl genrsa -aes256 -out privaterschluessel.pem 2048

The key length is 2048 bits in this case. For security reasons, the command encrypts the key using the AES256 method, which is why you need to enter a passphrase (i.e., a longer password). Armed with the private key and the passphrase, you can then generate a certificate:

openssl req -new -x509 -days 365 -key privatekey.pem -out certificate.pem

On Windows, you must explicitly reference the OpenSSL configuration file:

openssl req -config ..\conf\openssl.cnf -new -x509 -days 365 -key privatekey.pem -out certificate.pem

In any case, the command creates a new certificate (-new), whose structure follows the X.509 standard (-X509), is valid for 365 days, and ends up in the certificate.pem file. After calling the command, you are asked many questions. Even if you say yes to all the defaults by pressing the Enter key, be sure to specify the domain name under which the secured HTTPS pages are accessible when prompted for the Common Name. Otherwise, browsers will later refuse the connection. If the website is https://login.example.com, the answer to the Common Name prompt is login.example.com (Figure 2). Keep the certificate, the private key, and the passphrase somewhere safe; better yet, memorize the passphrase.

The Common Name is not your own name but the domain name.
Figure 2: The Common Name is not your own name but the domain name.

Fide Sed Cui Vide

A self-signed certificate has the disadvantage that browsers initially consider it unsafe – after all, anyone could issue such a certificate. The user must explicitly classify it as correct and reliable on first access to the server. On a public web server, it is a good idea to have the certificate signed by a certificate authority. Several commercial providers act as certificate authorities, the best-known being Verisign Security (now owned by Symantec [5]). Browsers already include signatures from this certificate authority and accept any certificate signed or issued by it. If the CA wants a certificate request, you can create it with the following command:

openssl req -new -key privatekey.pem -out request.csr

You then submit the request in the request.csr file to a certificate authority. On a corporate network, you could alternatively add your own certificates to browsers up front or even run your own certification authority.

In any case, you now have a file with the certificate and the private key. The duo are best kept in a separate subdirectory with the other configuration files. On Linux systems, configuration files are typically found in /etc/apache2 or /etc/httpd, and on Windows they are typically in conf below the Apache directory. Create an ssl subdirectory and copy the certificate and the private key to it:

mkdir -p /etc/apache2/ssl
cp *.pem /etc/apache2/ssl

Normally, these commands will require root privileges.

Components

The Apache mod_ssl module takes care of encrypted SSL connections. Many, but not all, Linux distributions enable it by default. The Apache server loads mod_ssl if the following line appears somewhere in its configuration files:

LoadModule ssl_module modules/mod_ssl.so

Usually, it is found in the central httpd.conf; CentOS stores the line in /etc/httpd/conf.d/ssl.conf. If you use the default configuration files, you only need to remove the hash mark from the line. Alternatively, some Linux distributions, including Debian, Ubuntu, and openSUSE, come with a script named a2enmod to enable dynamically loadable Apache modules. The root user thus enables mod_ssl as follows:

a2enmod ssl

On openSUSE, you additionally need the a2enflag SSL command. If the script a2enmod is available, you should use it. The distributions then usually rely on several configuration files, some of which are automatically generated. Debian uses symbolic links to enable and disable individual modules.

Requests via HTTPS normally arrive on port 443. To ensure that Apache listens on that port, you have to add the following section to the configuration:

<IfModule mod_ssl.c>
        Listen 443
</IfModule>

Which configuration file this section belongs in depends on the Apache installation. On Debian-based systems, it is already in the /etc/apache2/ports.conf file; openSUSE 12.3 uses /etc/apache2/listen.conf, and on CentOS it's in /etc/httpd/conf.d/ssl.conf. If necessary, remove the hash signs (#) that comment out the section. If you use the default configuration file, like the one included with the Apache Windows binary package, you only need to uncomment this line in httpd.conf:

#Include conf/extra/httpd-ssl.conf

This line tells Apache to parse httpd-ssl.conf in the extra subdirectory for the required section.

New Host

For Apache to respond to HTTPS requests, you need a new virtual host. Listing 1 gives an example. (See also the box labeled "Server Name Identification.") After setting the server name and document root, SSLEngine **On enables encryption. The document root directory is something you should choose carefully: If it is identical to the globally set document root directory, visitors can view the local sites via both secured and an unsecured connections (which is usually the case if you leave out the DocumentRoot directive on the SSL host). One should therefore use different document roots, where possible, or restrict access to the relevant parts of the website using a tool such as the Rewrite module.

Listing 1: Virtual host TLS

01 <VirtualHost *:443>
02    ServerName login.example.com
03    DocumentRoot "/var/www"
04
05    SSLEngine on
06    SSLCertificateFile    /etc/apache2/ssl/zertifikat.pem
07    SSLCertificateKeyFile /etc/apache2/ssl/privatekey.pem
08
09    <Directory "/var/www">
10        Options Indexes FollowSymLinks
11    </Directory>
12
13    CustomLog /var/log/apache2/ssl_request_log   ssl_combined
14    ErrorLog /var/log/apache2/ssl_error_log
15    TransferLog /var/log/apache2/ssl_access_log
16 </VirtualHost>

SSLCertificateFile points to the location of the certificate; SSLCertificateKeyFile reveals the file containing the private key. If a certificate is used, in which the private key is embedded, you can leave out SSLCertificateKeyFile. For security reasons, however, you should always outsource the private key to a separate file.

Access attempts via SSL are logged in /var/log/apache2/ssl_request_log. Error messages are sent to the ssl_error_log, and ssl_access_log collects all requests. Access to the pages of the domain is managed, as usual, by a Directory section.

Listing 1 is best stored in a separate configuration file. The directory in which it belongs again depends on the Apache installation. Debian admins put it under /etc/apache2/sites-available and name it after the ServerName. Then you need to enable the file explicitly with a2ensite login.example.com, replacing login.example.com with the name of the new configuration file. For openSUSE, the file in Listing 1 needs the extension .conf and resides in /etc/apache2/vhosts.d. CentOS and the Windows binary package for Apache include a sample configuration for a virtual host, which can be easily adjusted to match Listing 1. In CentOS, you can find the sample configuration in /etc/httpd/conf.d/ssl.conf; on Windows it is in httpd-ssl.conf, below the configure\extra folder of the Apache installation.

Passphrase to Start

Finally, you have to restart Apache again; if you are using Debian, use this: /etc/init.d/apache2 restart. Apache prompts you for the passphrase for the private key. You can only prevent this prompt by removing the encryption. If multiple SSL-secured virtual hosts are used, Apache attempts to use the passphrase for all the other private keys. Ideally, you only have to type in a passphrase once.

Now, when a user accesses the encrypted site – in the previous examples https://login.example.com – the browser warns them about the self-signed certificate, which might not be secure (Figure 3). Users can decide whether to classify the certificate manually as trusted, then encrypted communications can start.

Self-signed certificates prompt a warning from browsers.
Figure 3: Self-signed certificates prompt a warning from browsers.

Spoiled for Choice

In addition to the three SSL directives in Listing 1, Apache knows a few more. SSLCipherSuite is particularly interesting. The SSLCipherSuite directive specifies which encryption algorithms the server accepts for the SSL handshake. The directive is followed by a colon-separated list of possible algorithms. You have to specify, in each case, at least one algorithm for the key exchange, authentication, encryption, and integrity checking. An example of such a selection would be:

SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP

Each algorithm is abbreviated; RC4 is, for example, the RC4 algorithm. The algorithm abbreviations are given in Table 1. To avoid typing your fingers to the bone, you can rely on abbreviations or aliases. For example, SSLv2 means all algorithms supported by the SSL2 protocol; ALL means all possible algorithms. Other aliases are listed in Table 2. "Exportable" refers to the export restrictions of the United States, which dictate that particularly strong encryption methods cannot be exported. EXP thus contains only methods with low key lengths.

Tabelle 1: Possible Algorithms for SSLCipherSuite

Abbreviation

Meaning

Algorithms for key exchange

kRSA

RSA

kDHr

Diffie-Hellman with RSA key

kDHd

Diffie-Hellman with DSA key

kEDH

Ephemeral Diffie-Hellman (temporary key without certificate)

kSRP

Key exchange via Secure Remote Password (SRP)

Authentication algorithms

aNULL

No authentication

aRSA

RSA

aDSS

DSS

ADH

Diffie-Hellman

Encryption algorithms

eNULL

No encryption

NULL

Like eNULL

AES

AES

DES

DES

3DES

Triple DES

RC4

RC4

RC2

RC2

IDEA

IDEA

Algorithms for integrity checking (MAC digest algorithm)

MD5

MD5

SHA1

SHA1

SHA

Like SHA1

SHA256

SHA256

SHA384

SHA384

Tabelle 2: Aliases for SSLCipherSuite

Abbreviation

Meaning

SSLv3

All algorithms supported by SSL 3.0

TLSv1

All algorithms supported by TLS 1.0

EXP

All exportable algorithms

EXPORT40

Exportable algorithms with 40 bits

EXPORT56

Exportable algorithms with 56 bits

LOW

Weak but not exportable algorithms (single DES)

MEDIUM

All algorithms with 128 bits

HIGH

All algorithms that use triple DES

RSA

All algorithms that use an RSA key exchange

DH

All algorithms that use a Diffie-Hellman key exchange

EDH

All algorithms that use a key exchange with ephemeral Diffie-Hellman

ECDH

Key exchange using Elliptic Curve Diffie-Hellman

ADH

All algorithms that use an anonymous Diffie-Hellman key exchange

AECDH

All algorithms that use a key exchange with Elliptic Curve Diffie-Hellman

SRP

All algorithms that use a key exchange with the Secure Remote Password (SRP)

DSS

All algorithms that use a DSS authentication

ECDSA

All algorithms that use an ECDSA authentication

NULL

All algorithms that do not use authentication

Finally, you can prefer or exclude certain algorithms. This is shown by special characters + , - and !, which are prefixed to the shortcuts. The ! prohibits an algorithm, so the !ADH entry in the preceding example thus excludes all algorithms that use Anonymous Diffie-Hellman. The minus sign - also removes an algorithm, but you can add it to the chain again later. Using the plus sign, you can explicitly set an algorithm at the corresponding position in the list and thus influence the order. In the above example, the web server would prefer the algorithms from the HIGH group before those from the MEDIUM group. Finally, you can also select multiple cipher suites by adding a + between abbreviations. In the above example, RC4+RSA would enable all possible cipher suites that include RC4 and RSA. The example is also the default in Apache 2.2. Apache 2.4, however, accepts the default settings of OpenSSL.

What combinations of algorithms are possible in a setting is revealed by the openssl ciphers-v command. Just add the tail of options to be examined to the command:

openssl ciphers -v 'ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP'

The result is a table like Figure 4. The first column lists the names of the cipher suites; the second column states the SSL standard. Also included are algorithms for the key exchange, authentication, encryption, and integrity checking.

The possible combinations of algorithms, as shown by openssl.
Figure 4: The possible combinations of algorithms, as shown by openssl.

The major browsers normally prefer secure algorithms, currently mainly AES, which are computationally more expensive. Administrators who rely instead on faster, simpler methods live dangerously: RC4 recently hit the headlines. The "TLS" article elsewhere in this issue reveals more problems with TLS. You should not overrule the secure method proposed by the client with your own SSLCipherSuite. You can speed up encoding by deploying OpenSSL crypto hardware. But this assumes that OpenSSL was built with engine support (Figure 5), which is the case from OpenSSL 0.9.7 onward. To discover the available hardware accelerators, type:

On this Core i7 running openSUSE 12.3, there is only one crypto device for hardware accelerated encryption.
Figure 5: On this Core i7 running openSUSE 12.3, there is only one crypto device for hardware accelerated encryption.
openssl engine

Choose one of the accelerators and add the name in the parentheses after the SSLCryptoDevice directive, as in:

SSLCryptoDevice rsax

Additionally, you can set up a cache for the session data:

SSLSessionCache dbm:/tmp/cachefile

In this case, Apache would use the DBM file /tmp/cachefile.

Roll the Dice

The algorithms used by TLS rely on a random number generator. The default is mod_ssl, which creates random numbers from the current time, the process ID, and a randomly chosen 1KB chunk of the internal scoreboard memory, which Apache uses for inter-process communication. However, the result is not a true random number; instead, you can use SSLRandomSeed to select another source and thus improve security. In the simplest case, you can pick the random values from a file, such as from /dev/random in Linux:

SSLRandomSeed connect file:/dev/random

connect indicates that Apache retrieves the random number when connecting. The alternative, startup, would only retrieve a random number on starting the web server. SSLRandomSeed must also be in the global server context (i.e., outside the <VirtualServer> container). In addition to a file as the source, a program can deliver the data. The program must write the random values to standard output:

SSLRandomSeed startup exec:/bin/myprg

Finally, on Unix systems, you can use the data from a network socket as a source of random numbers:

SSLRandomSeed startup egd:/path/to/socket

A reference to all mod_ssl-provided directives is available for Apache 2.2 [6] and Apache 2.4 [7].

Once you have created a certificate, setting up mod_ssl is no problem, but SSL/TLS only encrypt traffic, and so only offer privacy against potential sniffers. Thus, it is not enough simply to enable the SSL module. The web application must also handle the received data confidentially and encrypt the data for storage in a database. TLS is thus only one small component in a comprehensive security strategy.