Understanding SSL

John Paul

Secure Sockets Layer (SSL) and its successor, Transport Layer Security (TLS), are cryptographic protocols which provide secure communications on the Internet for such things as web browsing (particularly form submission), e-mail, Internet faxing, and other data transfers. There are slight differences between SSL 3.0 and TLS 1.0, but the protocol remains substantially the same. The term "SSL" as used here applies to both protocols unless clarified by context.

SSL provides endpoint authentication and communications privacy over the Internet using cryptography. In typical use, only the server is authenticated (i.e., its identity is ensured) while the client remains unauthenticated; mutual authentication requires public key infrastructure (PKI) deployment to clients. The protocols allow client/server applications to communicate in a way designed to prevent eavesdropping, tampering, and message forgery.

SSL involves three basic phases:

   1. Peer negotiation for algorithm support
2. Public key encryption-based key exchange and certificate-based authentication
3. Symmetric cipher-based traffic encryption

During the first phase, the client and server negotiation uses cryptographic algorithms. Current implementations support the following choices:

    * for public-key cryptography: RSA, Diffie-Hellman, DSA or Fortezza;
* for symmetric ciphers: RC2, RC4, IDEA, DES, Triple DES or AES;
* for one-way hash functions: MD2, MD4, MD5 or SHA.

The SSL protocol exchanges records; each record can be optionally compressed, encrypted and packed with a message authentication code (MAC). Each record has a content_type field that specifies which upper level protocol is being used.

When the connection starts, the record level encapsulates another protocol, the handshake protocol, which has content_type 22.

The client sends and receives several handshake structures:

    * It sends a ClientHello message specifying the list of cipher suites, compression methods and the highest protocol version it supports. It also sends random bytes which will be used later.

    * Then it receives a ServerHello, in which the server chooses the connection parameters from the choices offered by the client earlier.

    * When the connection parameters are known, the client and server exchange certificates (depending on the selected public key cipher). These certificates are currently X.509, but there is also a draft specifying the use of OpenPGP based certificates.

    * The server can request a certificate from the client, so that the connection can be mutually authenticated.

    * The client and server negotiate a common secret called the "master secret", possibly using the result of a Diffie-Hellman exchange, or simply encrypting a secret with a public key that is decrypted with the peer's private key. All other key data is derived from this "master secret" (and the client- and server-generated random values), which is passed through a carefully designed "pseudorandom function".

TLS/SSL have a variety of security measures:

* Numbering all the records and using the sequence number in the MACs.
* Using a message digest enhanced with a key (so only with the key can you check the MAC). This is specified in RFC 2104.
* Protection against several known attacks (including man in the middle attacks), like those involving a downgrade of the protocol to a previous (less secure) version or a weaker cipher suite.
* The message that ends the handshake ("Finished") sends a hash of all the exchanged data seen by both parties.
* The pseudorandom function splits the input data in half and processes each one with a different hashing algorithm (MD5 and SHA), then XORs them together. This provides protection if one of these algorithms is found to be vulnerable.

SSL runs on layers beneath application protocols such as HTTP, FTP, SMTP and NNTP, and above the TCP or UDP transport protocol, which form part of the TCP/IP protocol suite. While it can add security to any protocol that uses reliable connections (such as TCP), it is most commonly used with HTTP to form HTTPS. HTTPS is used to secure World Wide Web pages for applications such as electronic commerce. It uses public key certificates to verify the identity of endpoints.

An increasing number of client and server products support SSL natively, but many still lack support. As an alternative, users may wish to use standalone SSL products like Stunnel. Wrappers such as Stunnel rely on being able to obtain an SSL connection immediately, by simply connecting to a separate port reserved for the purpose. For example, by default the TCP port for HTTPS is 443, to distinguish it from HTTP on port 80. However, in 1997 the Internet Engineering Task Force recommended that application protocols always start unsecured and instead offer a way to upgrade to TLS - which a pure wrapper like Stunnel cannot cope with.

