Getting an A+ on the SSL Labs test in Node.js and Io.js
certsimple.com
certsimple.com
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
Running a Node.js application without a reverse proxy in front of it sounds like poor practice though, particularly from a security standpoint.
I think it makes sense to separate the security and low level details of serving a public site, and the details of hosting an application though. This is common practice with Django, using gunicorn and nginx, and I believe with Ruby as well in a similar manner.
Whether that's worth it is another question.
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...
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.
Wasn't a scientific test, but the results were consistent enough for us to decide to use nginx.
(FWIW, neither nginx nor node did SSL termination - we have haproxy in front of them taking care of that and the load balancing itself).
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.
That's incorrect. See edit to parent post (sorry I couldn't reply earlier).
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.
One big difference to note is that nginx link to the local openssl while node binaries embeds an openssl. If there is a bug in openssl I can apt-get update/upgrade and I get the patch very early.
Personally I think nginx is awesome. They are going to support JavaScript soon, but I have done things with LUA and is great too.
Whaaaaaaat?
http://www.infoworld.com/article/2838008/javascript/nginx-ha...
Whoa. Slow down. They have only confirmed replacing their custom configuration language with JavaScript and hinted at an official JavaScript module [1], as opposed to the existing third-party module [2].
Bundling a Node.js-like JavaScript api layer with their official module would be a logical next step, because nginx is an event loop anyway. But, I highly doubt JavaScript will be anywhere near the Nginx core.
[1] http://www.infoworld.com/article/2838008/javascript/nginx-ha...
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...
I'll do some research around 4096 bit key support. I'm also checking out OCSP stapling.
Edit: precursory investigations show 4096 bit keys generally good to go with a few exceptions, eg AWS CloudFront:http://docs.aws.amazon.com/AmazonCloudFront/latest/Developer...
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.
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)
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) 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
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://www.schneier.com/blog/archives/2009/07/another_new_a...
As another poster mentions, using AES-GCM with 128 bit keys is considered superior to using a 256 bit key without (though indeed, removing all 128 bit keys gets you 100% on the SSLLabs test).
See https://wiki.mozilla.org/Security/Server_Side_TLS#Prioritiza...
> 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 Section 5 for more information.
- 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
[1] In particular, these two blocks of code: https://github.com/AGWA/titus/blob/43ecf6889d4c5a61f58de5f8a... https://github.com/AGWA/titus/blob/43ecf6889d4c5a61f58de5f8a...
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.