Ayesh Karunaratne: Full-time traveler, freelance software architect and security researcher
Sun, 2018-10-21 19:20
The much-awaited TLS 1.3 is now finalized and is a proper IETF standard: RFC 8446. A huge round of applause for everyone involved. This is a massive step forward.
Web servers and cryptographic libraries are catching up, and here is how you can enable TLS 1.3 today (yes, today)!
This site is not running TLS 1.3 yet, and all these tests were done in a different throw-away server.
OpenSSL 1.1.1 is out hero here and carries the heavy work with TLS 1.3. All these tests were done on Ubuntu 18.10. It was released on Oct 18 (which happens to be an important day for me, personally too). Ubuntu 18.10 comes with OpenSSL 1.1.1, so you don't have to compile OpenSSL yourself.
I highly recommend you upgrade to Ubuntu 18.10 to get OpenSSL out of Ubuntu repositories because it is too much hassle to compile OpenSSL every time an update is released.
You can check your current OpenSSL version with
openssl version command. If you see
OpenSSL 1.1.1 11 Sep 2018 or a later version, you are good to go!
We choose Ubuntu 18.10 because it comes with OpenSSL 1.1.1. In addition, default repos contain Apache 2.4.34 and Nginx 1.15 at the time of writing.
Enable TLS 1.3 in Nginx
It doesn't take more than a minute to enable TLS 1.3 in Nginx. Nginx shipped TLS 1.3 support a few months back. All we had to do was to wait for a proper OpenSSL release that had TLS 1.3 support. OpenSSL 1.1.1 is the version we were waiting for, and it works like magic!
First, if you have not installed already, install the latest Nginx version.
apt install nginx
If you have already, make sure that the nginx version is at least 1.15:
# Should print "nginx version: nginx/1.15.5 (Ubuntu)" or later
It only takes a single change to enable TLS 1.3 in Nginx. Edit the
/etc/nginx/nginx.conf file and locate
ssl_protocols directive. You will a list of TLS versions supported. Append
TLSv1.3 to the end of this list. After the changes, it should ideally look like this:
ssl_protocols TLSv1.2 TLSv1.3;
If you want to keep supporting TLS version 1.0 and 1.1, you can keep them in the list.
While you are at it, you can also enable HTTP/2, which I have explained at the post How to enable HTTP/2 support in NGINX.
Finally, all you have left to do is restart nginx, and TLS 1.3 should be working!
service nginx restart
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.
Enable TLS 1.3 in Apache
Enabling TLS 1.3 in Apache is not that straight forward. Ubuntu ships Apache 2.3.34, which unfortunately does not support TLS 1.3. You can compile Apache with OpenSSL 1.1.1, but Apache will still complain that it doesn't know TLS 1.3 if you try to enable it.
The earliest version to support TLS 1.3 is 2.4.37. It is not properly released and is currently in dev version. For this, we now must compile Apache 2.4.37 from source, along with OpenSSL 1.1.1. If you are reading this post in a later time that Apache 2.4.37 is available in a repository, do not bother with the compilation steps below.
Compile Apache 2.4.37 from source
First, we have to configure
apr-utilpackages that Apache depends on. I'm assuming you already know what commands like
wget works. If you don't, RTFM.
Compiler and Libssl dependencies
apt install build-essential libpcre3-dev libssl1.1 libssl-dev libexpat1-dev
mkdir /usr/src/apache2 # This is we download apr, apr-util, and apache2 source.
wget https://archive.apache.org/dist/apr/apr-1.6.5.tar.bz2 # Lookup the latest version and use it if available https://archive.apache.org/dist/apr/.
# It's also a good idea to compare checksum, but we don't here to keep the post short and to the point.
tar -xvjf apr-1.6.5.tar.bz2
wget https://archive.apache.org/dist/apr/apr-util-1.6.1.tar.bz2 # Lookup the latest version at https://archive.apache.org/dist/apr/
tar -xvjf apr-util-1.6.1.tar.bz2
./configure --prefix=/usr/local/apr/ --with-apr=/usr/local/apr/
tar -xvjf httpd-2.4.37.tar.bz2
The next step is to configure Apache before the compilation step. Note that you will need tinker these configuration options to suit your needs. These settings do not correlate 1:1 with the
apache2 package you install in a repo, and I do not recommend you use this compiled version in production severs because 2.4.37 is not a proper release yet.
./configure --prefix=/opt/apache2 \
See if the configuration options throw any errors. You might need to fix them manually before trying again. You can see the config log at
config.log file. Note that if SSL requirements are not met,
mod_ssl module will not build. Check the
config.log file for any signs that the configure script complains about it.
This will now install Apache2 in
./opt/apache2/bin/httpd -k start
Above command will start the server.
To enable TLS 1.3 in your just-compiled Apache, you can edit
/opt/apache2/httpd.conf file and make sure the
SSLProtocol is setup correctly.
SSLProtocol all -SSLv3 -TLSv1, -TLSv1.1
Above is my recommended setup that it disables TLS 1.0 and 1.1 along SSL 3, leaving TLS 1.2 and TLS 1.3 active.
You can restart the server to check if Apache can now make TLS 1.3 connections! (You will need to have a proper TLS certificate and the basic TLS setup done too of course).
Similar to Nginx, I will also link to How to enable HTTP/2 support in Apache post if you do not already have HTTP/2 enabled.
TLS 1.3 support in Chrome 70+. By default, this setup will use
x25519 for key exchange, and
CHACHA20_POLY1305 for symmetric encryption.