HTTPS just got faster and safer thanks to the release of TLS 1.3 by IETF (RFC 8446) in August 2018. TLS 1.3 is now the latest version of the TLS protocol. This tutorial will be showing you how to enable TLS 1.3 in Nginx web server on Ubuntu 18.04 and Ubuntu 16.04.
Update: There’s an easier way to enable TLS 1.3. See this article: How to easily enable TLS 1.3 in Nginx on Ubuntu 18.10, 18.04, 16.04, 14.04
TLS 1.3: Improved Performance and Security
Performance-wise, TLS 1.2 needs two round trips to establish HTTPS connection. With TLS 1.3, only one round trip is required. TLS 1.3 also supports zero round trip mode (0-RTT session resumption), allowing clients who have previously connected to your website to send HTTP request on the first message to the server. This makes a big difference for users on mobile networks or at far distant locations.
In terms of security, TLS 1.3 removed support for old cipher suites, which is responsible for exploits like ROBOT attack. As such server admins can no longer add old cipher suites in TLS 1.3 to appease users of old web browsers. This, of course, is an oversimplified explanation. CloudFlare has a good detailed explanation of TLS 1.3.
Enable TLS 1.3 in Nginx on Ubuntu 18.04, Ubuntu 16.04
There are two requirements when it comes to enable TLS 1.3 with Nginx.
- Your Nginx version must support TLS 1.3. That means nginx 1.13 or above.
- Nginx needs to either be built with OpenSSL 1.1.1 , or runs with OpenSSL 1.1.1 .
The second requirement may sound confusing, so let me give you two examples.
- Ubuntu 18.04 ships with OpenSSL 1.1.0. Replacing the system OpenSSL library isn’t a good idea, but you can download OpenSSL 1.1.1 source code and compile Nginx with OpenSSL 1.1.1 source code to enable TLS 1.3.
- Arch Linux currently ships with OpenSSL 1.1.1, but the Nginx package in Arch repository is actually built with OpenSSL 1.1.0. In this case, Nginx isn’t built with OpenSSL 1.1.1, but it runs with OpenSSL 1.1.1.
Now let’s see how to compile Nginx with OpenSSL 1.1.1 on Ubuntu 18.04 and Ubuntu 16.04.
1. Adding the Official Nginx Repository
Instead of downloading the source tarball and compiling it with make
, I’m going to add the official Nginx repository to my Ubuntu server and then create a deb package from source code. In this way, I don’t need to manually add a long list of configuration parameter to the configure
command. Also there will be a handy systemd service file within the deb package.
First fetch the Nginx GPG key and import it to Ubuntu.
wget http://nginx.org/keys/nginx_signing.key sudo apt-key add nginx_signing.key
Then create a source list file for Nginx repo.
sudo nano /etc/apt/sources.list.d/nginx.list
Add the following two lines into the file. The deb-src
line allows us to download Nginx source packages with apt source
command. Bonic
is the codename for Ubuntu 18.04. If you are using Ubuntu 16.04, replace it with xenial
. (Note: This repository doesn’t support 32 bit OS.)
deb [arch=amd64] http://nginx.org/packages/mainline/ubuntu/ bionic nginx deb-src http://nginx.org/packages/mainline/ubuntu/ bionic nginx
To save a file in Nano text editor, press Ctrl O
, then press Enter to confirm. To exit, press Ctrl X
. Then update local package index.
sudo apt update
Now the Nginx official repository is added to Ubuntu server.
2. Download Nginx and OpenSSL Source Code
We will make a nginx
directory under /usr/local/src/
to store the Nginx sources and then cd
into that directory.
sudo mkdir /usr/local/src/nginx cd /usr/local/src/nginx/
Download Nginx source package with the command below:
sudo apt install dpkg-dev sudo apt source nginx
Check out the downloaded files.
ls
Output:
nginx-1.15.3 nginx_1.15.3-1~bionic.dsc nginx_1.15.3-1~bionic.debian.tar.xz nginx_1.15.3.orig.tar.gz
Then clone the OpenSSL github repository.
cd /usr/local/src sudo apt install git sudo git clone https://github.com/openssl/openssl.git cd openssl
Next, list all branches and switch to the 1.1.1 stable branch.
git branch -a sudo git checkout OpenSSL_1_1_1-stable
3. Edit Nginx Compile Rules
Edit Nginx compile rules file.
sudo nano /usr/local/src/nginx/nginx-1.15.3/debian/rules
Find config.status.nginx: config.env.nginx
section. Add the following text at the end of CFLAGS line. Note that the following text isn’t a line by itself.
--with-openssl=/usr/local/src/openssl
Save and close the file.
4. Compile Nginx
Make sure you are in the Nginx source directory.
cd /usr/local/src/nginx/nginx-1.15.3/
Install dependencies to build our Nginx deb package.
sudo apt build-dep nginx
Now use the following command to build the deb package.
sudo dpkg-buildpackage -b
If you see the following error,
missing initializer for field 'md_ctrl' of 'EVP_MD {aka const struct evp_md_st}
Then edit the auto/cc/gcc
file.
sudo nano /usr/local/src/nginx/nginx-1.15.3/auto/cc/gcc
Comment out the following line. The -Werror
flag makes GCC treat warnings as errors.
CFLAGS="$CFLAGS -Werror"
Then rerun the build command. Once the build is complete, there will be a Nginx deb package in /usr/local/src/nginx/
directory. If you have installed Nginx before, it’s time to remove the old version and then install the new version.
sudo apt remove nginx nginx-common nginx-full
cd /usr/local/src/nginx/
sudo dpkg -i nginx_1.15.3-1~bionic_amd64.deb
Now let’s start Nginx.
sudo systemctl start nginx
If you see the following error message.
Failed to start nginx.service: Unit nginx.service is masked.
Then unmask nginx and issue the start command again.
sudo systemctl unmask nginx
Note that the Nginx process might run as user nginx
or www-data
. This can be changed by editing the first line in /etc/nginx/nginx.conf
file. Just make sure Nginx run as the same user with PHP-FPM.
Now check the config arguments of Nginx.
sudo nginx -V
As you can see, we have the latest version of Nginx built with OpenSSL 1.1.1.
5. Enable TLS 1.3 in Nginx Server Block
Now I assume that you have already enabled HTTPS for your Nginx server block. The syntax to enable TLS 1.3 is fairly easy. Open your Nginx server block file in /etc/nginx/conf.d/
directory or /etc/nginx/sites-enabled/
directory. Find the following line.
ssl_protocols TLSv1.2;
Add TLSv1.3
to the list of protocols.
ssl_protocols TLSv1.2 TLSv1.3;
Then add the following 3 cipher suites to your existing cipher suites.
TLS-CHACHA20-POLY1305-SHA256 TLS-AES-256-GCM-SHA384 TLS-AES-128-GCM-SHA256
like so:
ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:TLS-AES-128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
Save and close the file. Then test Nginx configuration and reload.
sudo nginx -t sudo systemctl reload nginx
It’s unlikely that Ubuntu 18.04 would switch to OpenSSL 1.1.1, so if you upgrade Nginx with sudo apt upgrade
command, TLS 1.3 will be gone. It’s a good idea to hold Nginx from being upgraded by apt
with this command:
sudo apt-mark hold nginx
Update: As of Nginx 1.15.4, you can enable 0-RTT with OpenSSL by adding the following directive in the ssl server context. The default value is set to off
. In the previous version 1.15.3, it can only be used with BoringSSL.
ssl_early_data on
Enable TLS 1.3 in Google Chrome
Currently, Firefox 62 and Chrome 69 only support draft 28 of TLS 1.3. OpenSSL 1.1.1 supports the final version of TLS 1.3. Implementations based on draft version and the final RFC version do not interoperate with each other.
To test our Nginx server now, we need to install the beta version of Google Chrome and enable the final version of TLS 1.3. Once you have Chrome beta installed, Enter chrome://flags/#tls13-variant
in the address bar and switch from default
to Enabled (Final)
. Then relaunch Google Chrome for the change to take effect.
Now visit your TLS 1.3 enabled website in Google Chrome beta and press Ctrl Shift I
to open the developer tools page. Go to Security
tab. You can see the version of TLS in use.
Firefox is said to ship the final version of TLS 1.3 in Firefox 63, scheduled for October 2018. In Chrome 70, the final version of TLS 1.3 will be enabled for outgoing connections.
Update: Chrome 70 added support for the final version of TLS 1.3, but it by default is stilling using draft 28 of TLS 1.3.
Enable TLS 1.3 with CloudFlare
If you are using CloudFlare CDN (Content Delivery Network), then your website is already using TLS1.3. In CloudFlare dashboard, select the crypto
tab and you will see the option to enable/disable TLS 1.3. You can also enable 0-RTT. CloudFlare supports both the draft 28 version and the final version.
That’s it! I hope this tutorial helped you enable TLS 1.3 in Nginx on Ubuntu 18.04 and Ubuntu 16.04. Take care.
Rate this tutorial
[Total: 27 Average: 4.3]