How to enable TLS 1.3 in Apache

Sun, 2018-10-28 14:32

I posted a few days ago TLS 1.3 with Nginx and Apache and mentioned that for Apache, you would need to compile Apache web server yourself. While I did some experiments with Apache, I did not write a guide on how to enable TLS 1.3 without compiling Apache yourself.

TLS 1.3 is now enabled in this blog, and after some tinkering, I could tweak a few things, and I will write how I did it.

SCARY WARNING!

Note that at the time of writing, I would consider Apache's TLS 1.3 support to be a bit flaky. I obviously don't take any responsibility in your actions nor should you risk any valuable system. I highly advice you to spin a test server to test them out.

Prerequisites

This guide is for Ubuntu 14.04 (), 14.04 (Trusty), 16.04 (Xenial), 18.04 (Bionic) and 18.10 (Cosmic). You will upgrade to Apache 2.4.37 and OpenSSL 1.1.1. If you are seeing this post weeks or months later, these version numbers wouldn't be the same.

Add Ondřej's Apache repository

At the time of writing, even Ubuntu 18.10 repository has Apache 2.4.35. We want to be the coolest kids in the block, so we use a separate PPA maintained by Ondřej Surý. He is putting an enormous effort to maintain these packages, and once you have TLS 1.3 running, I suggest you take a look at his well-deserved donations page.

To add the repo, enter these commands in terminal:

add-apt-repository ppa:ondrej/apache2
apt-get update

This will import signing keys and update the package meta information.

Now, you can simply run the following to install / update your Apache installation:

apt install apache2

You will notice that you are also upgrading your OpenSSL version. You can check if you are using the correct OpenSSL version from openssl version command. Make sure it is 1.1.1 or later.

Enable TLS 1.3

The default configuration option should have TLS 1.3 enabled by default. However, let's make double check.

In Apache, the TLS protocols are controlled by the SSLProtocol directive. The main value of this directive is set at /etc/apache2/mods-available/ssl.conf file. Locate it, and make sure you have something like all -SSLv2 -SSLv3. This is to enable all supported TLS versions, but remove ancient SSLv2 and SSLv3. While you are at it, I also suggest that you disable TLSv1 and TLSv1.1 because they are quite old protocols and the more push we make to phrase them out, the better. I'm not here to push my own security advice, so it's totally up to you.

Restart Apache

Enabling TLS 1.3 in Apache is so simple, restarting Apache can be put into its own heading:

service apache2 restart

See it in action

You can now check TLS 1.3 support from your browser developer tools or from SSL Labs Server Test.

TLS 1.3 support in Firefox
Above is a screenshot from Firefox showing TLS 1.3 support (Firefox 63). Open the Developer Panel (F12 shortcut), and go to the "Network" tab, and click on an HTTPS request that Firefox made to your server. Now, in the right-side pane, click on "Security" to see this information.

TLS 1.3 support in Chrome
TLS 1.3 support in Chrome 70+. By default, this setup will use x25519 for key exchange, and AES_GCM / CHACHA20_POLY1305 for symmetric encryption.

Changing Cipher Suite order

TLS 1.3 is easy enough to enable in Apache now. There was nothing to configure other than the SSLProtocol. TLS 1.3 got rid of several cipher suits that are future proof and secure. This is a brilliant move and makes it easier for both servers and clients to advance because we don't have a jabazillion cipher suits mix and match.

OpenSSL supports the following TLS 1.3 cipher suits, and the first 3 are used by default:

  1. TLS_AES_256_GCM_SHA384
  2. TLS_CHACHA20_POLY1305_SHA256
  3. TLS_AES_128_GCM_SHA256
  4. TLS_AES_128_CCM_8_SHA256
  5. TLS_AES_128_CCM_SHA256

In Apache, you can add, remove, and set the order of cipher suits with the SSLCipherSuite directive. SSLCipherSuite directive is used to configure the cipher suits, but to configure TLS 1.3 cipher suits, you need to specify them with a special TLSv1.3 modifier. Without this modifier, Apache/OpenSSL will assume the default TLS 1.3-specific ciphers.

In TLS 1.3 handshakes, OpenSSL (and hence Apache) uses this cipher suite:

TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256

To configure TLS 1.3 ciphers, you can use the same SSLCipherSuite directive again, but now with the modifier:

SSLCipherSuite      ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:.... # <-- The regular ciphers for TLS versions up to 1.2
SSLCipherSuite      TLSv1.3 TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384

H/T to Matthias Wirtz for this information. Before this, I had shown a different approach to configure TLS 1.3 ciphers using the SSLOpenSSLConfCmd, but it turns out you can change TLS 1.3 ciphers using the same SSLCipherSuite directive.

0-RTT

0-RTT is not supported at this time. I will update this post with more information on this

That's it, congratulations on enabling TLS 1.3 on Apache!