One commit a day makes the bugs go away

Menu

5 easy tips to accelerate SSL

Update: following popular demand, the article now includes nginx commands :)

Update 2: thanks to jackalope from Hacker News, I added a missing Apache directive for the cipher suites.

Update 3: recent attacks on RC4 have definitely made it a bad choice, and ECDHE cipher suites got improvements.

SSL is slow. These cryptographic algorithms eat the CPU, there is too much traffic, it is too hard to deploy correctly. SSL is slow. Isn’t it?

HELL NO!

SSL looks slow, because you did not even try to optimize it! For that matter, I could say that HTTP is too verbose, XML web services are verbose too, and all this traffic makes the website slow. But, SSL can be optimized, as well as everything!

Slow cryptographic algorithms

The cryptographic algorithms used in SSL are not all created equal: some provide better security, some are faster. So, you should choose carefully which algorithm suite you will use.

28 cipher suites, that’s a lot! Let’s see if we can remove the unsafe ones first! You can see at the end of the of the list 7 ones marked as “export”. That means that they comply with the US cryptographic algorithm exportation policy. Those algorithms are utterly unsafe, and the US abandoned this restriction years ago, so let’s remove them:
‘ALL:!ADH:!EXP:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2′.

Now, let’s remove the algorithms using plain DES (not 3DES) and RC2: ‘ALL:!ADH:!EXP:!LOW:!RC2:RC4+RSA:+HIGH:+MEDIUM’. That leaves us with 16 algorithms.

It is time to remove the slow algorithms! To decide, let’s use the openssl speed command. Use it on your server, ecause depending on your hardware, you might get different results. Here is the benchmark on my computer:

We can remove the SEED and 3DES suite because they are slower than the other. DES was meant to be fast in hardware implementations, but slow in software, so 3DES (which runs DES three times) is slower. On the contrary, AES can be very fast in software implementations, and even more if your CPU provides specific instructions for AES. You can see that with a bigger key (and so, better theoretical security), AES gets slower. Depending on the level of security, you may choose different key sizes. According to the key length comparison, 128 might be enough for now. RC4 is a lot faster than other algorithms. AES is considered safer, but the implementation in SSL takes into account the attacks on RC4. So, we will propose this one in priority. Following recent researches, it appears that RC4 is not safe enough anymore. And ECDHE got a performance boost with recent versions of OpenSSL. So, let’s forbid RC4 right now!

So, here is the new cipher suite: ‘ALL:!ADH:!EXP:!LOW:!RC2:!3DES:!SEED:!RC4:+HIGH:+MEDIUM’

You can also see that the performance of RSA gets worse with key size. With the current security requirements (as of now, January 2013, if you are reading this from the future). You should choose a RSA key of 2048 bits for your certificate, because 1024 is not enough anymore, but 4096 is a bit overkill.

Remember, the benchmark depends on the version of OpenSSL, the compilation options and your CPU, so don’t forget to test on your server before implementing my recommandations.

Take care of the handshake

The SSL protocol is in fact two protocols (well, three, but the first is not interesting for us): the handshake protocol, where the client and the server will verify each other’s identity, and the record protocol where data is exchanged.

Here is a representation of the handshake protocol, taken from the TLS 1.0 RFC:

You can see that there are 4 messages exchanged before any real data is sent. If a TCP packet takes 100ms to travel between the browser and your server, the handshake is eating 400ms before the server has sent any data!

And what happens if you make multiple connections to the same server? You do the handshake every time. So, you should activate Keep-Alive. The benefits are even bigger than for plain unencrypted HTTP.

Present all the intermediate certification authorities in the handshake

During the handshake, the client will verify that the web server’s certificate is signed by a trusted certification authority. Most of the time, there is one or more intermediate certification authority between the web server and the trusted CA. If the browser doesn’t know the intermediate CA, it must look for it and download it. The download URL for the intermediate CA is usually stored in the “Authority information” extension of the certificate, so the browser will find it even if the web server doesn’t present the intermediate CA.

