

Getting an A+ on the SSL Labs test in Node.js and Io.js - nailer
https://certsimple.com/blog/a-plus-node-js-ssl

======
danpalmer
Isn't this all better implemented in the nginx/apache server in front of the
application?

I've just done a very similar thing for my Django hosted website, but didn't
touch Python at all for it.

Edit: Here's a blog post where I detail the steps to set this up in Nginx -
[https://news.ycombinator.com/item?id=9256200](https://news.ycombinator.com/item?id=9256200)

~~~
nailer
Edit: added reply to 'vkjv' below as I have hit the comment threshhold and
have been unable to reply to this account. Since HN seems to be somewhat
unsure of node's concept of IO (why I imagine the downmods) and why it's
significantly different to common Python and Ruby setup (Tornado and
EventMachine excepted).

The main point of nginx is event based, non-blocking IO. That's why
traditionally blocking languages (like your Python setup) use nginx for static
content and their own engines for dynamic stuff.

However event based, non-blocking IO is also the main point of node. So most
people using, say Express would use the express module's inbuilt 'static'
middleware rather than add an entire webserver to replicate the built-in
functionality.

Unless there's a compelling reason to do SSL elsewhere (for example, an AWS
ELB would allow you to isolate & consolidate your SSL in a separate layer)
then you'd want to avoid adding complexity.

Edit: reply to vkjv:

> it still needs to serialize that data from I/O to the request and that is
> both blocking and slow.

No. If the socket wasn't ready, node wouldn't block writing data there.
streams are evented and that includes sockets. Hence the callback on
socket.write()
[https://nodejs.org/api/net.html#net_socket_write_data_encodi...](https://nodejs.org/api/net.html#net_socket_write_data_encoding_callback)

    
    
        var socket = new net.Socket();
        socket.write(...)
        console.log('Yep sockets are non blocking too')
    

This is why both node and nginx have outperformed each other in different
tests.

Agreed, if you're already using nginx for other reasons, eg, load balancing,
you should use nginx for SSL. If you're not, think carefully before doubling
the size of your stack without specific reason to do so.

~~~
vkjv
While node.js is great at non-blocking IO, it's not great at the blocking
kind. E.g., shuffling bytes.

While you are correct that node.js is happily not blocking the main thread
while reading from disk, once that returns it still needs to serialize that
data from I/O to the request and that is both blocking and slow.

I highly advise that you don't use node.js to service static content outside
of a development environment. And if you are already using nginx in front of
node, you might as well use it for SSL.

As a bonus, nginx does a great job proxying multiple node.js processes. You
could also use the cluster module, but last time I checked, that was still
marked as experimental.

~~~
virmundi
I know that the parent replied already, but I want add that using node for
static content is a good idea. I/O is what Node excels at. As long as you use
the non-blocking API to load content, you should get good throughput. What
Node is bad at is processing dynamic things. If your templates are CPU
intensive, you'll block Node.

This is why I'm, to this day, confused about building whole websites on Node.
Dynamic, templated web sites are computation intensive (without result
caching). Sure you can have N-Nodes running for N cores. This will minimize
blocking. I/O for DB is time intensive so Node will pickup other workloads
while it waits. So everything averages out, but it still an interesting thing
often overlooked.

------
samch
I kind of wish they wouldn't just hand out an A+ that easily. There are clear
areas of improvement that the sub-scores call out (90 in both Key Exchange and
Cipher Suite). They see the HSTS and grant the A+ when there is clearly
improvement that can be made. In my mind, an A+ should be reserved for an
SSL/TLS implementation that cannot reasonably be improved upon given the
current state of the industry.

To improve your Key Exchange score you can bump your certificate from a
2048-bit key up to 4096-bit (giving you a score of 100). That's probably a
good idea anyway as 2048 has been the minimum safe key size since 2010 [1],
and I'd imagine that 4096 will become the new minimum over the next few years.

To improve your Cipher Suite score you can easily drop support for payload
encryption with keys less than 256 bits in length. You will risk not
supporting IE 6 users, but that's a fringe case these days (and there are many
more issues with supporting IE 6 on top of that).

Making those adjustments, you should be able to get your scores to
100,95,100,100 which, in my opinion, is much more worthy of an A+.

There may be a few other tweaks you can make to improve items in the Protocol
Details section, but I don't know enough about the node.js/io.js system to be
able to recommend a clear path for improvement there.

The only score that you really would have difficulty bumping to 100 is the
Protocol Support which is limited by the fact that all versions of IE prior to
11 had TLS 1.1 and 1.2 disabled by default. Unfortunately, there are still
many IE 9 and 10 users out there