SSL can also be used to tunnel an entire network stack to create a VPN, as is the case with OpenVPN.

Developed by Netscape, SSL version 3.0 was released in 1996, which later served as the basis for TLS version 1.0, an IETF standard protocol first defined in RFC 2246. Visa, MasterCard, American Express and many leading financial institutions have endorsed SSL for commerce over the Internet.

SSL operates in modular fashion. It is extensible by design, with support for forward and backward compatibility and negotiation between peers.

Some early implementations of SSL could use a maximum of only 40-bit symmetric keys because of US government restrictions on the export of cryptographic technology. The US government explicitly imposed a 40-bit keyspace small enough to be broken by brute-force search by law enforcement agencies wishing to read the encrypted traffic, while still presenting obstacles to less-well-funded attackers. A similar limitation applied to Lotus Notes in export versions. After several years of public controversy, a series of lawsuits, and eventual US government recognition of changes in the market availability of 'better' cryptographic products produced outside the US, the authorities relaxed some aspects of the export restrictions. The 40-bit key size limitation has mostly gone away. Modern implementations use 128-bit (or longer) keys for symmetric key ciphers.

Installing SSL on Apache

Depending on the web server you use, there can be different SSL configurations. Now that you've learned all about SSL, you need to install SSL support for Apache. SSL support is provided by mod_ssl, a module that is included with Apache but is not enabled by default. mod_ssl, in turn, requires the OpenSSL library—an open source implementation of the SSL/TLS protocols and a variety of other cryptographic algorithms. OpenSSL is based on the SSLeay library developed by Eric A. Young and Tim J. Hudson.
If you are running a recent Linux or FreeBSD distribution, OpenSSL might already be installed in your system. Use the package management tools bundled with your distribution to determine whether that is the case or, otherwise, to install it.
If you need to install OpenSSL from source, you can download OpenSSL from http://www.openssl.org. After you have downloaded the software, you need to uncompress it and cd into the created directory:

# gunzip < openssl*.tar.gz | tar xvf -
# cd openssl*

OpenSSL contains a config script to help you build the software. You must provide the path to which the software will install. The path used in this hour is /usr/local/ssl/install, and you probably need to have root privileges to install the software there. You can install the software as a regular user, but to do so, you will need to change the path. Then you must build and install the software:

# ./config --prefix=/usr/local/ssl/install 
--openssldir=/usr/local/ssl/install/openssl
# make
# make install

If everything went well, you have now successfully installed the OpenSSL toolkit. The openssl command-line tool will be located in /usr/local/ssl/install/bin/.

This tool is used to create and manipulate certificates and keys and its usage is described in a later section on certificates.

mod_ssl

In the past, SSL extensions for Apache had to be distributed separately because of export restrictions. Although there are limitations in redistribution of binaries that need to be solved and clarified, these restrictions no longer exist for distribution of source code, and mod_ssl is bundled and integrated with Apache 2.0. This section describes the steps necessary to build and install this module. mod_ssl depends on the OpenSSL library, so a valid OpenSSL installation is required.

If you are using the Apache 2.0 server that came installed with your operating system, chances are that it already includes mod_ssl. Use the package management tools bundled with your distribution to install mod_ssl if it is not present in your system.
When you build Apache 2.0 from source, you must pass the following options to enable and build mod_ssl at compile time.

--enable-ssl --with-ssl=/usr/local/ssl/install/openssl

This assumes that you installed OpenSSL in the location described in previous sections.
If you compiled mod_ssl statically into Apache, you can check whether it is present by issuing the following command, which provides a list of compiled-in modules:

# /usr/local/apache2/bin/httpd -l

The command assumes that you installed Apache in the /usr/local/apache2 directory.
If mod_ssl was compiled as a dynamic loadable module, the following line must be added or uncommented to the configuration file:

LoadModule ssl_module modules/libmodssl.so

