Getting an A+ in Qualys SSL Labs

Comments None

As you may notice, this site (and all others in personal domains I’m accessible on) currently get the famed A+ rating on Qualys SSL Labs.

I use Nginx, with a Namecheap-distributed domain-validated Thawte SSL123 certificate for the main domain (and one or two others), as they have by far the MOST widely approved CA cert by default, and I use Let’s Encrypt certs for everything else.

Here’s how I do it, and some considerations to make.

First, use a hierarchical structure:

mkdir -p /etc/nginx/ssl/{key,crt,csr} && chmod 700 /etc/nginx/ssl/key

When generating my key (for CSRs, etc.) I always use a 4096-bit key (note that Let’s Encrypt automatically generates a key for you, 2096-bit. Sad trombone sound here.). This step, as you might have guessed, is going to not be applicable if you’re using Let’s Encrypt (see my post about it for more details; I symlink to the LE key from /etc/nginx/ssl/key/):

openssl openssl -out /etc/nginx/ssl/key/domain.tld.key 4096

Replacing, of course, domain.tld with your actual domain.

Then, we need to generate a custom DH paramaters file (because of Logjam which thankfully is easily thwarted for services):

openssl dhparam -out /etc/nginx/ssl/key/dh4096.pem 4096

Generate your CSR (also not applicable for Let’s Encrypt):

openssl req -new -sha512 -key /etc/nginx/ssl/key/domain.tld.key -out /etc/nginx/ssl/csr/domain.tld.csr

Submit your CSR, wait for your certificate, etc. Note that you then need to combine your new certificate and your CA’s intermediate certificate (again, not applicable for Let’s Encrypt):

cat /etc/nginx/ssl/crt/domain.tld.crt /etc/nginx/ssl/crt/ca.intermediate.crt > /etc/nginx/ssl/crt/domain.tld-bundle.crt

The order of certificates for the cat command is important!

(You may have to look around to find a CA’s intermediate certificate, or they may bundle it with the cert when they deliver it. For Thawte, you’ll actually want to use this one or this one depending on which CA signed your certificate, NOT any others; they use deprecated options, we want SHA-2. The nginx -t command will complain about the ssl_stapling directive not verifying if you have the wrong CA certificate. You can find all of Thawte’s intermediate certs here)

Then you can set up your nginx vhost with this as a base (NOTE: this is for a default server block! See below0 before just copy-pasting and blindly restarting):

 listen [::]:80 ipv6only=off default_server;
  listen [::]:443 ssl ipv6only=off default_server;
  server_name domain.tld; 

  ## SSL ##
  ssl_certificate /etc/nginx/ssl/crt/domain.tld-bundle.crt;
  ssl_certificate_key /etc/nginx/ssl/key/domain.tld.key;
  ssl_session_timeout  5m;
  ssl_protocols TLSv1.1 TLSv1.2;
  ssl_dhparam /etc/nginx/ssl/key/dh4096.pem;
  ssl_prefer_server_ciphers   on;
  ssl_session_cache shared:SSL:10m;
  # HSTS #
  # Uncomment below and remove the other add_header if you have a cert which serves multiple domains.
  #add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
  add_header Strict-Transport-Security "max-age=31536000";
  ssl_stapling on;
  ssl_stapling_verify on;
  ssl_trusted_certificate /etc/nginx/ssl/crt/domain.tld-bundle.crt;

  # other configuration here, e.g. root /some/path; etc.

Now run nginx -t to test the configuration. You should see something like:

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

If it tests OK, restart (NOT reload!) Nginx.

After you’ve restarted Nginx (and made sure you allow 443/TCP through your firewall), you can now test:

curl -sIL https://domain.tld

Should return an “HTTP/1.1 200 OK” on the first line (along with some other useful information).

openssl s_client -connect domain.tld:443 2>&1 < /dev/null | grep 'Verify return code'

Should return “Verify return code: 0 (ok)”. If so, you’re all set- go ahead and test your site on Qualys’ SSL Labs!

0 If “nginx -t” returns an error, it should tell you what is wrong. But MOST likely, your distro supplied a default server block already (and the error message for that can be confusing, saying something is already listening on the port, etc.). You can either comment out the entire server{…} block in /etc/nginx/nginx.conf (it may be in /etc/nginx/sites-available/default, etc. as well) OR remove the ipv6only=off default_server sections in the above snippet/vhost. Your call.

Categories Meta, InfoSec


There are currently no comments on this article.


Enter your comment below. Fields marked * are required. You must preview your comment before submitting it.

← Older Newer →