The Best HTTPS Configuration

June 22, 2015

Nowadays, the web is moving towards making HTTPS mandatory across all websites. Initiatives like Let’s Encrypt that offer dead-simple https installation, or Root CAs like StartSSL that offer unlimited free certificates or even browsers like Google Chrome that already started deprecating HTTP all contribute into going towards this direction. Many of us think this is the correct way. An HTTPS-only web provides a lot of great advantages over the traditional, HTTP one. However, just because you can see that little green https:// in your address bar doesn’t mean you’re secure. There is a vast amount of possible SSL/TLS configurations that a system administrator can make that range from the most secure one yet, all the way to “Rebranded HTTP”. Currently, configuring a web server to be really secure is increasingly difficult and requires the administrator to always watch the latest news for the upcoming attacks and deprecations that may require a change in the configuration. Fortunately, tools like Qualys’ SSL Server Test make the job a little bit easier, as you can run that test against your (or anybody else’s) servers and see a little nice grade on how well you did. This grade can range from A+ all the way to F, or even T. At least that’s how low I’ve seen it go. Maybe you can make an even worse configuration.. ;-) Now getting an A+ is not really difficult and ensures that your website is relatively secure, at least as far as HTTPS is concerned. Let’s see how we can get this grade in Apache 2.2.22 on Debian Jessie 8.0 with mod_ssl. For this to work, you need a valid HTTPS Certificate from a Trusted Certificate Authority. In order to start for free, you can use StartSSL. Now you need to make sure this certificate is signed with SHA-2 or SHA-256 (actually the latter is a part of the first). After that, you can create a VritualHost for your secure website:

<VirtualHost *:443>
    DocumentRoot "/var/www/"

The above example will create a basic HTTP website for the domain listening on port 443. Now the next lines can be added below the ServerName:

SSLEngine on

This tells Apache to enable HTTPS for this VirtualHost.

SSLCertificateFile /path/to/your.crt
SSLCertificateKeyFile /path/to/your.key
SSLCertificateChainFile /path/to/

The above will tell the webserver where is the certificate, the private key, and the certificate chain file. I assume you already have these files.

SSLProtocol -ALL +TLSv1.2

This explicitly enables only TLS v1.2 for all HTTPS connections, the latest stable version of TLS that is supported by the latest stable version of OpenSSL.

SSLHonorCipherOrder on

With this set to on, the web server will try to honor the order of the ciphers in this configuration file. With this current setup, this is not really necessary, but it is recommended to have it set.

SSLCipherSuite ALL:!aNULL:!eNULL:!EXP:!LOW:!MD5:!RC4:!SHA1:!DH

Here is the most important line of all. The supported ciphers. In this line we tell Apache to use ALL ciphers, except the NULL ciphers, EXPort Grade (Weak) Cryptography, ciphers marked as LOW-strength, and finally, everything that uses MD5, RC4, SHA1 and DH (Diffie-Hellman). One could argue that a white-list is better than a black-list, but this is easier to maintain, in a sense that if an attack comes up against a specific cipher in the future, you can easily block it by appending it in the end.

SSLInsecureRenegotiation off

This will tell the server to never renegotiate keys with a client in an insecure way.

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

And finally, enable HSTS. That is a special header that requires mod_header to be enabled (use the command a2enmod header). If a browser visits the website over HTTPS once, it will only visit this website again for the next 31536000 seconds using HTTPS and never falls back to HTTP. Additionally, with includeSubDomains you can tell the browser to also treat all subdomains in the same way (HTTPS-only).

Now, after running a service apache2 restart, and running a test for your website, you should see an A+ with results similar to this. Congratulations on enabling one of the most secure HTTPS configurations on your website!

Getting an A+

But is this the best HTTPS configuration you can have? Absolutely not. And I’m not talking about the remaining 10% in “Cipher Strength”. You see, apart from this grade, there are many more things to consider when enabling HTTPS with configurations like this. If you take a look for example at the “Handshake Simulation” area of the detailed report, you see that using this, you leave out some large parts of the Internet Population, like:

  • Android 4.3.X and below (Late 2013)
  • Baidu Crawler (Early 2015)
  • Internet Explorer 10 and below (Late 2013)
  • Java 7 and below (Early 2014)
  • Mac OS X & iOS w/ Safari 5 (Mid 2010)

Some of these devices are old and some are newer. If you set the configuration above, all these users will never be able to use your HTTPS website. This is clearly a business decision. Do you want to block all these users in order to be more secure or do you want to relax your requirements a little bit but make sure more people have access to the website? If it’s a personal blog it may be okay, but if you’re a huge website like Google Search you might risk even going as low as a B to enable access to more customers. If you consider that it’s nearly impossible to update every Android Phone to 4.4+, then pretty much most Android users are gone! With an iPhone, more people have access, since people using an iPhone 3GS or newer still can visit the website securely. If you exclude the Baidu Crawler, you might appear lower in the Baidu Search Engine Ranks. Again, this is a business decision and depends on how much security you’re willing to sacrifice to enable access to more customers. If you’re a System Administrator it’s probably a good idea to consult an executive before making this decision on your own..

Update: Mozilla has a website dedicated to helping web server administrators picking the proper Cipher Suite. You can view that here. Thanks 0xdiba.