2014-11-20 (thanks Miron - GoogleBot note)
Having a decent SSL/TLS configuration for your web server is all the rage lately. And for good reasons, too.
SSL/TLS being enabled alone does not give a good level of assurance against eavesdropping and authentication anymore. Safe ciphers, correct options, proper renegotiation, etc. are just as important, if not more (nothing like having a little “lock” icon in the browser that make you believe you’re safe - yet have an encryption cipher that is trivial to crack).
It’s complicated for everyone, even the professionals.
Anyhow, the current reference to test your website is Qualys’ tool at ssllabs and while it’s not perfect, it’s pretty good. I found quite a few guides on how to configure NGINX to get a decent score (here’s a good one), but not much about Apache. You see, Apache isn’t the cool kid on the block anymore… and the official “mod_ssl introduction” doc is missing some things.
This is an attempt to guide and explain how to do this on Apache - because it’s what I use.
Click the clicky links if you don’t know what all this stuff means :-)
Compression for SSL turned off (CRIME).
Provide the complete chain of certificates (concatenate all certificates in a file).
Ensure the certificate you get and the certificate chain are signed with SHA256 or better (i.e. not SHA1 or MD5).
Use a strong private key (RSA 2048 or above, or EC are the current recommendations).
A good cipher suite (no known-weak cipher).
Mitigate BEAST, when possible.
Perfect Forward Secrecy (even thus there’s no such thing as perfect).
SNI, maybe (not a security measure).
mod_ssl in previous Apache versions (such as 2.2 which is quite popular, still) has issues with the cipher order and selection.
Also, 2.4 has support for OCSP stapling.
Sadly, Apache 2.4 does not have support for setting the DH parameter, and at the time of writing, there’s no Apache 2.6 (unless you’re running trunk) or backport available (there’s a patch tho <https://issues.apache.org/bugzilla/show_bug.cgi?id=49559> ! and an ArchLinux backport) ;-)
Apache 2.4.7 has now been released with the DH parameter patch :-) When using the DH parameter patch with Apache, there is no need for any additional configuration. Apache will automatically use a DH param that is the same size as the private key.
Let’s get right into it!
Different distributions have different path for config files. In general it’s in /etc/httpd/* with files in /etc/httpd/conf and /etc/httpd/conf/extra. Refer to your distro documentation for more information, if you can’t find something.
It’s going to look like:
LoadModule ssl_module modules/mod_ssl.so
If you plan to support SSLv3 clients, and you use SNI, make sure they can get to the default site
While there are other ways to do this, it’s easy to ensure in the Apache config. Set max-age to whatever you decide - clients won’t connect to your site in non-SSL/TLS mode after their first visit for that amount of time. If you plan to revert that later (you really should not do that) - still - well, be careful while testing.
Header add Strict-Transport-Security "max-age=15768000"
SSLUseStapling on SSLStaplingResponderTimeout 5 SSLStaplingReturnResponderErrors off SSLStaplingCache shmcb:/var/run/ocsp(128000)
Where ca.pem is the CA certificate file (from your CA!).
In each virtual host (or the main config if no virtual hosts are used):
If like many of us, you are a startcom (startssl) user, make sure you get their SHA2-signed certificates from http://www.startssl.com/certs/class1/sha2/pem/ not the default SHA1-signed certs.
Only RC4 with TLS 1.0, or TLS 1.1 and above mitigate BEAST. However, RC4 is also considered a weak cipher. RC4 is pretty much considered broken nowadays. Since even the current Firefox does not have TLS 1.1 enabled (note that Nightly can go up to TLS 1.2 with an about:config flag) - I’m choosing to keep TLS 1.0 enabled and provide the RC4 cipher. I now only provide TLS1.2 as all recent browsers support this properly. This means also no RC4, and also that BEAST is no longer an issue.
This selection means only recent browsers/clients will be able to connect. You may still allow TLSv1 if you’re supporting older clients (<2013).
# Best but least compatible with older browsers SSLProtocol all -SSLv2 -SSLv3 -TLSv1
In particular, GoogleBot (and probably some other crawlers) does not support most recent TLS versions. Thus, you may want to keep TLSv1 enabled if you need your site to be indexed.
# Allow GoogleBot and other older clients SSLProtocol all -SSLv2 -SSLv3
If you do choose to enable SSLv3 for some reason, make sure your version of apache supports TLS_FALLBACK_SCSV. This ensures clients supporting TLS will not be tricked into falling back to SSLv3 (exposing them to the POODLE vulnerability).
Honor the cipher suite, so that clients get the best possible selection of ciphers, depending on what they support:
See https://wiki.mozilla.org/Security/Server_Side_TLS for legacy cipher support.
This is the recommended cipher suite I am using (“modern” as per Server_Side_TLS):
SSLCipherSUite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !CAMELLIA !SEED !3DES !RC4 !aNULL !eNULL !LOW !MD5 !EXP !PSK !SRP !DSS"
Well, that wasn’t so hard after all now was it?
Don’t forget to test your setup at SSL Labs for example :)
For convenience, here’s the complete config options that you’ll generally want to add to your setup (including RC4 support).
# Note: Remove -TLSv1 if you want your site to be indexed by GoogleBot SSLProtocol all -SSLv2 -SSLv3 -TLSv1 SSLCompression off SSLHonorCipherOrder on SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !CAMELLIA !SEED !3DES !RC4 !aNULL !eNULL !LOW !MD5 !EXP !PSK !SRP !DSS" SSLUseStapling on SSLStaplingResponderTimeout 5 SSLStaplingReturnResponderErrors off SSLStaplingCache shmcb:/var/run/ocsp(128000) Header add Strict-Transport-Security "max-age=15768000"
This can also go in /etc/httpd/conf/extra/httpd-ssl.conf if you have only the default virtual host, or don’t use virtual hosts, of course.
SSLCertificateChainFile "/etc/ssl/apache/sub.class1.server.ca.pem" SSLCACertificateFile /etc/ssl/apache/ca.pem