SSL Labs Perfect Score for nginx

Setting up TLS certificates on nginx this days is easy, but you should spend few more minutes and configure them properly. If you do it right you should have SSL Labs perfect score of A+

I had a customer for whom we ware asked to setup Let’s Encrypt certificate and do it fast, so we generated the certificates and applied the basic configuration. The next day we had another call and we ware told that some mobile customers had some issues opening the website, so we analyzed the website using the SSL Labs online tool and got the score of B. The plan was FIX the SSL Labs score and the issues will be solved.

ssl-labs-B-score

We assume that you already have your Certificates and we need to do few more configuration changes.


Enable HTTP2 and TLS

You need to add ssl and http2 in your listen line:

server {
  listen     *:443 ssl http2;
  ...
}

Disable the old SSL protocol

SSL is very old protocol and we need to disable it,

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

Optimize cipher list

Ciphers can impact both performance and security so we need to have good cipher list. This list will probably change but for the time when I’m writing this article the list below is a good start.

We will tell nginx that we are going to use preferred cipher list and then list the preferred ciphers

ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

DH parameters

We should generate our own DH parameters with at least 2048 bits, if you use 4096 bits on your certificate please generate 4096 bits DH parameters.

mkdir /etc/nginx/certs/
openssl dhparam 2048 -out /etc/nginx/certs/dhparam.pem

Then add the following line in your nginx config

ssl_dhparam /etc/nginx/certs/dhparam.pem;

OCSP stapling

We can tell our server to get a signed message from the OCSP server and add it to the initial handshake, this way the client will be confidante that the certificate is not revoked and the browser will not need to add additional overhead the the connection.

We will get it directly from Let’s Encrypt website

wget -O /etc/nginx/certs/lets-encrypt-x3-cross-signed.pem "https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem"

And add this lines to our nginx configuration

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/certs/lets-encrypt-x3-cross-signed.pem;

Enable HSTS

To get the benefits of HTTP2 we need to use enable HSTS with allows the server to tell the client to only use HTTPS and the client will not try to communicate with HTTP for the time specified.

Add the following line to enable HSTS

add_header Strict-Transport-Security "max-age=31536000" always;

If you want to include all subdomains Add this

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

NOTE: Don’t use both.


Optimizing SSL session cache

Creating a bigger session cache will reduce the number of handshakes and we will have better performance. The default time is 5 minutes and we will increase it to 4 hours.

As a reference 1MB cache will hold around 4000 sessions.

We will add 40MB of shared cache with 4 hours of session timeout.

ssl_session_cache shared:SSL:40m;
ssl_session_timeout 4h;

Enable session tickets

This is alternative to session cache, if a client has a session ticket it can be presented to the server and the re-negotiation is not necessary.

Add the following to the config

ssl_session_tickets on;

Finally the whole config file

server {
 # Enable HTTP2 and TLS
 listen *:443 ssl http2;

# Tell client which ciphers are available
 ssl_prefer_server_ciphers on;
 ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

# Use our own DH params
 ssl_dhparam /etc/nginx/certs/dhparam.pem;

# Enable OCSP stapling
 ssl_stapling on;
 ssl_stapling_verify on;
 ssl_trusted_certificate /etc/nginx/certs/lets-encrypt-x3-cross-signed.pem;

# Enable HSTS
 add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# Optimize session cache
 ssl_session_cache shared:SSL:40m;
 ssl_session_timeout 4h;

# Enable session tickets
 ssl_session_tickets on;
 
 ......
}

ssl-labs-A+-score

Now we got A+, the website performance was much better and no more issues opening the website.

Nginx SSL module
SSL Labs Server Test