To have a working SSL server implementation, the first step is to create a server certificate. This section explains in detail how to create and manage certificates and keys by using the openssl command-line tool. For example, if you are using SSL for an e-commerce site, encryption prevents customer data from eavesdroppers and the certificate enables customers to verify that you are who you claim to be.

The examples refer to the Unix version of the command-line program openssl. If you are running under Windows, you need to use openssl.exe instead and change the paths of the examples to use backslashes instead of forward slashes. The examples also assume that OpenSSL was installed in the path described earlier in the OpenSSL installation section.

Creating a Key Pair

You must have a public/private key pair before you can create a certificate request. Assume that the FQDN for the certificate you want to create is www.example.com. (You will need to substitute this name for the FQDN of the machine you have installed Apache on.) You can create the keys by issuing the following command:

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

genrsa indicates to OpenSSL that you want to generate a key pair.
des3 indicates that the private key should be encrypted and protected by a pass phrase.

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.
The result of invoking this command looks like this:

625152 semi-random bytes loaded
Generating RSA private key, 1024 bit long modulus
.....++++++
.........................++++++
e is 65537 (0x10001)
Enter PEM pass phrase:
Verifying password - Enter PEM pass phrase:

As you can see, you will be asked to provide a pass phrase. Choose a secure one. The pass phrase is necessary to protect the private key and you will be asked for it whenever you want to start the server. You can choose not to protect the key. This is convenient because you will not need to enter the pass phrase during reboots, but it is highly insecure and a compromise of the server means a compromise of the key as well. In any case, you can choose to unprotect the key either by leaving out the -des3 switch in the generation phase or by issuing the following command:

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

It is a good idea to back up the www.example.com.key file. You can learn about the contents of the key file by issuing the following command:

# ./usr/local/ssl/bin/openssl rsa -noout -text -in www.example.com.key

Creating a Certificate Signing Request
To get a certificate issued by a CA, you must submit what is called a certificate signing request. To create a request, issue the following command:

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

You will be prompted for the certificate information:

Using configuration from /usr/local/ssl/install/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 []:administrator@example.com
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 Web site 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.
The certificate is now stored in www.example.com.csr. You can learn about the contents of the certificate via the following command:

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

You can submit the certificate signing request file to a CA for processing. VeriSign and Thawte are two of those CAs. You can learn more about their particular submission procedures at their Web sites:

Creating a Self-Signed Certificate
You can also 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 Web site, 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/install/bin/openssl x509 -req -days 30 
-in www.example.com.csr -signkey www.example.com.key 
-out www.example.com.cert

You 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/install/openssl/certs/ and your key to /usr/local/ssl/install/openssl/private/.
Protect your key file by issuing the following command:

# chmod 400 www.example.com.key

The previous sections introduced the (not-so-basic) concepts behind SSL and you have learned how to generate keys and certificates. Now, finally, you can configure Apache to support SSL. mod_ssl must either be compiled statically or, if you have compiled as a loadable module, the appropriate LoadModule directive must be present in the file.
If you compiled Apache yourself, a new Apache configuration file, named ssl.conf, should be present in the conf/ directory. That file contains a sample Apache SSL configuration and is referenced from the main httpd.conf file via an Include directive.
If you want to start your configuration from scratch, you can add the following configuration snippet to your Apache configuration file:

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

With the previous configuration, you set up a new virtual host that will listen to port 443 (the default port for HTTPS) and you enable SSL on that virtual host with the SSLEngine directive.

You need to indicate where to find the server's certificate and the file containing the associated key. You do so by using SSLCertificateFile and SSLCertificateKeyfile directives.

Starting the Server
Now you can stop the server if it is running, and start it again. If your key is protected by a pass phrase, you will be prompted for it. After this, Apache will start and you should be able to connect securely to it via the https://http://www.example.com/ URL.
If you compiled and installed Apache yourself, in many of the vendor configuration files, you can see that the SSL directives are surrounded by an <IfDefine SSL> block. That allows for conditional starting of the server in SSL mode. If you start the httpd server binary directly, you can pass it the -DSSL flag at startup. You can also use the apachectl script by issuing the apachectl startssl command. Finally, if you always want to start Apache with SSL support, you can just remove the <ifDefine> section and start Apache in the usual way.

