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.
Generating the certificate/keys is out of scope for this post.
What you want your config to include
This is as of 2013-10 - this stuff evolves over time
Click the clicky links if you don’t know what all this stuff means :-)
- OCSP stapling
- 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.
- Mitigiate POODLE
- Perfect Forward Secrecy (even thus there’s no such thing as perfect).
- SNI, maybe (not a security measure).
Notes about Apache versions (=> use 2.4 or above)
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.
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/extra. Refer to your distro documentation for more information, if you can’t find something.
Check mod_ssl is loaded (duh!)
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
Enable HSTS everywhere
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"
Enable OCSP stapling
In the main SSL config
SSLUseStapling on SSLStaplingResponderTimeout 5 SSLStaplingReturnResponderErrors off SSLStaplingCache shmcb:/var/run/ocsp(128000)
In each virtual host (or the main config if no virtual hosts are used)
ca.pem is the CA certificate file (from your CA!).
Turn off SSL compression (CRIME mitigation)
Provide the SSL certificate chain to the client directly
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 startssl not the default SHA1-signed certs.
Use a (current as of 2014-10) good cipher suite
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.
Enable only recent TLS protocols
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).
Cipher suite settings
Honor the cipher suite, so that clients get the best possible selection of ciphers, depending on what they support:
Legacy ciphers support
See Mozilla 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"
The end & TL;DR; copy-pastable configs
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