Configure Nginx to use TLS 1.2 and 1.3 only

last updated in Categories , , , , , ,

How do I enable and configure TLS 1.2 and 1.3 only in Nginx web server?

TLS is an acronym for Transport Layer Security. It is cryptographic protocols designed to provide network communications security. TLS used by websites and other apps such as IM (instant messaging), email, web browsers, VoIP, and more to secure all communications between their server and client. This page explains how to enable and configure Nginx to use TLS 1.2 and 1.1 version only.

How to configure and enable Nginx to use TLS 1.2 and 1.3

  1. Open the terminal application
  2. Login to Nginx server using the ssh command
  3. Edit nginx.conf file or virtual domain config file
  4. Set TLS version by editing ssl_protocols TLSv1.2;
  5. Save and close the file
  6. Restart or reload the Nginx server

A note about our set up for TLS 1.2 only in Nginx web server

I tested the server configuration with the following components:

  • Nginx version 1.14.2
  • OpenSSL version 1.1.0

As a result, this config option works the following clients only:

  • Supports Firefox 27+
  • Android 4.4.2+
  • Chrome 31+
  • Edge, IE 11 on Windows 7 or above
  • Java 8u31
  • OpenSSL 1.0.1
  • Opera 20+
  • Safari 9+

In other words, an older client from Windows XP or an older version of Android/Java won’t work.

How To enable TLS 1.2 only in Nginx web server

Edit the nginx.conf:
sudo vi /etc/nginx/nginx.conf
OR
sudo vi /etc/nginx/vhosts.d/cyberciti.biz
Update/append as follows:

Please note that the TLSv1.1 and TLSv1.2 parameters (1.1.13, 1.0.12) work only when OpenSSL 1.0.1 or higher is used. The TLSv1.3 parameter (1.13.0) works only when OpenSSL 1.1.1 built with TLSv1.3 support is used.

server {
    listen 443 ssl http2;
    server_name www.cyberciti.biz cyberciti.biz
 
    # Path to certs
    ssl_certificate /etc/nginx/ssl/cyberciti.biz.csr;
    ssl_certificate_key /etc/nginx/ssl/cyberciti.biz.key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MySSL:10m;
    ssl_session_tickets off;
    ssl_dhparam /etc/nginx/ssl/cyberciti.biz.dhparam.pem;
 
 
    ssl_protocols TLSv1.2;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
 
    # HSTS 
    add_header Strict-Transport-Security "max-age=63072000" always;
 
    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;
 
    # verify chain of trust of OCSP response using Root CA and Intermediate certs
    # ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;
 
    # replace with the IP address of your resolver
    resolver 1.1.1.1;
 
    ## rest of config ##
}

Save and close the file. For both TLS version 1.2 and 1.3 use the following in nginx config file:

    ssl_protocols TLSv1.2 TLSv1.3;

Reload or restart the nginx

Now that server configured. It is time to test our nginx config server for syntax errors:
nginx -t
Sample outputs:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Reload or restart the nginx server:
sudo systemctl restart nginx
OR
sudo service nginx restart

Test Nginx TLS 1.2 support

Run the curl command as follows:
curl -I -v --tlsv1.2 --tls-max 1.2 https://www.cyberciti.biz/

Test Nginx TLS 1.3 support

curl -I -v --tlsv1.3 --tls-max 1.3 https://www.cyberciti.biz/

*   Trying 104.20.187.5:443...
* TCP_NODELAY set
* Connected to www.cyberciti.biz (104.20.187.5) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; ST=CA; L=San Francisco; O=Cloudflare, Inc.; CN=cyberciti.biz
*  start date: Nov 28 00:00:00 2019 GMT
*  expire date: Oct  9 12:00:00 2020 GMT
*  subjectAltName: host "www.cyberciti.biz" matched cert's "*.cyberciti.biz"
*  issuer: C=US; ST=CA; L=San Francisco; O=CloudFlare, Inc.; CN=CloudFlare Inc ECC CA-2
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x558d280211d0)
> HEAD / HTTP/2
> Host: www.cyberciti.biz
> User-Agent: curl/7.65.3
> Accept: */*
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 256)!
< HTTP/2 200 
HTTP/2 200 
< date: Sun, 01 Dec 2019 19:51:39 GMT
date: Sun, 01 Dec 2019 19:51:39 GMT
< content-type: text/html; charset=UTF-8
content-type: text/html; charset=UTF-8
< set-cookie: __cfduid=d0754cfef8441ee725af158ad808a62211575229899; expires=Tue, 31-Dec-19 19:51:39 GMT; path=/; domain=.cyberciti.biz; HttpOnly; Secure
set-cookie: __cfduid=d0754cfef8441ee725af158ad808a62211575229899; expires=Tue, 31-Dec-19 19:51:39 GMT; path=/; domain=.cyberciti.biz; HttpOnly; Secure
< strict-transport-security: max-age=15552000
strict-transport-security: max-age=15552000
< x-whome: l-cbz04
x-whome: l-cbz04
< cf-cache-status: HIT
cf-cache-status: HIT
< age: 126265
age: 126265
< x-content-type-options: nosniff
x-content-type-options: nosniff
< alt-svc: h3-23=":443"; ma=86400
alt-svc: h3-23=":443"; ma=86400
< expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< server: cloudflare
server: cloudflare
< cf-ray: 53e798d6081edc89-MAA
cf-ray: 53e798d6081edc89-MAA
 
< 
* Connection #0 to host www.cyberciti.biz left intact

Test Nginx TLS 1.1/1.0 support (must fail)

In this final example, check and use Nginx use TLS 1.0/1.1:
curl -I -v --tlsv1 --tls-max 1.0 https://www.cyberciti.biz/
curl -I -v --tlsv1.1 --tls-max 1.1 https://www.cyberciti.biz/

Configure Nginx to use TLS 1.2 and 1.3 only

Understanding curl command options

  • -I : Show document header info only
  • -v : Verbose outputs
  • --tlsv1, --tlsv1.0, --tlsv1.1, --tlsv1.2, --tlsv1.3: Use given TLS version
  • --tls-max VERSION : Set maximum allowed TLS version

Conclusion

You successfully configured and enabled TLS 1.{2,3} with the Nginx web server running on Linux or Unix like systems. See Nginx web server docs here for more info.

Posted by: Vivek Gite

The author is the creator of nixCraft and a seasoned sysadmin, DevOps engineer, and a trainer for the Linux operating system/Unix shell scripting. Get the latest tutorials on SysAdmin, Linux/Unix and open source topics via RSS/XML feed or weekly email newsletter.

Start the discussion at www.nixcraft.com

Historical Comment Archive