Getting an A+ on Qualy's SSL Labs Tester

Security, SSL Posted on

I recently spent a few hours trying to get a perfect score on Qualy's SSL Labs Tester. While I was not able to achieve a "100" in every category, I feel I got pretty close: SSL Score

This post will detail the steps for getting an A+ SSL rating using Nginx.

Generate a Certificate

The first step in securing your server with SSL is to generate an SSL certificate. At this time, the only way to get a verified certificate that will be trusted across most Internet browsers is to pay for a certificate. I chose RapidSSL, but you can choose any respectable provider.

You do not need to purchase an extended validation (EV) certificate to achieve an A+ rating. For personal blogs or sites that are not processing secure information, a regular certificate is fine. There is no additional encryption added with an EV certificate - just a pretty green bar that makes users feel better.

Depending on the provider you chose, you will need to generate a CSR and securely transmit the files onto your server. You may also need to install an intermediate certificate.

Install the Packages

In my case, I used Nginx and OpenSSL. The latest version of OpenSSL in Ubuntu's is good enough, but the latest Nginx does not support the SSL stapling we want to use later.

$ sudo apt-get install openssl

Because these instructions could easily become out of date, I recommend following the steps for compiling Nginx from source on the Nginx website.

Choose Protocols

This is arguably the hardest decision you will need to make. If you want to achieve an A+ rating, you will need to neglect a small percentage of your user base.

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

This tells Nginx to explicitly only allow TLS, which means older clients (namely IE 6 and Windows XP users) will get certificate errors when visiting your website. If any of these are your target audience, you must also add SSLv3 to the list, but you will be unable to get an A+ by doing so (you can still get an A).

Choose Ciphers

Below, we only permit 256-bit encryption schemes. The ECDHE suite gives us Forward Secrecy (although we will generate a new set of dhparams in a later step). It is important to note that these values are in order of specificity, so the ordering is from best to worst.

ssl_prefer_server_ciphers on;
ssl_ciphers AES256+EECDH:AES256+EDH:!aNULL;

Again, if you plan to support IE6 or older clients, you may need to add additional cipher suites. Doing so will reduce your rating.

Generate new dhparams

With Forward Secrecy, if an attacker gets a hold of the server's private key, it will not be able to decrypt past communications. The private key is only used to sign the DH handshake, which does not reveal the pre-master key. Diffie-Hellman ensures that the pre-master keys never leave the client and the server, and cannot be intercepted by a MITM.

All versions of Nginx as of 1.4.4 rely on OpenSSL for input parameters to Diffie-Hellman (DH). Unfortunately, this means that Ephemeral Diffie-Hellman (DHE) will use OpenSSL's defaults, which include a 1024-bit key for the key-exchange. Since we're using a 2048-bit certificate, DHE clients will use a weaker key-exchange than non-ephemeral DH clients.

We need generate a stronger DHE parameter:

$ cd /etc/ssl/certs
$ openssl dhparam -out dhparam.pem 4096

And then tell Nginx to use it for DHE key-exchange:

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

Please note: this section was adopted from Strong SSL Security on nginx at

Turn on SSL

In your Nginx configuration, you will need to activate SSL. The code below is documented inline to describe each option.

# Enable SSL on all domains - you may also want to enable this on a per-site
# basis instead if you are supporting multiple virtual hosts.
ssl on;

# Cache SSL sessions for 10m (this is about 40,000 sessions), timing them out
# after 24 hours.
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 24h;

# Set the buffer size to 1400 bytes (that way it fits into a single MTU).
ssl_buffer_size 1400;

OCSP Stapling

When connecting to a server, clients should verify the validity of the server certificate using either a Certificate Revocation List (CRL), or an Online Certificate Status Protocol (OCSP) record.

ssl_stapling on;
ssl_stapling_verify on;
resolver valid=300s;
resolver_timeout 10s;


HTTP Strict Transport Security (HSTS) instructs browsers to communicate with your website only over SSL.

# Enable HSTS
add_header Strict-Transport-Security max-age=63072000;

# Do not allow this site to be displayed in iframes
add_header X-Frame-Options DENY;

# Do not permit Content-Type sniffing.
add_header X-Content-Type-Options nosniff;

Intermediate Certificates

Depending on when you purchase your certificate, you may be issued a certificate that uses SHA1 encryption. Many browsers, such as Chrome and Safari will soon distrust these certificates and show a warning.

In my case, with RapidSSL, I needed 256-bit GeoTrust and RapidSSL intermediate certificates. It took some searching, but I was able to find the SHA 256 intermediate certificates on each of the provider's websites. You may need to contact your SSL certificate provider to obtain the SHA 256 intermediate certificate. You must have a certificate using SHA 256 to obtain an A+ on the SSL labs tester.

GeoTrust SHA256 Intermediate Certificate


RapidSSL SHA256 Intermediate Certificate


Final Configuration

If you are just looking for a copy-paste solution to get an A+, you can copy and paste the Nginx configuration below.

ssl on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 24h;
ssl_buffer_size 1400;
ssl_session_tickets off;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

ssl_ciphers AES256+EECDH:AES256+EDH:!aNULL;
ssl_prefer_server_ciphers on;

ssl_certificate /etc/ssl/;
ssl_certificate_key /etc/ssl/;
ssl_dhparam /etc/ssl/dhparam.pem;

ssl_stapling on;
ssl_stapling_verify on;
resolver valid=300s;
resolver_timeout 10s;

spdy_keepalive_timeout 300;
spdy_headers_comp 9;

add_header Strict-Transport-Security max-age=63072000;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

You will still need to generate and install the proper certificates. I hope this blog post helps you install and secure your website. Please feel free to leave a comment or suggestion!

About Seth

Seth Vargo is an engineer at Google. Previously he worked at HashiCorp, Chef Software, CustomInk, and some Pittsburgh-based startups. He is the author of Learning Chef and is passionate about reducing inequality in technology. When he is not writing, working on open source, teaching, or speaking at conferences, Seth advises non-profits.