"A" Grade SSL/TLS with Nginx and StartSSL

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:

Feel free to comment here.

Cheers


Julien Vehent
http://jve.linuxwall.info

Hi Julien,

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

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, which can tell you a lot about the
quality of the tests they’re running.

Best regards,
Piotr S.

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, 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 :wink:

  • Julien

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

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

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

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.

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

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:

2013-10-15 Piotr S. [email protected]
has cited Julien Vehent [email protected]:

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 299.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

[1] Related-key Cryptanalysis of the Full AES-192 and AES-256
[2] Cryptanalysis of Block Ciphers with Overdefined Systems of Equations