tls: more secure defaults
authorRoman Reiss <me@silverwind.io>
Sun, 15 Feb 2015 17:43:36 +0000 (18:43 +0100)
committerFedor Indutny <fedor@indutny.com>
Mon, 16 Feb 2015 11:33:12 +0000 (12:33 +0100)
This updates the default cipher suite to an more secure list, which
prefers strong ciphers with Forward Secrecy. Additionally, it enables
`honorCipherOrder` by default.

Noteable effect of this change is that the insecure RC4 ciphers are
disabled and that Chrome negotiates a more secure ECDHE cipher.

Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Fedor Indutny <fedor@indutny.com>
PR-URL: https://github.com/iojs/io.js/pull/826

doc/api/tls.markdown
lib/_tls_wrap.js
lib/tls.js
test/parallel/test-tls-dhe.js

index c5cfc15..63c9649 100644 (file)
@@ -25,8 +25,10 @@ To create a self-signed certificate with the CSR, do this:
 
 Alternatively you can send the CSR to a Certificate Authority for signing.
 
-(TODO: docs on creating a CA, for now interested users should just look at
-`test/fixtures/keys/Makefile` in the Node source code)
+For Perfect Forward Secrecy, it is required to generate Diffie-Hellman
+parameters:
+
+    openssl dhparam -outform PEM -out dhparam.pem 2048
 
 To create .pfx or .p12, do this:
 
@@ -136,31 +138,20 @@ automatically set as a listener for the [secureConnection][] event.  The
   - `crl` : Either a string or list of strings of PEM encoded CRLs (Certificate
     Revocation List)
 
-  - `ciphers`: A string describing the ciphers to use or exclude.
-
-    To mitigate [BEAST attacks] it is recommended that you use this option in
-    conjunction with the `honorCipherOrder` option described below to
-    prioritize the non-CBC cipher.
-
-    Defaults to
-    `ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL`.
-    Consult the [OpenSSL cipher list format documentation] for details
-    on the format.
+  - `ciphers`: A string describing the ciphers to use or exclude, seperated by
+    `:`. The default cipher suite is:
 
-    `ECDHE-RSA-AES128-SHA256`, `DHE-RSA-AES128-SHA256` and
-    `AES128-GCM-SHA256` are TLS v1.2 ciphers and used when io.js is
-    linked against OpenSSL 1.0.1 or newer, such as the bundled version
-    of OpenSSL.  Note that it is still possible for a TLS v1.2 client
-    to negotiate a weaker cipher unless `honorCipherOrder` is enabled.
+        ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA256:
+        DHE-RSA-AES256-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:
+        HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA
 
-    `RC4` is used as a fallback for clients that speak on older version of
-    the TLS protocol.  `RC4` has in recent years come under suspicion and
-    should be considered compromised for anything that is truly sensitive.
-    It is speculated that state-level actors possess the ability to break it.
-
-    **NOTE**: Previous revisions of this section suggested `AES256-SHA` as an
-    acceptable cipher. Unfortunately, `AES256-SHA` is a CBC cipher and therefore
-    susceptible to [BEAST attacks]. Do *not* use it.
+    The default cipher suite prefers ECDHE and DHE ciphers for Perfect Forward
+    secrecy, while offering *some* backward compatibiltity. Old clients which
+    rely on insecure and deprecated RC4 or DES-based ciphers (like Internet
+    Explorer 6) aren't able to complete the handshake with the default
+    configuration. If you absolutely must support these clients, the
+    [TLS recommendations] may offer a compatible cipher suite. For more details
+    on the format, see the [OpenSSL cipher list format documentation].
 
   - `ecdhCurve`: A string describing a named curve to use for ECDH key agreement
     or false to disable ECDH.
@@ -178,11 +169,7 @@ automatically set as a listener for the [secureConnection][] event.  The
     times out.
 
   - `honorCipherOrder` : When choosing a cipher, use the server's preferences
-    instead of the client preferences.
-
-    Although, this option is disabled by default, it is *recommended* that you
-    use this option in conjunction with the `ciphers` option to mitigate
-    BEAST attacks.
+    instead of the client preferences. Default: `true`.
 
   - `requestCert`: If `true` the server will request a certificate from
     clients that connect and attempt to verify that certificate. Default:
@@ -812,3 +799,4 @@ The numeric representation of the local port.
 [ECDHE]: https://en.wikipedia.org/wiki/Elliptic_curve_Diffie%E2%80%93Hellman
 [asn1.js]: http://npmjs.org/package/asn1.js
 [OCSP request]: http://en.wikipedia.org/wiki/OCSP_stapling
+[TLS recommendations]: https://wiki.mozilla.org/Security/Server_Side_TLS
index c6bf31b..c24d366 100644 (file)
@@ -703,10 +703,10 @@ Server.prototype.setOptions = function(options) {
   if (options.sessionTimeout) this.sessionTimeout = options.sessionTimeout;
   if (options.ticketKeys) this.ticketKeys = options.ticketKeys;
   var secureOptions = options.secureOptions || 0;
-  if (options.honorCipherOrder)
-    this.honorCipherOrder = true;
+  if (options.honorCipherOrder !== undefined)
+    this.honorCipherOrder = !!options.honorCipherOrder;
   else
-    this.honorCipherOrder = false;
+    this.honorCipherOrder = true;
   if (secureOptions) this.secureOptions = secureOptions;
   if (options.NPNProtocols) tls.convertNPNProtocols(options.NPNProtocols, this);
   if (options.sessionIdContext) {
index 0e13516..9e1b928 100644 (file)
@@ -13,11 +13,24 @@ exports.CLIENT_RENEG_WINDOW = 600;
 
 exports.SLAB_BUFFER_SIZE = 10 * 1024 * 1024;
 
-exports.DEFAULT_CIPHERS =
-    // TLS 1.2
-    'ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:AES128-GCM-SHA256:' +
-    // TLS 1.0
-    'RC4:HIGH:!MD5:!aNULL';
+exports.DEFAULT_CIPHERS = [
+  'ECDHE-RSA-AES256-SHA384',
+  'DHE-RSA-AES256-SHA384',
+  'ECDHE-RSA-AES256-SHA256',
+  'DHE-RSA-AES256-SHA256',
+  'ECDHE-RSA-AES128-SHA256',
+  'DHE-RSA-AES128-SHA256',
+  'HIGH',
+  '!aNULL',
+  '!eNULL',
+  '!EXPORT',
+  '!DES',
+  '!RC4',
+  '!MD5',
+  '!PSK',
+  '!SRP',
+  '!CAMELLIA'
+].join(':');
 
 exports.DEFAULT_ECDH_CURVE = 'prime256v1';
 
index 8c28920..af0db51 100644 (file)
@@ -26,6 +26,7 @@ function test(keylen, expectedCipher, cb) {
   var options = {
     key: key,
     cert: cert,
+    ciphers: ciphers,
     dhparam: loadDHParam(keylen)
   };