HOWTO: A+ with all 100%'s on SSL Labs test using apache2.4 (READ WARNINGS)


This is a restrictive setup that will block access to some/many clients. Please evaluate your site and client base before enabling this! Read eva2000’s reply below first: HOWTO: A+ with all 100%'s on SSL Labs test using apache2.4 (READ WARNINGS)

Use at your own risk, I have no idea what I am doing!

I finally got all 100%'s on my scores…

Here’s my config for apache2.4:

  1. 4096 bit key:
    You will need to generate a 4096 bit key instead of the default 2048 bit key to get the key exchange to 100%. To do this, run letsencrypt-auto with this flag: --rsa-key-size 4096

    ./letsencrypt-auto --agree-dev-preview --server auth --rsa-key-size 4096

  2. SSL Settings:
    Add these directives to your apache2 config in the vhost section:

    SSLEngine on
    SSLCompression off
    SSLCipherSuite “HIGH:!aNULL:!MD5:!3DES:!CAMELLIA:!AES128”
    SSLHonorCipherOrder on
    SSLProtocol TLSv1.2
    SSLUseStapling on

  3. SSL Certificate and Key File Settings:
    Also add these directives to your apache2 config in the same vhost section. Keep in mind you need to update the path to your specific certificate and key that relate to your domain (<<< YOUR DOMAIN HERE >>>):

    SSLCertificateFile “/etc/letsencrypt/live/<<< YOUR DOMAIN HERE >>>/fullchain.pem”
    SSLCertificateKeyFile “/etc/letsencrypt/live/<<< YOUR DOMAIN HERE >>>/privkey.pem”

  4. DH parameters:
    Generate >=4096 dhparams using your openssl binary. This will take some time:

    openssl dhparam -out /etc/ssl/private/dhparams_4096.pem 4096

If you have openssl >= 1.0.2d installed (type openssl version to find out), you can use the following line in your apache2 vhost config:

SSLOpenSSLConfCmd DHParameters "/etc/ssl/private/dhparams_4096.pem"

If you do not have openss >= 1.0.2d, you will need to append your dhparameters to the bottom of your certificate file:

cat /etc/letsencrypt/live/<<< YOUR DOMAIN HERE >>>/fullchain.pem \
    /etc/ssl/private/dhparams_4096.pem > \
    /etc/letsencrypt/archive/<<< YOUR DOMAIN HERE >>>/fullchain_dhparams_4096.pem

Then you will use this file in place of your SSLCertificateFile above:

SSLCertificateFile "/etc/letsencrypt/archive/<<< YOUR DOMAIN HERE >>>/fullchain_dhparams_4096.pem"

