Configuring SSL/TLS With Hipache (And Node.js)

2014-12-26 - most of the patches I have sent to Hipache have already been merged, making Hipache safer than ever.

Lately, I have been working on configuring a SSL/TLS layer for a project. As you may (or may not) think, it is not only about creating SSL certificates. In the following article, I am going to describe how to properly configure SSL/TLS with Hipache, a distributed HTTP(s) and websocket proxy. Disclaimer: even if I am really interested in security, I am not a security expert.


Getting SSL certificates (key, crt, pem files) is a good start, but it is definitely not enough. With the recent security issues such as POODLE, Heartbleed and so on, configuring this layer requires more attention than ever. Want to check your current configuration? Qualys SSL Server Test to the rescue! First time I tried, I got a C grade…

Secure Protocols

There are five secure procotols, part of the SSL/TLS family, but most of them should not be used. SSLv2 and SSLv3 are insecure, do not used them! Yes, disable SSLv3 now! TLSv1 is also insecure, whereas TLSv1.1 and TLSv1.2 are not, or at least are without known security issues (yet).

Hipache is a Node.js application. The good thing about this platform is that people seem to care about security, and since v0.10 SSLv2 and SSLv3 are disabled by default. Hipache relies on Node’s https.createServer() method, and a secureProtocol option is available to specify the secure protocol to use. Its default value is SSLv23_method and is about negotiating a protocol from the highest level down to whatever the client supports. Yes, worst name ever! Another option called secureOptions is available and can be used to explicitly disable the use of SSLv3 and SSLv2. Since v0.10.33, it is disabled by default though. Such a configuration protects against the POODLE attack in Node.js.

Unfortunately, I could not get it work as is using Hipache, so I ended up patching this load balancer to support the secureOptions parameter. This patch provides the exact same configuration as described above. (Note: I maintain a Docker image with my Hipache tweaks, running in production).

Securing secure protocols: done!

Secure Cipher Suites

Next step is about defining how secure communication takes place. That is important for enabling Forward Secrecy, which means that for an attacker it wil not be possible to decrypt your previous data exchanges if they get access to your private key, and to protect against the BEAST attack (which is not impractical).

After having read how to configure Apache, Nginx, and OpenSSL for Forward Secrecy, I decided to use the following cipher suite (which disables RC4 by the way):

DH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4

So far so good. Not exactly, because stable Node.js version (v0.10.34) does not support Elliptic Curve Diffie-Hellman (ECDH) ciphers yet, even if a patch has been merged. Node v0.11.14 (unstable) contains this patch, therefore it is the version to use if one wants to deploy Forward Secrecy. It is important to support ECDHE because it is supported by all major modern browsers whereas Diffie-Hellman (DHE) does not.

Hipache exposes a ciphers option but does not provide the honorCipherOrder one, which is recommended to mitigate BEAST attacks in Node.js documentation. Then again, there is a pull-request for that!

My Hipache https configuration now looks like this:

"https": {
    "port": 443,
    "bind": [ "0.0.0.0" ],
    "key": "/etc/ssl/ssl.key",
    "cert": "/etc/ssl/ssl.crt",
    "ciphers": "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4",
    "honorCipherOrder": true
}

Doing all of this allowed me to get a A grade with Qualys’ tool, which is quite good. In the next section, I am going to describe a few more security points that everyone should know and check.

What’s Next?

Client-Initiated Renegotiation

In TLS, renegotiation allows parties to stop exchanging data in order to renegotiate how the communication is secured. The protocol lets the client renegotiate certain aspects of the TLS session. Thing is, client-initiated renegotiation may lead to Denial of Service (DoS), and therefore must be disabled.

In Node.js, renegotiations are limited to three times every 10 minutes. While these default values seems legit to me, Qualys’ tool reports no protection against this attack.

TLS Compression

The CRIME attack exploits a flaw with data compression. When used to recover the content of secret authentication cookies, it allows an attacker to perform session hijacking on an authenticated web session, allowing the launching of further attacks (says Wikipedia).

In order to protect against this attack, Node.js disables all compression.

Downgrade Attack Prevention

A Man-In-The-Middle (MITM) can disrupt an SSL handshake and cause the client and server to select an earlier SSL protocol version. This is known as an SSL downgrade attack. Disabling SSLv3 protects against this attack.

It is worth mentioning that Google has written an RFC to propose an extension to SSL/TLS named TLS_FALLBACK_SCSV that seeks to prevent protocol downgrade attacks. The latest OpenSSL 1.0.1j version support TLS_FALLBACK_SCSV which Node v0.11.14 does not support yet (1.0.1i by now).

OpenSSL

Reminder: make sure to use a secure version of OpenSSL.

HTTP Headers

Enable HTTP Strict Transport Security (HSTS) in your web server (Nginx here) configuration:

# Enable HSTS
add_header Strict-Transport-Security max-age=63072000;

Resources

By the way, if you found a typo, please fork and edit this post. Thank you so much! This post is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

If you like this post or if you use one of the Open Source projects I maintain, say hello by email. There is also my Amazon Wish List. Thank you ♥

Comments

Fork me on GitHub