# "A" Grade SSL/TLS with Nginx and StartSSL

**URL:** <https://www.ruby-forum.com/t/a-grade-ssl-tls-with-nginx-and-startssl/246439>\
**Category:** NGINX\
**Created:** [October 12, 2013, 11:55pm UTC](https://www.ruby-forum.com/t/a-grade-ssl-tls-with-nginx-and-startssl/246439 "2013-10-12T23:55:43Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sadaf\_N](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/858c86/32.png) [@Sadaf\_N](https://www.ruby-forum.com/u/Sadaf_N)\
**Post date:** [October 12, 2013, 11:55pm UTC](https://www.ruby-forum.com/t/a-grade-ssl-tls-with-nginx-and-startssl/246439/1 "2013-10-12T23:55:43Z")

</div>

Hi Nginx folks,

I spent some time hacking on my SSL conf recently. Nothing new, but I  
figured I’d share it with the group:

> **["A" Grade SSL/TLS with Nginx and StartSSL - Quelques digressions sous GPL](https://jve.linuxwall.info/blog/index.php?post%2F2013%2F10%2F12%2FA-grade-SSL%2FTLS-with-Nginx-and-StartSSL)**
>
> I've been spending the past 3 months doing a full review of the TLS landscape. I plan on publishing it very soon (just need to polish the doc), and in the meantime, here are a few

Feel free to comment here.

Cheers

–  
Julien Vehent  
[http://jve.linuxwall.info](http://jve.linuxwall.info)

---

<div class="post-metadata">

**Author:** ![Julien\_Vehent](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/51bf81/32.png) [@Julien\_Vehent](https://www.ruby-forum.com/u/Julien_Vehent)\
**Post date:** [October 15, 2013, 6:40am UTC](https://www.ruby-forum.com/t/a-grade-ssl-tls-with-nginx-and-startssl/246439/2 "2013-10-15T06:40:07Z")

</div>

Hi Julien,

> I spent some time hacking on my SSL conf recently. Nothing new, but I  
> figured I’d share it with the group:

> **["A" Grade SSL/TLS with Nginx and StartSSL - Quelques digressions sous GPL](https://jve.linuxwall.info/blog/index.php?post%2F2013%2F10%2F12%2FA-grade-SSL%2FTLS-with-Nginx-and-StartSSL)**
>
> I've been spending the past 3 months doing a full review of the TLS landscape. I plan on publishing it very soon (just need to polish the doc), and in the meantime, here are a few

> Feel free to comment here.

> a few pointers for configuring state-of-the-art TLS on Nginx.

Far from it, from the top:

> build\_static\_nginx.sh

You should be using:

```
--with-openssl=../openssl-1.0.1e
--with-openssl-opt="enable-ec_nistp_64_gcc_128"

```

instead of compiling OpenSSL yourself and playing with CFLAGS & LDFLAGS.

> listen 443;  
> ssl on;

That’s deprecated syntax, you should be using:

```
listen 443 ssl;

```

> ssl\_dhparam /path/to/dhparam.pem;

While there is nothing wrong with it per se, DH params are only used  
by DHE, which is simply too slow to be used.

> ssl\_session\_timeout 5m;

Not only doesn’t it change anything (5m is the default value), but  
it’s way too low value to be used.

Few examples from the real world:

```
Google : 28h
Facebook : 24h
CloudFlare: 18h
Twitter : 4h

```

> ssl\_protocols TLSv1 TLSv1.1 TLSv1.2;

SSLv3 is still out there, so you shouldn’t be dropping support for it  
unless you know the consequences very well… This definitely  
shouldn’t be a general recommendation.

> ssl\_ciphers  
> ‘ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK’;

Why would you put ECDSA cipher suites here when you’re using RSA  
certificate?

You should also disable:

- DHE cipher suites, because they’re too slow compared to the  
alternative,
- CAMELLIA cipher suites (if you’re using AES-NI), because they’re too  
slow compared to the alternative.

Overall, that’s far from the state-of-the-art SSL configuration for  
nginx. The only good thing about it is that it’s using OCSP and  
achieves “A” grade on [ssllabs.com](http://ssllabs.com), which can tell you a lot about the  
quality of the tests they’re running.

Best regards,  
Piotr S.

---

<div class="post-metadata">

**Author:** ![Julien\_Vehent](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/51bf81/32.png) [@Julien\_Vehent](https://www.ruby-forum.com/u/Julien_Vehent)\
**Post date:** [October 15, 2013, 3:27pm UTC](https://www.ruby-forum.com/t/a-grade-ssl-tls-with-nginx-and-startssl/246439/3 "2013-10-15T15:27:44Z")

</div>

On 2013-10-15 00:39, Piotr S. wrote:

> 

Afaik, the above dynamically links openssl. Am I wrong?

> > listen 443;  
> > ssl on;
> 
> That’s deprecated syntax, you should be using:
> 
> ```
> listen 443 ssl;
> 
> ```

noted, but that doesn’t impact security

> > ssl\_dhparam /path/to/dhparam.pem;
> 
> While there is nothing wrong with it per se, DH params are only used  
> by DHE, which is simply too slow to be used.

Are you saying you would rather use non-PFS ciphers than wait an extra  
15ms  
to complete a DHE handshake? I wouldn’t.

> ```
> Twitter : 4h
> 
> ```

Interesting information, which I didn’t have before. May I ask how you  
collected it?

> certificate?

Because someone else might use DSA certificates.

> You should also disable:
> 
> - DHE cipher suites, because they’re too slow compared to the alternative,

No. The alternatives aren’t available everywhere.

> - CAMELLIA cipher suites (if you’re using AES-NI), because they’re too  
> slow compared to the alternative.

Again, I don’t control clients. I push down unwanted ciphers, but I  
won’t  
disable them unless they are obviously broken (MD5, …).

> Overall, that’s far from the state-of-the-art SSL configuration for  
> nginx. The only good thing about it is that it’s using OCSP and  
> achieves “A” grade on [ssllabs.com](http://ssllabs.com), which can tell you a lot about the  
> quality of the tests they’re running.

I appreciate the feedback, but no need to be rude about it 😉

- Julien

---

<div class="post-metadata">

**Author:** ![Julien\_Vehent](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/51bf81/32.png) [@Julien\_Vehent](https://www.ruby-forum.com/u/Julien_Vehent)\
**Post date:** [October 16, 2013, 12:01am UTC](https://www.ruby-forum.com/t/a-grade-ssl-tls-with-nginx-and-startssl/246439/4 "2013-10-16T00:01:24Z")

</div>

Hi Julien,

> Afaik, the above dynamically links openssl. Am I wrong?

Yes, you’re wrong.

> Are you saying you would rather use non-PFS ciphers than wait an extra 15ms  
> to complete a DHE handshake? I wouldn’t.

No, I’m saying that since you’re compiling against OpenSSL-1.0.1,  
you’ve got ECDHE cipher suites, which are much faster than DHE and all  
modern browsers support ECDHE.

I know this kind of contradicts my “you shouldn’t be dropping SSLv3  
support” statement (since SSLv3 doesn’t support ECDHE, so it would end  
up without PFS cipher suite), but you cannot have everything.

Also, while this isn’t the best reason to do things, none of the “big”  
players offers DHE.

> Interesting information, which I didn’t have before. May I ask how you  
> collected it?

openssl s\_client -connect :443 \</dev/null 2\>/dev/null | grep  
lifetime

While this only shows you the Session Ticket lifetime hint and not the  
internal session cache expire policy, it shows you the value they are  
aiming for with resumption. Also, in nginx’s case both values are the  
same.

Trust me, you want this to be high 🙂

> Because someone else might use DSA certificates.

It’s ECDSA, not DSA… And I’m yet to see a site that offers ECDSA  
instead of RSA certificate.

> No. The alternatives aren’t available everywhere.

Virtually everywhere 😉

> Again, I don’t control clients. I push down unwanted ciphers, but I won’t  
> disable them unless they are obviously broken (MD5, …).

Kind of the same reasoning as for DHE - AES (with AES-NI) is much  
faster than CAMELLIA and I dare you to find a software that supports  
CAMELLIA but not AES.

Keep in mind that the reason for disabling slow cipher suites is not  
to limit interoperability, but to limit impact of attacks that use  
time-consuming crypto… For example, AES (with AES-NI) is 4x faster  
than CAMELLIA while essentially providing the same level of security,  
which means that (D)DoS attacks on SSL require 4x less resources if  
you don’t disable it.

> I appreciate the feedback, but no need to be rude about it 😉

Actually, I was trying hard to not sound rude (apparently I failed),  
but the fact is that calling it “A grade” and “state of the art”  
configuration results in people that don’t know any better picking up  
your recommendations and deploying them in production.

Best regards,  
Piotr S.

---

<div class="post-metadata">

**Author:** ![Julien\_Vehent](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/51bf81/32.png) [@Julien\_Vehent](https://www.ruby-forum.com/u/Julien_Vehent)\
**Post date:** [October 17, 2013, 4:05pm UTC](https://www.ruby-forum.com/t/a-grade-ssl-tls-with-nginx-and-startssl/246439/5 "2013-10-17T16:05:46Z")

</div>

On 15/10/13 23:00, Piotr S. wrote:

> > Because someone else might use DSA certificates.
> 
> It’s ECDSA, not DSA… And I’m yet to see a site that offers ECDSA  
> instead of RSA certificate.

There are some sites that offer an ECDSA cert where possible, but  
fallback to an RSA cert when the client doesn’t offer any ECDSA ciphers.  
AFAIK, Apache httpd is the only major webserver that can currently be  
configured this way.  
I expect to see this configuration become more common in the (near?)  
future, given that some commercial CAs are now actively selling ECDSA  
certs.

Nginx currently only allows one cert to be configured, and I too am yet  
to see a site that offers _only_ an ECDSA cert. I expect this is due to  
the large proportion (I estimate ~20%) of clients that support RSA certs  
but not ECDSA certs.

I’d love to see the ECDSA cert + RSA cert feature implemented in Nginx  
too. OpenSSL does most of the hard work already. I’ve written a PoC  
patch, but I’ll post it to a different thread.

–  
Rob Stradling  
Senior Research & Development Scientist  
COMODO - Creating Trust Online

---

<div class="post-metadata">

**Author:** ![Julien\_Vehent](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/51bf81/32.png) [@Julien\_Vehent](https://www.ruby-forum.com/u/Julien_Vehent)\
**Post date:** [October 17, 2013, 4:22am UTC](https://www.ruby-forum.com/t/a-grade-ssl-tls-with-nginx-and-startssl/246439/6 "2013-10-17T04:22:54Z")

</div>

## Piotr S. Wrote:

> ```
> Twitter : 4h
> 
> ```

Wouldn’t having a timeout that high lower the effectiveness of forward  
secrecy? You’d have the potential to be using the same key for up to 28  
hours on Google.

I suppose most sites don’t even rotate their session tickets that often,  
so  
it probably doesn’t matter for a lot of people.

Posted at Nginx Forum:  
[http://forum.nginx.org/read.php?2,243653,243779#msg-243779](http://forum.nginx.org/read.php?2,243653,243779#msg-243779)

---

<div class="post-metadata">

**Author:** ![Julien\_Vehent](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/51bf81/32.png) [@Julien\_Vehent](https://www.ruby-forum.com/u/Julien_Vehent)\
**Post date:** [October 20, 2013, 11:12pm UTC](https://www.ruby-forum.com/t/a-grade-ssl-tls-with-nginx-and-startssl/246439/7 "2013-10-20T23:12:50Z")

</div>

2013-10-15 Piotr S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
has cited Julien Vehent [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> ssl\_ciphers  
> ‘ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK’;

Why did you sort the ciphers in this particular order?

If you wanted to prefer AES128 over AES256 over RC4 you could write:

# ssl\_ciphers ‘AES128:AES256:RC4+SHA:!aNULL:!PSK:!SRP’;

See the output of:

# openssl ciphers list -v ‘AES128:AES256:RC4+SHA:!aNULL:!PSK’

OpenSSL will order the combinations by strength and include new modes  
by default.

Why do you include the weak RC4?  
You don’t use SSLv3. The subset of outdated clients not able to  
use TLSv1.1 _and_ AES properly is diminishing. (They would have been  
not been patched for about more than two years and need to repeatedly  
(think: millions of times) request the same binary data without Nginx  
changing the response…)

Given that AES256 boils down to 2**99.5 bits attack (time/step)  
complexity [1] and AES128 to 2**100 if you agree with [2] I would  
suggest this:

# ssl\_ciphers ‘AES128:!aNULL:!PSK:!SRP’

… Include PSK and/or SRP if you need them, which almost none webserver  
operator does. Optionally with !ECDH if you don’t trust the origin of  
the random seed values for NIST curves.

–  
Mark

> **[Open Source Software Entwicklung Heidelberg | OSSDL](https://ossdl.de/)**
>
> OSSDL — Open Source Software Development Labs Heidelberg. Softwareentwicklung, Architektur, Linux und DevOps auf Basis offener Technologien.

[1] [http://eprint.iacr.org/2009/317](http://eprint.iacr.org/2009/317)  
[2] [http://eprint.iacr.org/2002/044](http://eprint.iacr.org/2002/044)