1\.
[http://csrc.nist.gov/publications/nistpubs/800-131A/sp800-13...](http://csrc.nist.gov/publications/nistpubs/800-131A/sp800-131A.pdf)

~~~
agwa
> I'd imagine that 4096 will become the new minimum over the next few years.

That's unlikely to happen. 2048-bit RSA provides a security level of ~112
bits, which would physically require a massive amount of energy to break, and
it's unlikely that so much energy would ever be expended on a single task. So
2048-bit RSA is only likely to be broken if there's a mathematical
breakthrough against RSA. The thing is, such a breakthrough is likely to break
4096-bit RSA as well, so using 4096-bit RSA is only a protection against a
minor breakthrough.

Meanwhile, 4096-bit RSA carries a massive performance cost. It's just not
worth slowing down your TLS handshake with 4096-bit RSA to protect against a
mathematical breakthrough, but not too much of a breakthrough.

So stick with 2048-bit RSA for now, and in a few years when elliptic curve
crypto is better supported, switch to that.

~~~
nuxi7
Totally This ^

This is a key you get re-signed every 1-3 years. You don't need it to last 10
years, you need it to last maybe a year longer than your SSL cert is actually
good for. (Assuming your site is setup to have all the browsers do PFS)

------
nailer
Hi there, author here.

This began as an exercise in improving the rating for an individual website,
the iojs advocacy just came as a side effect of investigating what was needed
and running into the megapatch in iojs
([https://github.com/iojs/io.js/pull/826](https://github.com/iojs/io.js/pull/826))
where they fixed the tls defaults affecting node 0.12's out of the box score.

Let me know if you have any additions or corrections, there's also an express
boilerplate app used to pass the tests here:
[https://github.com/mikemaccana/ssltest](https://github.com/mikemaccana/ssltest)

------
davidben
This isn't prioritizing quite the right ciphers. The CBC mode construction in
TLS has serious problems (MAC-then-encrypt instead of encrypt-then-MAC) and
should be considered cryptographically broken. It's incredibly fragile and
difficult to implement correctly.

You want to make sure TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 is negotiated, at
least where browsers support it. (It's spelled "ECDHE-RSA-AES128-GCM-SHA256"
in OpenSSL.) There's a small handful of others that are also acceptable, but
between ECDSA certificates being rare and CHACHA20_POLY1305 still being
standardized, that's the one you want. All the rest are legacy baggage.

Mozilla has some server-side recommendations here:
[https://wiki.mozilla.org/Security/Server_Side_TLS](https://wiki.mozilla.org/Security/Server_Side_TLS)

~~~
samch
Just out of curiosity, why are you proposing that AES 128 is the one to go
with? According to SSL Labs AES 256 is preferable and has broad support among
browsers.

~~~
tuxychandru
This article points to an attack that applies to AES-256, but not 128.

[https://www.schneier.com/blog/archives/2009/07/another_new_a...](https://www.schneier.com/blog/archives/2009/07/another_new_aes.html)

~~~
samch
Except that the attack you mention has no bearing on the standard 14-round
AES-256 that everybody uses.

------
masta
The explanation of the Full cipher suite format has some tiny mistakes for the
explained case.

> Use GCM for the cipher mode > Use SHA256 for message authentication (making
> sure messages haven't been tampered with)

GCM is an AEAD-Mode, it builts upon CTR-Mode, but also provides message
authentication. SHA256 is used as a PRF (Pseudo Random Function) to generate
key material based on the master secrect. See
[https://tools.ietf.org/html/rfc5246](https://tools.ietf.org/html/rfc5246)
Section 5 for more information.

~~~
nailer
Thank you! I've published a correction in the article and credited you.

------
ouaibe
I did split ioerror's duraconf nginx configs in 3 distinct configs with
different ciphersuites lists, that specifically list desired ciphers in order,
targetting :

\- Very high security with low compatibility.

\- PFS-only moderate security with high compatibility.

\- PFS-centric moderate security with very high compatibility.

All of them give an A on Qualys SSL Labs test.

[https://github.com/ouaibe/duraconf/tree/master/configs/nginx](https://github.com/ouaibe/duraconf/tree/master/configs/nginx)

------
zaphoyd
Anyone know of a guide like this for a C or C++ server implemented using raw
OpenSSL?

~~~
agwa
You could look at the source for my titus TLS proxy server[1]. It gets an A
out of the box, and an A+ if the application sends the HSTS header.

[1] In particular, these two blocks of code:
[https://github.com/AGWA/titus/blob/43ecf6889d4c5a61f58de5f8a...](https://github.com/AGWA/titus/blob/43ecf6889d4c5a61f58de5f8ae3fb1ecda1d97bb/titus.cpp#L607-L623)
[https://github.com/AGWA/titus/blob/43ecf6889d4c5a61f58de5f8a...](https://github.com/AGWA/titus/blob/43ecf6889d4c5a61f58de5f8ae3fb1ecda1d97bb/titus.cpp#L256-L283)

------
matt-attack
Is it rude that SSL Labs publishes those who got Fs?

~~~
Karunamon
There's a "don't publish" checkbox on the main page right below where your URL
is entered. Also, anecdotally, most of the F's I see are from untrusted certs.
(I.e. the encryption is fine, the site in question just didn't pay the CA
protection money.)

------
Thaxll
Why people are that "concerned" about getting A+ on SSL Labs...

~~~
samch
I'm not really sure what you're asking about or commenting on here. I will,
however, take the opportunity to say that I am a big fan of the SLL Labs
Server Test that Ivan Ristic made. With the number of SSL/TLS vulnerabilities
over the past few years, it's important to ensure that secure servers stay
current with best practices. This tool offers a free way to audit that.

Getting an A+ doesn't guarantee security as your application and
infrastructure must all be kept current and secured. The A+, however, is
intended as an indicator that your SSL/TLS is configured to provide the
optimal level of security around the transport layer. If a site gets a grade
of B, that doesn't necessarily make it insecure, but it does indicate that
certain vulnerabilities could expose their users' data.

~~~
Thaxll
The problem by getting an A+ is that you are probably blocking a lot of
clients from reaching your service.

~~~
agwa
No, that's not true. The only client with non-negligible use that you have to
lock out to get an A+ is IE6 (because IE6 only supports SSLv3, at best, by
default).

~~~
jamiesonbecker
IE6 Must Die. Except for China, IE6 is used by less than 1% of the population
around the world, according to Microsoft's own data:

[https://www.modern.ie/en-us/ie6countdown](https://www.modern.ie/en-
us/ie6countdown)

~~~
agwa
Indeed. Locking IE6 out to get an A/A+ on SSL Labs is totally worth it.

~~~
jamiesonbecker
Absolutely. If people have old hardware or OS's, they could at least switch to
an older version of a better browser.