If you are unable to successfully start your server, check the Apache error log for clues about what might have gone wrong. For example, if you cannot bind to the port, make sure that another Apache is not running already. You must have administrator privileges to bind to port 443; otherwise, you can change the port to 8443 and access the URL via https://http://www.example.com:8443.
Configuration Directives

mod_ssl provides comprehensive technical reference documentation. This information will not be reproduced here; rather, I will explain what is possible and which configuration directives you need to use. You can then refer to the online SSL documentation bundled with Apache for the specific syntax or options.

Algorithms

You can control which ciphers and protocols are used via the SSLCipherSuite and SSLProtocol commands. For example, you can configure the server to use only strong encryption with the following configuration:

SSLProtocol all
SSLCipherSuite HIGH:MEDIUM

See the Apache documentation for a detailed description of all available ciphers and protocols.

Client Certificates

Similarly to how clients can verify the identity of servers using server certificates, servers can verify the identity of clients by requiring a client certificate and making sure that it is valid.

SSLCACertificateFile and SSLCACertificatePath are two Apache directives used to specify trusted Certificate Authorities. Only clients presenting certificates signed by these CAs will be allowed access to the server.

The SSLCACertificateFile directive takes a file containing a list of CAs as an argument. Alternatively, you could use the SSLCACertificatePath directive to specify a directory containing trusted CA files. Those files must have a specific format, described in the documentation. SSLVerifyClient enables or disables client certificate verification. SSLVerifyDepth controls the number of delegation levels allowed for a client certificate. The SSLCARevocationFile and SSLCARevocationPath directives enable you to specify certificate revocation lists to invalidate certificates.

Performance

SSL is a protocol that requires intensive calculations. mod_ssl and OpenSSL allow several ways to speed up the protocol by caching some of the information about the connection. You can cache certain settings using the SSLSessionCache and SSLSessionCacheTimeout directives. There is also built-in support for specialized cryptographic hardware that will perform the CPU-intensive computations and offload the main processor. The SSLMutex directive enables you to control the internal locking mechanism of the SSL engine. The SSLRandomSeed directive enables you to specify the mechanism to seed the random-number generator required for certain operations. The settings of both directives can have an impact on performance.

Logging

mod_ssl hooks into Apache's logging system and provides support for logging any SSL-related aspect of the request, ranging from the protocol used to the information contained in specific elements of a client certificate. This information can also be passed to CGI scripts via environment variables by using the StdEnvVars argument to the Options directive. You can get a listing of the available SSL variables at http://httpd.apache.org/docs-2.0/ssl/ssl_compat.html.

The SSLOptions Directive
Many of these options can be applied in a per-directory or per-location basis. The SSL parameters might be renegotiated for those URLs. This can be controlled via the SSLOptions directive.

The SSLPassPhraseDialog directive can be used to avoid having to enter a pass phrase at startup by designating an external program that will be invoked to provide it.

Access Control
The SSLRequireSSL directive enables you to force clients to access the server using SSL. The SSLRequire directive enables you to specify a set of rules that have to be met before the client is allowed access. SSLRequire syntax can be very complex, but itallows an incredible amount of flexibility. Listing 17.1 shows a sample configuration from the mod_ssl documentation that restricts access based on the client certificate and the network the request came from. Access will be granted if one of the following is met:

  • 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.

You can check the documentation for SSLRequire for a complete syntax reference.

SSLRequire Example

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]+$/

You can access the mod_ssl reference documentation for in-depth syntax explanation and additional configuration information. Bear in mind also that SSL is just part of maintaining a secure server, which includes applying security patches, OS configuration, access control, physical security, and so on.








}