4.4. Apache and SSLIf you are using Apache from the 2.x branch, the support for SSL is included with the distribution. For Apache 1, it is a separate download of one of two implementations. You can use mod_ssl (http://www.modssl.org) or Apache-SSL (http://www.apache-ssl.org). Neither of these two web sites discusses why you would choose one instead of the other. Historically, mod_ssl was created out of Apache-SSL, but that was a long time ago and the two implementations have little in common (in terms of source code) now. The mod_ssl implementation made it into Apache 2 and is more widely used, so it makes sense to make it our choice here. Neither of these implementations is a simple Apache module. The Apache 1 programming interface does not provide enough functionality to support SSL, so mod_ssl and Apache-SSL rely on modifying the Apache source code during installation. 4.4.1. Installing mod_sslTo add SSL to Apache 1, download and unpack the mod_ssl distribution into the same top folder where the existing Apache source code resides. In my case, this is /usr/local/src. I will assume you are using Apache Version 1.3.31 and mod_ssl Version 2.8.19-1.3.31: $ cd /usr/local/src $ wget -q http://www.modssl.org/source/mod_ssl-2.8.19-1.3.31.tar.gz $ tar zxvf mod_ssl-2.8.19-1.3.31.tar.gz $ cd mod_ssl-2.8.19-1.3.31 $ ./configure --with-apache=../apache_1.3.31 Return to the Apache source directory (cd ../apache_1.3.31) and configure Apache, adding a --enable-module=ssl switch to the configure command. Proceed to compile and install Apache as usual: $ ./configure --prefix=/usr/local/apache --enable-module=ssl $ make # make install Adding SSL to Apache 2 is easier as you only need to add a --enable-ssl switch to the configure line. Again, recompile and reinstall. I advise you to look at the configuration generated by the installation (in httpd.conf for Apache 1 or ssl.conf for Apache 2) and familiarize yourself with the added configuration options. I will cover these options in the following sections. 4.4.2. Generating KeysOnce SSL is enabled, the server will not start unless a private key and a certificate are properly configured. Private keys are commonly protected with passwords (also known as passphrases) to add additional protection for the keys. But when generating a private key for a web server, you are likely to leave it unprotected because a password-protected private key would require the password to be manually typed every time the web server is started or reconfigured. This sort of protection is not realistic. It is possible to tell Apache to ask an external program for a passphrase (using the SSLPassPhraseDialog directive), and some people use this option to keep the private keys encrypted and avoid manual interventions. This approach is probably slightly more secure but not much. To be used to unlock the private key, the passphrase must be available in cleartext. Someone who is after the private key is likely to be determined enough to continue to look for the passphrase. The following generates a nonprotected, 1,024-bit server private key using the RSA algorithm (as instructed by the genrsa command) and stores it in server.key: # cd /usr/local/apache/conf # mkdir ssl # cd ssl # openssl genrsa -out server.key 1024 Generating RSA private key, 1024 bit long modulus ....................................++++++ ..........................++++++ e is 65537 (0x10001) Only the private key was generated: # cat server.key -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCtLL9Tb27Tg/KWdPbhNXAwQFfJ8cxkAQW8W9yI5dZMMObpO3kZ 4MUep2OmiEGI6gsBSyZ8tSnl3AfD/XFWwCfrcTWQi4qwS1sQiGMV+DglPJNKMOfq tR1cqTUIpajqt12Zc57LVhIQJV3Q6Cnpupo5n40avwUXzEm5VmUxwzmmWQIDAQAB AoGAeMdYuUxis0q3ipARD4lBsaVulP37W1QLOA+phCEokQMaSVidYZsOYA7GxYMK kf8JpeFP+nIvwozvLZY50hM6wyh6j7T1vbUoiKl7J5FPBnxMcdi/CfOMhF1I42hp abfvFWDilol+sanmmgiSPn9tSzDUaffwTdEbx5lrCDuXvcECQQDfnDE4lS74QdL0 hbqsuyoqeuv6+18O/j/YAwdr16SWNhpjXck+fRTcfIiDJCRn+jV1bQosSB4wh2yP H1feYbe9AkEAxkJV2akePfACOHYM1jGM/FkIn8vG73SUr5spNUPakJUsqkZ6Tnwp 5vRkms+PgE5dYlY4P0BncV0Itg10DqXUzQJBAKh3RYIKqyNwfB2rLtP6Aq+UgntJ rPlfxfvZdFrkUWS2CDV6sCZ7GB9xV2vt69vGX0ZDy1lHUC9hqAFALPQnDMUCQDA3 w+9q/SrtK20V8OtLI9HfyYQrqFdmkB7harVEqmyNi05iU66w7fP4rlskbe8zn+yh sY5YmI/uo4a7YOWLGWUCQCWcBWhtVzn9bzPj1h+hlmAZd/3PtJocN+1y6mVuUwSK BdcOxH2kwhazwdUlRwQKMuTvI9j5JwB4KWQCAJFnF+0= -----END RSA PRIVATE KEY----- But the public key can be extracted from the private key: # openssl rsa -in server.key -pubout writing RSA key -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtLL9Tb27Tg/KWdPbhNXAwQFfJ 8cxkAQW8W9yI5dZMMObpO3kZ4MUep2OmiEGI6gsBSyZ8tSnl3AfD/XFWwCfrcTWQ i4qwS1sQiGMV+DglPJNKMOfqtR1cqTUIpajqt12Zc57LVhIQJV3Q6Cnpupo5n40a vwUXzEm5VmUxwzmmWQIDAQAB -----END PUBLIC KEY----- 4.4.3. Generating a Certificate Signing RequestThe next step is to create a certificate-signing request (CSR). This is a formal request asking a certificate authority to sign a certificate, and it contains the public key of the entity requesting the certificate and information about the entity. The information becomes part of the certificate. CSR creation is an interactive process, which takes the private server key as input. Read the instructions given by the openssl tool carefully: if you want a field to be empty, you must enter a single dot (.) and not just press Return because doing so would populate the field with the default value. # openssl req -new -key server.key -out server.csr 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) [GB]: State or Province Name (full name) [Berkshire]:. Locality Name (eg, city) [Newbury]:London Organization Name (eg, company) [My Company Ltd]:Apache Security Organizational Unit Name (eg, section) [ ]:. Common Name (eg, your name or your server's hostname) [ ]: www.apachesecurity.net Email Address [ ]:webmaster@apachesecurity.net Please enter the following 'extra' attributes to be sent with your certificate request A challenge password [ ]: An optional company name [ ]: After a CSR is generated, you use it to sign your own certificate and/or send it to a public CA and ask him to sign the certificate. Both approaches are described in the sections that follow. 4.4.4. Signing Your Own CertificateFor testing purposes, you should sign your own certificate; it may be days before the CA completes the certificate generation process. You have the files you need: the CSR and the private key. The x509 command with the -req switch creates a self-signed certificate. Other switches on the following command line instruct openssl to create a certificate valid for 365 days using the private key specified in server.key: # openssl x509 -req -days 365 -in server.csr \ > -signkey server.key -out server.crt Signature ok subject=/C=GB/L=London/O=Apache Security/CN=www.apachesecurity.net/emailAddress=webmaster@apachesecurity.net Getting Private key Use the x509 command to examine the contents of the certificate you have created: # openssl x509 -text -in server.crt Certificate: Data: Version: 1 (0x0) Serial Number: 0 (0x0) Signature Algorithm: md5WithRSAEncryption Issuer: C=GB, L=London, O=Apache Security, CN=www.apachesecurity.net/emailAddress=webmaster@apachesecurity.net Validity Not Before: Jul 26 13:36:34 2004 GMT Not After : Jul 26 13:36:34 2005 GMT Subject: C=GB, L=London, O=Apache Security, CN=www.apachesecurity.net/emailAddress=webmaster@apachesecurity.net Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) Modulus (1024 bit): 00:d0:b6:1e:63:f1:39:9c:17:d2:56:97:e9:6d:0d: a5:a1:de:80:6b:66:f9:62:53:91:43:bf:b9:ff:57: b3:54:0b:89:34:3e:93:5f:46:bc:74:f8:88:92:bd: 3c:0a:bb:43:b4:57:81:e7:aa:b6:f0:3f:e7:70:bf: 84:2e:04:aa:05:61:fb:c9:f7:65:9a:95:23:d7:24: 97:75:6e:14:dc:94:48:c0:cd:7b:c7:2e:5b:8c:ad: ad:db:6c:ab:c4:dd:a3:90:5b:84:4f:94:6c:eb:6e: 93:f4:0f:f9:76:9f:70:94:5e:99:12:15:8f:b7:d8: f0:ff:db:f6:ee:0c:85:44:43 Exponent: 65537 (0x10001) Signature Algorithm: md5WithRSAEncryption 9e:3b:59:a4:89:7e:30:c7:b3:3d:82:ea:3e:f5:99:4a:e9:b2: 53:25:9f:04:66:e0:b7:43:47:48:a2:b9:27:bc:b6:37:bb:6a: 2f:66:d2:58:bf:b8:50:19:4f:7f:51:54:ba:a9:c9:8a:3c:70: 25:0d:29:d1:af:78:f2:3a:0b:74:de:a6:36:c1:f8:f9:6c:b2: 9d:4e:f5:3a:e6:87:99:99:b9:c6:25:33:c2:84:4e:81:e8:b3: e4:e3:5b:20:1e:09:3c:b3:60:88:90:1c:a2:29:dd:91:25:3e: cb:44:55:97:9e:96:97:52:49:38:77:03:0d:59:b8:7d:4f:32: 44:45 -----BEGIN CERTIFICATE----- MIICfTCCAeYCAQAwDQYJKoZIhvcNAQEEBQAwgYYxCzAJBgNVBAYTAkdCMQ8wDQYD VQQHEwZMb25kb24xGDAWBgNVBAoTD0FwYWNoZSBTZWN1cml0eTEfMB0GA1UEAxMW d3d3LmFwYWNoZXNlY3VyaXR5Lm5ldDErMCkGCSqGSIb3DQEJARYcd2VibWFzdGVy QGFwYWNoZXNlY3VyaXR5Lm5ldDAeFw0wNDA3MjYxMzM2MzRaFw0wNTA3MjYxMzM2 MzRaMIGGMQswCQYDVQQGEwJHQjEPMA0GA1UEBxMGTG9uZG9uMRgwFgYDVQQKEw9B cGFjaGUgU2VjdXJpdHkxHzAdBgNVBAMTFnd3dy5hcGFjaGVzZWN1cml0eS5uZXQx KzApBgkqhkiG9w0BCQEWHHdlYm1hc3RlckBhcGFjaGVzZWN1cml0eS5uZXQwgZ8w DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANC2HmPxOZwX0laX6W0NpaHegGtm+WJT kUO/uf9Xs1QLiTQ+k19GvHT4iJK9PAq7Q7RXgeeqtvA/53C/hC4EqgVh+8n3ZZqV I9ckl3VuFNyUSMDNe8cuW4ytrdtsq8Tdo5BbhE+UbOtuk/QP+XafcJRemRIVj7fY 8P/b9u4MhURDAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAnjtZpIl+MMezPYLqPvWZ SumyUyWfBGbgt0NHSKK5J7y2N7tqL2bSWL+4UBlPf1FUuqnJijxwJQ0p0a948joL dN6mNsH4+WyynU71OuaHmZm5xiUzwoROgeiz5ONbIB4JPLNgiJAcoindkSU+y0RV l56Wl1JJOHcDDVm4fU8yREU= -----END CERTIFICATE----- 4.4.5. Getting a Certificate Signed by a CATo get a publicly recognized certificate, you will send the generated CSR to a CA. The CA will collect payment, validate your organization's identity, and issue a certificate. Certificates used to be very expensive but, thanks to competing CAs, are now inexpensive enough to allow all but the smallest organizations to use valid public certificates for internal installations. Most CAs offer free trials so you can practice before making the purchase. Thawte, for example, is offering a script that generates test certificates instantly when fed with CSRs. That script and further information is available at https://www.thawte.com/cgi/server/try.exe.
After receiving the certificate, overwrite the self-signed certificate used for testing and restart Apache. No other changes should be required, but the CA may provide specific installation instructions. 4.4.6. Configuring SSLA minimal SSL configuration consists of three directives in the Apache configuration file: # Enable SSL SSLEngine On # Path to the server certificate SSLCertificateFile /usr/local/apache/conf/ssl/server.crt # Path to the server private key SSLCertificateKeyFile /usr/local/apache/conf/ssl/server.key You may wish to make the default configuration slightly more secure by adjusting the allowed protocols. SSLv2 is known to be flawed. (For details, see http://www.meer.net/~ericm/papers/ssl_servers.html#1.2.) Unless your installation has to support browsers that do not speak SSLv3 (which is unlikely), there is no reason to allow SSLv2. The following disallows it: # Allow SSLv3 and TLSv1 but not SSLv2 SSLProtocol All -SSLv2 One other useful configuration option is the following, which disallows the situation where, though the server supports high-grade encryption, the client negotiates a low-grade (e.g., 40-bit) protocol suite, which offers little protection: # Disallow ciphers that are weak (obsolete or # known to be flawed in some way). The use of # an exclamation mark in front of a cipher code # tells Apache never to use it. EXP refers to 40-bit # and 56-bit ciphers, NULL ciphers offer no encryption. # ADH refers to Anonymous Diffie-Hellman key exchange # which effectively disables server certificate validation, # and LOW refers to other low strength ciphers. SSLCipherSuite ALL:!EXP:!NULL:!ADH:!LOW After the certificate is installed, you can test it by opening the web site in your browser. You should get no warnings for a certificate issued by a well-known CA. You will get at least one warning if you are using a self-signed certificate for testing. In the Appendix A, I introduce SSLDigger, a tool designed to evaluate the strength of a site's SSL protection. 4.4.6.1 Supporting broken SSL clientsSome browsers do not have fully compliant SSL implementations. To make them work with Apache, you need a workaround. The code below is a workaround for problems related to Internet Explorer. The code is in the default SSL configurations, but I have provided it here because you need to be aware of what it does. Whenever the Internet Explorer browser is detected, this configuration fragment disables the HTTP Keep-Alive feature, downgrades the HTTP protocol to 1.0 (from the usual 1.1), and allows the SSL channel to be closed by closing the TCP/IP connection: # Make SSL work with Internet Explorer SetEnvIf User-Agent ".*MSIE.*" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 4.4.6.2 Securing the server private keyOn a server with many user accounts (and not all of them trusted), relaxed permissions on the file with the server private key may result in the key being retrieved by one of the users. The root user should be the only one with permission to read the private key and certificate files: # cd /usr/local/apache/conf/ssl # chmod 400 server.crt server.key 4.4.6.3 Ensuring reliable SSL startupIf you are using the apachectl script to start and stop Apache, then you have probably noticed it must be invoked with the startssl command in order to activate SSL. This can lead to problems (and service downtime) when you forget about it and execute the usual apachectl start. I suggest that you modify this script to make the start command behave in the same manner as startssl, always activating SSL. In the following script fragment, I emphasize where you need to add the -DSSL switch: case $ARGV in start|stop|restart|graceful) $HTTPD -k $ARGV -DSSL ERROR=$? ;; 4.4.6.4 Preventing configuration mistakesIf you are running a web site that needs to be available only over SSL, then avoid a chance of making the same content available through a non-SSL channel and create a virtual host that points to an empty folder. Use a RedirectPermanent directive to redirect users to the correct (secure) location: <VirtualHost 217.160.182.153:80> ServerName www.apachesecurity.net DirectoryRoot /var/www/empty RedirectPermanent / https://www.apachesecurity.net/ </VirtualHost> If the site contains SSL and non-SSL content, separating the content into two virtual hosts and separate directories decreases the chance of providing sensitive information without SSL. If the content must be put under the same directory tree, consider creating a special folder where the secure content will go. Then tell Apache to allow access to that folder only when SSL is used: <Directory /var/www/htdocs/secure> # SSL must be used to access this location SSLRequireSSL # Do not allow SSLRequireSSL to be overriden # by some other authorization directive SSLOptions +StrictRequire </Directory> A slightly more user-friendly approach to ensuring content is served over SSL is to use a few mod_rewrite rules to detect access to non-SSL content and redirect the user to the correct location, as demonstrated in Apache Cookbook by Ken Coar and Rich Bowen (O'Reilly) in Recipe 5.15 and online at http://rewrite.drbacchus.com/rewritewiki/SSL: RewriteEngine On RewriteCond %{HTTPS} !=on RewriteRule ^/secure(.*) https://%{SERVER_NAME}/secure$1 [R,L] If neither of these two choices is possible (separating the content into two virtual hosts and separate directories or placing the content in a special folder that can only be accessed using SSL), the burden of controlling SSL access will be on the shoulders of the programmers. You should check (during final site testing) that the secure content available, for example at https://www.example.com/my-sensitive-data/, cannot be accessed using a nonsecure URL, such as http://www.example.com/my-sensitive-data/. |