Getting a perfect score on the SSL Labs Server Test
I decided to take it as a challenge to get a full perfect score on the de facto standard of SSL implementation quality, the Qualys SSL Labs Server Test.
Update (2025-06-04): changed the domain name and modernized configuration.
Needless to say, getting a perfect score is not without cost. For example, many browsers will be incapable of accessing the site. For this reason, I decided to use a separate domain name: ssl100.quantum5.ca, which also runs on a separate IPv6 address to prevent any contamination on this website (there is no IPv4 since addresses are expensive), so you will need IPv6 access.
This is the configuration I used. Think thrice before copying, since it’s rather extreme, and will break your site for some users.
ssl_certificate /etc/letsencrypt/live/ssl100.quantum5.ca/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ssl100.quantum5.ca/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/ssl100.quantum5.ca/chain.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_conf_command Ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!AES128:!SHA";
ssl_ecdh_curve secp384r1;
ssl_dhparam /etc/nginx/dhparam4096.pem;
ssl_session_cache shared:SSL:4m;
ssl_session_timeout 1h;
add_header Strict-Transport-Security max-age=31536000 always;
add_header Content-Security-Policy "default-src 'self'" always;
add_header X-Frame-Options SAMEORIGIN always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
Effectively, this configuration allows only TLSv1.2 and TLSv1.3 with “256-bit”
and equivalent strength ciphers. This is achieved using ssl_ciphers
for
TLSv1.2 and ssl_conf_command Ciphersuites
for TLSv1.3.
We also need to perform the key exchange with a Diffie–Hellman parameter ≥ 4096
bits or the elliptic curve equivalent on the secp384r1
curve, equivalent to
7680 bits. I also had to get Let’s Encrypt to issue a 4096-bit RSA certificate.
Note that in 2025, OCSP is being phased out. While the original 2017 version of this post used OCSP stapling with must-staple in the certificate as best practice, this is no longer possible or recommended—see Let’s Encrypt’s announcement for more details.
The security headers are fairly standard, and securityheaders.io has a fairly decent explanation for all of them.