Keep in mind that if you manipulate the certificate (issue a new one, etc), you will need to repeat this step as the dhparams will not be added to that certificate!

  1. Headers:
    You need to set a Public-Key-Pin header. Generate the first pin against the letsencrypt chain cert with the following code (read more here:

    openssl x509 -noout -in /etc/letsencrypt/live/<<<< YOUR DOMAIN HERE >>>>/chain.pem -pubkey |
    openssl asn1parse -noout -inform pem -out /tmp/fingerprint.key;
    openssl dgst -sha256 -binary /tmp/fingerprint.key | openssl enc -base64

The next pin comes from your private key. You should keep this key in a safe place:

openssl x509 -noout -in /etc/letsencrypt/live/<<<< YOUR DOMAIN HERE >>>>/privkey.pem -pubkey | \
openssl asn1parse -noout -inform pem -out /tmp/fingerprint.key;
openssl dgst -sha256 -binary /tmp/fingerprint.key | openssl enc -base64

You will use these fingerprints in the section below (<<< YOUR CUSTOM PIN HERE >>>).

I haven’t figured out a good programmatic way to get the chain cert keys, but I have found that you can get them with by analyzing your own site once it’s already running.

Also add these directives to your apache2 config in the same vhost section:

Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure
Header always set Public-Key-Pins "pin-sha256=\"<<< YOUR CHAIN PIN HERE >>>=\"; pin-sha256=\"<<< YOUR PRIVATE KEY PIN HERE >>>\"; max-age=31536000; includeSubDomains"
Header always set X-Frame-Options SAMEORIGIN
Header always set Strict-Transport-Security "max-age=31536000; includeSubdomains; preload"
Header always set X-Content-Type-Options nosniff
  1. SSL Stapling Cache:
    Add the following line to your ssl.conf /etc/apache2/conf-available/ssl.conf file:

    echo ‘SSLStaplingCache shmcb:/tmp/stapling_cache(2097152)’ >>

Enable your ssl.conf file:

a2enconf ssl
  1. Restart Apache:

    service apache2 restart

  2. Test your site at You’re done!


Hi, this is no big deal. I could get it with to.
But there are two points:

  • Did you check what happen if IE try to negotiate with DH>=4096 bits ?
    I prefer A+ 100% 100% 100% 90%. Because AES128 is not really weaker than AES256.
    But with this setup you block to many clients specially Google bot.
    So this should also be mentioned here. Much more save is if you can not find out
    the server version and have all ports safe.

Yes, it’s a very restrictive setup. I was just listing what it takes to get all 100%'s on their test.

I see Googlebot/2.1 in my logs now on the SSL site, so it seems to support this configuration, but I agree MANY other clients won’t be able to negotiate.

1 Like

i’d warn folks as 100% in all tests can be dangerous to a site’s livelihood and traffic…

the proper way is to fully analyse all sites traffic and browser breakdown for sites you intend to deploy SSL on and make sure your web site traffic won’t be adversely affected…

Google Analytics can give you a proper breakdown of web browser and browser version and OS stats i.e. for one of my sites broken down by WinXP vs non-WinXP and then by specific browsers and their versions

1 Like

Agreed. I’ve linked to your post in a warning header. Thanks for the Analytics reference too, that’s a great idea.

1 Like

Hi, at least there is one gap in your setup you should read a little bit more about “Public-Key-Pins”.
You pin only one key and for very long time frame. All documentations mention that you should
ALWAYS add an backup key that is offline that can be used in replacement in case of another
ssl gau like heartbeat.

1 Like

Thanks… that’s left from me hastily trying things to get to 100. I updated it, but please check it for correctness. I also threw another disclaimer at the top that I’m an idiot, instructing people to not follow me.

Some (important) general notes about the first post…

  1. Do not pin your private key!
  2. HPKP is risky. You should always understand what it is, how it works and what effects this has/can have before using it on your (productional) server.
  3. @tlussnig is right: You have to add a backup key. Otherwise this disables the added security by HPKP, so it’s just useless. You should use to test this with the latest version of SSLLabs test as this has integrated more tests of headers like HSTS and HPKP. Edit: The SSLLabs version with extended HPKP test is now stable and accessible at
  4. Currently there is an important thing you should know when using HPKP with Let’s Encrypt, which can - in the worst case - break your whole site and prevent users from accessing your site. More information here:
    HTTP Public Key Pinning (HPKP)

The most important thing: Do not follow guides just to get 100% of something. Think about what you actual do at your server!

Here are some good resources for reading about HPKP:

Additionally here you get a bunch of tools for HPKP by @ScottHelme, especially the analyse tool.


Some notes about your site after testing it:

  1. You have included a report-uri directive in your HPKP header. ( I don’t know whether you actually know what it is used for, but currently it does nothing and is insecure.
    1.1. It does nothing because the page at returns a 404 error, so it does not seem to exist.
    1.2. It is insecure, because it does not use HTTPS. And I also don’t know why you use the IP address there. That’s not necessary and obviously prevents using HTTPS there.
    You should use a normal HTTPS address, because the attack scenario HPKP wants to protect against includes an attacker monitoring all traffic from a clients device. WIthout HTTPS he can just tamper the reports.
    You may say that sending this reports could also trigger an (HPKP) error, but this is good and by design. If the clients follow the specification they should try to send such reports later again.
  2. To be even more secure you could enable OCSP.
  3. Currently your server seems to accept non-existent TLS versions including TLS 1.3, which is the next TLS version which you likely want to support if it’s ready.
  1. I fully know that i did currently not have an servlet behind the reporting url. But 404 are logged so you checked it last nicht 0:30 and 0:50.
  2. If there is something to report than possible there is an attacker between the client and my host:
    a) DNS-Spoofing
    b) Man in the middle
    So the client have no secure connection to the host. But http: to the IP is not affected by key pinning / hsts and allow the client to at least try to send the data without an SSL error.
  3. OCSP stapling is enabled and OCSP,CRL also.
  4. No if only accept TLSv1.2 it is TLS version intolerance to 1.3 and that is marked orange because i the near future server should support it.

This is great commentary and I have learned a lot from the comments, but I feel I should remove this post as it’s dangerous and misleading at this point.

No. I think it is very insightful. Please leave it up.

Personally I think that any client that does not support encryption require to get an A+ grade is broken, out of date, and deserves to be locked out, blocked, left out in the cold, etc. Keep up to date or get left behind I say.


You don’t need a restrictive setup to get an A+, see


Right, but when you go for 100’s it gets very restrictive. The basic apache setup gets you an A+ iirc.

Basic setup with Mozilla Intermediate and HSTS, yes.

1 Like

I’m curious about the 4096-bit RSA key and Diffie-Hellman parameters. In most current keylength recommendations those would be considered disproportionate to the security levels of other parts of the system. Would the SSL Labs site give an A+ for a 2048-bit RSA key and 2048-bit DH parameters? Do you have to go all the way to 4096 and 4096 for the A+?

I believe @kelunik’s setup is showing an A+ right now with 2048 and 2048.


Yes, 2048 and 2048 is enough for an A+.

[quote=“kelunik, post:17, topic:2436, full:true”]
Yes, 2048 and 2048 is enough for an A+.
[/quote] Yup it is, provided optimal cipher preferences the difference between A and A+ is usually whether HSTS is enabled or not

I also enabled mod_spdy losely following and CHACHA20-POLY1305 with… getting a little nuts over here.


after your comments of hpkp report i change the handling.
Now if gets logged and return an
405 “Method not Allowed” for anything other than POST
201 “Created” if there was an POST call.