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

**URL:** <https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436>\
**Category:** Server\
**Created:** [October 29, 2015, 7:48pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436 "2015-10-29T19:48:58Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alives](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/alives/32/1133_2.png) [@Alives](https://community.letsencrypt.org/u/Alives)\
**Post date:** [October 29, 2015, 7:48pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/1 "2015-10-29T19:48:58Z")

</div>

## WARNING

**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)](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4/2436/4)**

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

* * *

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

 ![](https://global.discourse-cdn.com/letsencrypt/original/2X/1/1dc2272c8852e759babae7ef2683e7e70bdf9027.png)

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`**

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

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 \>\>\>** ):

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

**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: [https://raymii.org/s/articles/HTTP\_Public\_Key\_Pinning\_Extension\_HPKP.html](https://raymii.org/s/articles/HTTP_Public_Key_Pinning_Extension_HPKP.html)):

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 [https://dev.ssllabs.com/ssltest/analyze.html](https://dev.ssllabs.com/ssltest/analyze.html) 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:

Enable your **`ssl.conf`** file:

```
a2enconf ssl

```

1. **Restart Apache** :

2. Test your site at [https://www.ssllabs.com/ssltest/analyze.html](https://www.ssllabs.com/ssltest/analyze.html). You’re done!

---

<div class="post-metadata">

**Author:** ![tlussnig](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/tlussnig/32/2053_2.png) [@tlussnig](https://community.letsencrypt.org/u/tlussnig)\
**Post date:** [October 29, 2015, 8:04pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/2 "2015-10-29T20:04:31Z")

</div>

Hi, this is no big deal. I could get it with [https://suche.org](https://suche.org) 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.

---

<div class="post-metadata">

**Author:** ![Alives](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/alives/32/1133_2.png) [@Alives](https://community.letsencrypt.org/u/Alives)\
**Post date:** [October 29, 2015, 8:19pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/3 "2015-10-29T20:19:56Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![eva2000](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/eva2000/32/289_2.png) [@eva2000](https://community.letsencrypt.org/u/eva2000)\
**Post date:** [October 29, 2015, 8:33pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/4 "2015-10-29T20:33:29Z")

</div>

> [@Alives](#):
>
> Yes, it's a very restrictive setup. I was just listing what it takes to get all 100%'s on their test

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

 ![](https://global.discourse-cdn.com/letsencrypt/original/2X/0/0844473df42ddb92ff0525aca25081eb68d96afa.png)

---

<div class="post-metadata">

**Author:** ![Alives](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/alives/32/1133_2.png) [@Alives](https://community.letsencrypt.org/u/Alives)\
**Post date:** [October 29, 2015, 8:38pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/5 "2015-10-29T20:38:33Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![tlussnig](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/tlussnig/32/2053_2.png) [@tlussnig](https://community.letsencrypt.org/u/tlussnig)\
**Post date:** [October 29, 2015, 8:57pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/6 "2015-10-29T20:57:59Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Alives](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/alives/32/1133_2.png) [@Alives](https://community.letsencrypt.org/u/Alives)\
**Post date:** [October 29, 2015, 10:52pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/7 "2015-10-29T22:52:00Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![rugk](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/rugk/32/19612_2.png) [@rugk](https://community.letsencrypt.org/u/rugk)\
**Post date:** [October 29, 2015, 11:30pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/8 "2015-10-29T23:30:17Z")

</div>

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 [dev.ssllabs.com](https://dev.ssllabs.com/) 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 [ssllabs.com](https://ssllabs.com).
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)](https://community.letsencrypt.org/t/http-public-key-pinning-hpkp/2450)

**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:

- [https://scotthelme.co.uk/hpkp-http-public-key-pinning/](https://scotthelme.co.uk/hpkp-http-public-key-pinning/)
- [https://en.wikipedia.org/wiki/HTTP\_Public\_Key\_Pinning](https://en.wikipedia.org/wiki/HTTP_Public_Key_Pinning)
- [https://scotthelme.co.uk/guidance-on-setting-up-hpkp/](https://scotthelme.co.uk/guidance-on-setting-up-hpkp/)
- [https://developer.mozilla.org/en-US/docs/Web/Security/Public\_Key\_Pinning](https://developer.mozilla.org/en-US/docs/Web/Security/Public_Key_Pinning)

Additionally [here](https://report-uri.io/home/tools) you get a bunch of tools for HPKP by @ScottHelme, especially the [analyse tool](https://report-uri.io/home/pkp_analyse).

---

<div class="post-metadata">

**Author:** ![rugk](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/rugk/32/19612_2.png) [@rugk](https://community.letsencrypt.org/u/rugk)\
**Post date:** [October 29, 2015, 11:50pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/9 "2015-10-29T23:50:24Z")

</div>

Some notes about your site after [testing it](https://dev.ssllabs.com/ssltest/analyze.html?d=suche.org&hideResults=on):

1. You have included a report-uri directive in your HPKP header. (`http://130.117.188.81/pkp-report`) I don’t know whether you actually [know what it is used for](https://scotthelme.co.uk/hpkp-http-public-key-pinning/#reportingpinvalidationfailures), but currently it does nothing and is insecure.  
1.1. It does nothing because the page at [http://130.117.188.81/pkp-report](http://130.117.188.81/pkp-report) 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](https://security.stackexchange.com/questions/66782/what-is-tls-version-intolerance), which is the next TLS version which you likely want to support if it’s ready.

---

<div class="post-metadata">

**Author:** ![tlussnig](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/tlussnig/32/2053_2.png) [@tlussnig](https://community.letsencrypt.org/u/tlussnig)\
**Post date:** [October 30, 2015, 3:30pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/10 "2015-10-30T15:30:05Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Alives](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/alives/32/1133_2.png) [@Alives](https://community.letsencrypt.org/u/Alives)\
**Post date:** [October 30, 2015, 4:43pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/11 "2015-10-30T16:43:17Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![NOYB](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/noyb/32/247_2.png) [@NOYB](https://community.letsencrypt.org/u/NOYB)\
**Post date:** [October 30, 2015, 8:57pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/12 "2015-10-30T20:57:12Z")

</div>

> [@Alives](#):
>
> 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.

---

<div class="post-metadata">

**Author:** ![kelunik](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/kelunik/32/359_2.png) [@kelunik](https://community.letsencrypt.org/u/kelunik)\
**Post date:** [October 30, 2015, 10:29pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/13 "2015-10-30T22:29:52Z")

</div>

You don’t need a restrictive setup to get an A+, see [https://www.ssllabs.com/ssltest/analyze.html?d=kelunik.com](https://www.ssllabs.com/ssltest/analyze.html?d=kelunik.com).

---

<div class="post-metadata">

**Author:** ![Alives](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/alives/32/1133_2.png) [@Alives](https://community.letsencrypt.org/u/Alives)\
**Post date:** [October 30, 2015, 10:45pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/14 "2015-10-30T22:45:35Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![kelunik](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/kelunik/32/359_2.png) [@kelunik](https://community.letsencrypt.org/u/kelunik)\
**Post date:** [October 30, 2015, 10:46pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/15 "2015-10-30T22:46:46Z")

</div>

Basic setup with Mozilla Intermediate and HSTS, yes.

---

<div class="post-metadata">

**Author:** ![schoen](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/schoen/32/79_2.png) [@schoen](https://community.letsencrypt.org/u/schoen)\
**Post date:** [October 30, 2015, 10:59pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/16 "2015-10-30T22:59:51Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![kelunik](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/kelunik/32/359_2.png) [@kelunik](https://community.letsencrypt.org/u/kelunik)\
**Post date:** [October 30, 2015, 11:01pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/17 "2015-10-30T23:01:19Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![eva2000](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/eva2000/32/289_2.png) [@eva2000](https://community.letsencrypt.org/u/eva2000)\
**Post date:** [October 31, 2015, 12:20am UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/18 "2015-10-31T00:20:17Z")

</div>

[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

---

<div class="post-metadata">

**Author:** ![Alives](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/alives/32/1133_2.png) [@Alives](https://community.letsencrypt.org/u/Alives)\
**Post date:** [October 31, 2015, 6:10pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/19 "2015-10-31T18:10:30Z")

</div>

I also enabled mod\_spdy losely following [https://xuri.me/2015/02/25/enabling-spdy-and-hsts-on-apache.html](https://xuri.me/2015/02/25/enabling-spdy-and-hsts-on-apache.html) and CHACHA20-POLY1305 with [https://github.com/PeterMosmans/openssl/tree/1.0.2-chacha](https://github.com/PeterMosmans/openssl/tree/1.0.2-chacha)… getting a little nuts over here.

---

<div class="post-metadata">

**Author:** ![tlussnig](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/tlussnig/32/2053_2.png) [@tlussnig](https://community.letsencrypt.org/u/tlussnig)\
**Post date:** [November 1, 2015, 10:32pm UTC](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436/20 "2015-11-01T22:32:47Z")

</div>

Hi,

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.

[Next page](https://community.letsencrypt.org/t/howto-a-with-all-100-s-on-ssl-labs-test-using-apache2-4-read-warnings/2436.md?page=2)