This means that if the server doesn’t present the intermediate CA certificates, the browser will block the handshake until it has downloaded them and verified that they are valid.

So, if you have intermediate CAs for your server’s certificate, configure your webserver to present the full certification chain. With Apache, you just need to concatenate the CA certificates, and indicate them in the configuration with this directive:

SSLCertificateChainFile /path/to/certification/chain.pem

For nginx, concatenate the CA certificate to the web server certificate and use this directive:

ssl_certificate /path/to/certification/chain.pem

Activate caching for static assets

By default, the browsers will not cache content served over SSL, for security. That means that your static assets (Javascript, CSS, pictures) will be reloaded on every call. Here is a big performance failure!

The fix for that: set the HTTP header “Cache-Control: public” for the static assets. That way, the browser will cache them. But don’t activate it for the sensitive content, beacuase it should not be cached on the disk by your browser.

Beware of CDN with multiple domains

If you followed a bit the usual performance tips, you already offloaded your static assets (Javascript, CSS, pictures) to a content delivery network. That is a good idea for a SSL deployment too, BUT, there are caveats:

your CDN must have servers accessible over SSL, otherwise you will see the “mixed content” warning

it must have “Keep-Alive” and “Cache-control: public” activated

it should serve all your assets from only one domain!

Why the last one? Well, even if multiple domains point to the same IP, the browser will do a new handshake for every domain. So, here, we must go against the common wisdom of separating your assets on multiple domains to profit from the parallelized request in the browser. If all the assets are served from the same domain, there will only be one handshake. It could be fixed to allow multiple domains, but this is beyond the scope of this article.

More?

I could talk for hours about how you could tweak your web server performance with SSL. There is alot more to it than these easy tips, but I hope those will be of useful for you!

Presenting the intermediate certificates can solve a lot of weird bugs, too. I had one with a client changing a certificate signed by Verisign, where the CA root had changed in the meantime. Fun…
SPDY is a good idea, and I’ll write about it in the future.

These settings are pretty good from a security point of view. He includes the HSTS header, and adds the HTTP -> HTTPS redirection code for websites where SSL was added recently.
But please be aware that the cipher suite selection depends on his particular OpenSSL version. I get the same cipher suites with OpenSSL 0.9.8r, but with OpenSSL 1.0.1, I get 64 different cipher suites (mostly because I have elliptic curves, SRP and Camellia algorithms).
That’s why I gave the commands, so that people can test and make their own mind.
Did you deploy the duraconf settings on your servers?

The goal was not to reduce the number of ciphers, but to select a few efficient ones. The Nginx default still uses 3DES, whch was deemed slow, does not provide RC4, which is fast and protects against the BEAST attack, and prevents the usage of MD5 for the MAC. MD5 should not be used to sign certificates, but it might (don’t take my word for it, I have not yet confirmed that) be safe, for now, as a MAC for SSL record messages, with the added benefit that MD5 is faster than SHA1.

Yes, because Linux hosts have a more recent OpenSSL versions, and a lot of delicious ciphers to taste :)
If you remove AES 256 (which, from a theoretical standpoint, has more attacks than AES 128), and Diffie Hellman key exchange, which is slower than elliptic curve Diffie Hellman. Here is the command: openssl ciphers -v ‘ALL:!ADH:!EXP:!LOW:!RC2:!3DES:!SEED:!AES256:!DH:RC4+RSA:+HIGH:+MEDIUM’

With this, you’re left with 30 ciphers. Mostly, you have Camellia, AES 128 and RC4 for transport encryption, ECDH, SRP and RSA for the key exchange. The cipher chosen will depend on a lot of things, like the client support, which type of key you use in your certificate, etc.

I don’t have enough data on the client support of ciphers (yet), but there will be more in the ebook, once it is written :)

Good article, but it is missing one of the biggest SSL acceleration options available – session renegotiation and session resumption. the best way to handle a slow handshake is to avoid it in the firstplace. this is possibly trivial or even on by default with one web server, but add more and suddenly they have to sync ssl session data between them, which requires special configuration.