@@ -140,6 +140,94 @@ To test the renegotiation limits on a server, connect to it using the OpenSSL
140
140
command-line client (` openssl s_client -connect address:port ` ) then input
141
141
` R<CR> ` (i.e., the letter ` R ` followed by a carriage return) multiple times.
142
142
143
+ ### Session Resumption
144
+
145
+ Establishing a TLS session can be relatively slow. The process can be sped
146
+ up by saving and later reusing the session state. There are several mechanisms
147
+ to do so, discussed here from oldest to newest (and preferred).
148
+
149
+ *** Session Identifiers*** Servers generate a unique ID for new connections and
150
+ send it to the client. Clients and servers save the session state. When
151
+ reconnecting, clients send the ID of their saved session state and if the server
152
+ also has the state for that ID, it can agree to use it. Otherwise, the server
153
+ will create a new session. See [ RFC 2246] [ ] for more information, page 23 and
154
+ 30 .
155
+
156
+ Resumption using session identifiers is supported by most web browsers when
157
+ making HTTPS requests.
158
+
159
+ For Node.js, clients must call [ ` tls.TLSSocket.getSession() ` ] [ ] after the
160
+ [ ` 'secureConnect' ` ] [ ] event to get the session data, and provide the data to the
161
+ ` session ` option of [ ` tls.connect() ` ] [ ] to reuse the session. Servers must
162
+ implement handlers for the [ ` 'newSession' ` ] [ ] and [ ` 'resumeSession' ` ] [ ] events
163
+ to save and restore the session data using the session ID as the lookup key to
164
+ reuse sessions. To reuse sessions across load balancers or cluster workers,
165
+ servers must use a shared session cache (such as Redis) in their session
166
+ handlers.
167
+
168
+ *** Session Tickets*** The servers encrypt the entire session state and send it
169
+ to the client as a "ticket". When reconnecting, the state is sent to the server
170
+ in the initial connection. This mechanism avoids the need for server-side
171
+ session cache. If the server doesn't use the ticket, for any reason (failure
172
+ to decrypt it, it's too old, etc.), it will create a new session and send a new
173
+ ticket. See [ RFC 5077] [ ] for more information.
174
+
175
+ Resumption using session tickets is becoming commonly supported by many web
176
+ browsers when making HTTPS requests.
177
+
178
+ For Node.js, clients use the same APIs for resumption with session identifiers
179
+ as for resumption with session tickets. For debugging, if
180
+ [ ` tls.TLSSocket.getTLSTicket() ` ] [ ] returns a value, the session data contains a
181
+ ticket, otherwise it contains client-side session state.
182
+
183
+ Single process servers need no specific implementation to use session tickets.
184
+ To use session tickets across server restarts or load balancers, servers must
185
+ all have the same ticket keys. There are three 16-byte keys internally, but the
186
+ tls API exposes them as a single 48-byte buffer for convenience.
187
+
188
+ Its possible to get the ticket keys by calling [ ` server.getTicketKeys() ` ] [ ] on
189
+ one server instance and then distribute them, but it is more reasonable to
190
+ securely generate 48 bytes of secure random data and set them with the
191
+ ` ticketKeys ` option of [ ` tls.createServer() ` ] [ ] . The keys should be regularly
192
+ regenerated and server's keys can be reset with
193
+ [ ` server.setTicketKeys() ` ] [ ] .
194
+
195
+ Session ticket keys are cryptographic keys, and they *** must be stored
196
+ securely*** . With TLS 1.2 and below, if they are compromised all sessions that
197
+ used tickets encrypted with them can be decrypted. They should not be stored
198
+ on disk, and they should be regenerated regularly.
199
+
200
+ If clients advertise support for tickets, the server will send them. The
201
+ server can disable tickets by supplying
202
+ ` require('constants').SSL_OP_NO_TICKET ` in ` secureOptions ` .
203
+
204
+ Both session identifiers and session tickets timeout, causing the server to
205
+ create new sessions. The timeout can be configured with the ` sessionTimeout `
206
+ option of [ ` tls.createServer() ` ] [ ] .
207
+
208
+ For all the mechanisms, when resumption fails, servers will create new sessions.
209
+ Since failing to resume the session does not cause TLS/HTTPS connection
210
+ failures, it is easy to not notice unnecessarily poor TLS performance. The
211
+ OpenSSL CLI can be used to verify that servers are resuming sessions. Use the
212
+ ` -reconnect ` option to ` openssl s_client ` , for example:
213
+
214
+ ``` sh
215
+ $ openssl s_client -connect localhost:443 -reconnect
216
+ ```
217
+
218
+ Read through the debug output. The first connection should say "New", for
219
+ example:
220
+
221
+ ``` text
222
+ New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
223
+ ```
224
+
225
+ Subsequent connections should say "Reused", for example:
226
+
227
+ ``` text
228
+ Reused, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
229
+ ```
230
+
143
231
## Modifying the Default TLS Cipher suite
144
232
145
233
Node.js is built with a default suite of enabled and disabled TLS ciphers.
@@ -169,10 +257,10 @@ HIGH:
169
257
!CAMELLIA
170
258
```
171
259
172
- This default can be replaced entirely using the [ ` --tls-cipher-list ` ] [ ] command line
173
- switch (directly, or via the [ ` NODE_OPTIONS ` ] [ ] environment variable). For
174
- instance, the following makes ` ECDHE-RSA-AES128-GCM-SHA256:!RC4 ` the default
175
- TLS cipher suite:
260
+ This default can be replaced entirely using the [ ` --tls-cipher-list ` ] [ ] command
261
+ line switch (directly, or via the [ ` NODE_OPTIONS ` ] [ ] environment variable). For
262
+ instance, the following makes ` ECDHE-RSA-AES128-GCM-SHA256:!RC4 ` the default TLS
263
+ cipher suite:
176
264
177
265
``` sh
178
266
node --tls-cipher-list=" ECDHE-RSA-AES128-GCM-SHA256:!RC4" server.js
@@ -221,11 +309,13 @@ added: v0.9.2
221
309
-->
222
310
223
311
The ` 'newSession' ` event is emitted upon creation of a new TLS session. This may
224
- be used to store sessions in external storage. The listener callback is passed
225
- three arguments when called:
312
+ be used to store sessions in external storage. The data should be provided to
313
+ the [ ` 'resumeSession' ` ] [ ] callback.
314
+
315
+ The listener callback is passed three arguments when called:
226
316
227
- * ` sessionId ` - The TLS session identifier
228
- * ` sessionData ` - The TLS session data
317
+ * ` sessionId ` {Buffer} The TLS session identifier
318
+ * ` sessionData ` {Buffer} The TLS session data
229
319
* ` callback ` {Function} A callback function taking no arguments that must be
230
320
invoked in order for data to be sent or received over the secure connection.
231
321
@@ -288,15 +378,19 @@ The `'resumeSession'` event is emitted when the client requests to resume a
288
378
previous TLS session. The listener callback is passed two arguments when
289
379
called:
290
380
291
- * ` sessionId ` - The TLS/SSL session identifier
381
+ * ` sessionId ` {Buffer} The TLS session identifier
292
382
* ` callback ` {Function} A callback function to be called when the prior session
293
- has been recovered.
294
-
295
- When called, the event listener may perform a lookup in external storage using
296
- the given ` sessionId ` and invoke ` callback(null, sessionData) ` once finished. If
297
- the session cannot be resumed (i.e., doesn't exist in storage) the callback may
298
- be invoked as ` callback(null, null) ` . Calling ` callback(err) ` will terminate the
299
- incoming connection and destroy the socket.
383
+ has been recovered: ` callback([err[, sessionData]]) `
384
+ * ` err ` {Error}
385
+ * ` sessionData ` {Buffer}
386
+
387
+ The event listener should perform a lookup in external storage for the
388
+ ` sessionData ` saved by the [ ` 'newSession' ` ] [ ] event handler using the given
389
+ ` sessionId ` . If found, call ` callback(null, sessionData) ` to resume the session.
390
+ If not found, the session cannot be resumed. ` callback() ` must be called
391
+ without ` sessionData ` so that the handshake can continue and a new session can
392
+ be created. It is possible to call ` callback(err) ` to terminate the incoming
393
+ connection and destroy the socket.
300
394
301
395
Listening for this event will have an effect only on connections established
302
396
after the addition of the event listener.
@@ -406,10 +500,11 @@ Returns the current number of concurrent connections on the server.
406
500
added: v3.0.0
407
501
-->
408
502
409
- * Returns: {Buffer}
503
+ * Returns: {Buffer} A 48-byte buffer containing the session ticket keys.
410
504
411
- Returns a ` Buffer ` instance holding the keys currently used for
412
- encryption/decryption of the [ TLS Session Tickets] [ ] .
505
+ Returns the session ticket keys.
506
+
507
+ See [ Session Resumption] [ ] for more information.
413
508
414
509
### server.listen()
415
510
@@ -421,17 +516,15 @@ This method is identical to [`server.listen()`][] from [`net.Server`][].
421
516
added: v3.0.0
422
517
-->
423
518
424
- * ` keys ` {Buffer} The keys used for encryption/decryption of the
425
- [ TLS Session Tickets] [ ] .
426
-
427
- Updates the keys for encryption/decryption of the [ TLS Session Tickets] [ ] .
519
+ * ` keys ` {Buffer} A 48-byte buffer containing the session ticket keys.
428
520
429
- The key's ` Buffer ` should be 48 bytes long. See ` ticketKeys ` option in
430
- [ ` tls.createServer() ` ] for more information on how it is used.
521
+ Sets the session ticket keys.
431
522
432
523
Changes to the ticket keys are effective only for future server connections.
433
524
Existing or currently pending server connections will use the previous keys.
434
525
526
+ See [ Session Resumption] [ ] for more information.
527
+
435
528
## Class: tls.TLSSocket
436
529
<!-- YAML
437
530
added: v0.11.4
@@ -695,19 +788,28 @@ information.
695
788
added: v0.11.4
696
789
-->
697
790
698
- Returns the ASN.1 encoded TLS session or ` undefined ` if no session was
699
- negotiated. Can be used to speed up handshake establishment when reconnecting
700
- to the server.
791
+ * {Buffer}
792
+
793
+ Returns the TLS session data or ` undefined ` if no session was
794
+ negotiated. On the client, the data can be provided to the ` session ` option of
795
+ [ ` tls.connect() ` ] [ ] to resume the connection. On the server, it may be useful
796
+ for debugging.
797
+
798
+ See [ Session Resumption] [ ] for more information.
701
799
702
800
### tlsSocket.getTLSTicket()
703
801
<!-- YAML
704
802
added: v0.11.4
705
803
-->
706
804
707
- Returns the TLS session ticket or ` undefined ` if no session was negotiated.
805
+ * {Buffer}
806
+
807
+ For a client, returns the TLS session ticket if one is available, or
808
+ ` undefined ` . For a server, always returns ` undefined ` .
809
+
810
+ It may be useful for debugging.
708
811
709
- This only works with client TLS sockets. Useful only for debugging, for session
710
- reuse provide ` session ` option to [ ` tls.connect() ` ] [ ] .
812
+ See [ Session Resumption] [ ] for more information.
711
813
712
814
### tlsSocket.localAddress
713
815
<!-- YAML
@@ -1162,18 +1264,17 @@ changes:
1162
1264
* ` requestCert ` {boolean} If ` true ` the server will request a certificate from
1163
1265
clients that connect and attempt to verify that certificate. ** Default:**
1164
1266
` false ` .
1165
- * ` sessionTimeout ` {number} An integer specifying the number of seconds after
1166
- which the TLS session identifiers and TLS session tickets created by the
1167
- server will time out. See [ ` SSL_CTX_set_timeout ` ] for more details .
1267
+ * ` sessionTimeout ` {number} The number of seconds after which a TLS session
1268
+ created by the server will no longer be resumable. See
1269
+ [ Session Resumption ] [ ] for more information. ** Default: ** ` 300 ` .
1168
1270
* ` SNICallback(servername, cb) ` {Function} A function that will be called if
1169
1271
the client supports SNI TLS extension. Two arguments will be passed when
1170
1272
called: ` servername ` and ` cb ` . ` SNICallback ` should invoke ` cb(null, ctx) ` ,
1171
1273
where ` ctx ` is a ` SecureContext ` instance. (` tls.createSecureContext(...) `
1172
1274
can be used to get a proper ` SecureContext ` .) If ` SNICallback ` wasn't
1173
1275
provided the default callback with high-level API will be used (see below).
1174
- * ` ticketKeys ` : A 48-byte ` Buffer ` instance consisting of a 16-byte prefix,
1175
- a 16-byte HMAC key, and a 16-byte AES key. This can be used to accept TLS
1176
- session tickets on multiple instances of the TLS server.
1276
+ * ` ticketKeys ` : {Buffer} 48-bytes of cryptographically strong pseudo-random
1277
+ data. See [ Session Resumption] [ ] for more information.
1177
1278
* ...: Any [ ` tls.createSecureContext() ` ] [ ] option can be provided. For
1178
1279
servers, the identity options (` pfx ` or ` key ` /` cert ` ) are usually required.
1179
1280
* ` secureConnectionListener ` {Function}
@@ -1348,21 +1449,26 @@ secureSocket = tls.TLSSocket(socket, options);
1348
1449
1349
1450
where ` secureSocket ` has the same API as ` pair.cleartext ` .
1350
1451
1452
+ [ `'newSession'` ] : #tls_event_newsession
1453
+ [ `'resumeSession'` ] : #tls_event_resumesession
1351
1454
[ `'secureConnect'` ] : #tls_event_secureconnect
1352
1455
[ `'secureConnection'` ] : #tls_event_secureconnection
1353
1456
[ `--tls-cipher-list` ] : cli.html#cli_tls_cipher_list_list
1354
1457
[ `NODE_OPTIONS` ] : cli.html#cli_node_options_options
1355
- [ `SSL_CTX_set_timeout` ] : https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_timeout.html
1356
1458
[ `crypto.getCurves()` ] : crypto.html#crypto_crypto_getcurves
1357
1459
[ `dns.lookup()` ] : dns.html#dns_dns_lookup_hostname_options_callback
1358
1460
[ `net.Server.address()` ] : net.html#net_server_address
1359
1461
[ `net.Server` ] : net.html#net_class_net_server
1360
1462
[ `net.Socket` ] : net.html#net_class_net_socket
1361
1463
[ `server.getConnections()` ] : net.html#net_server_getconnections_callback
1464
+ [ `server.getTicketKeys()` ] : #tls_server_getticketkeys
1362
1465
[ `server.listen()` ] : net.html#net_server_listen
1466
+ [ `server.setTicketKeys()` ] : #tls_server_setticketkeys_keys
1363
1467
[ `tls.DEFAULT_ECDH_CURVE` ] : #tls_tls_default_ecdh_curve
1364
1468
[ `tls.Server` ] : #tls_class_tls_server
1365
1469
[ `tls.TLSSocket.getPeerCertificate()` ] : #tls_tlssocket_getpeercertificate_detailed
1470
+ [ `tls.TLSSocket.getSession()` ] : #tls_tlssocket_getsession
1471
+ [ `tls.TLSSocket.getTLSTicket()` ] : #tls_tlssocket_gettlsticket
1366
1472
[ `tls.TLSSocket` ] : #tls_class_tls_tlssocket
1367
1473
[ `tls.connect()` ] : #tls_tls_connect_options_callback
1368
1474
[ `tls.createSecureContext()` ] : #tls_tls_createsecurecontext_options
@@ -1376,10 +1482,12 @@ where `secureSocket` has the same API as `pair.cleartext`.
1376
1482
[ OpenSSL Options ] : crypto.html#crypto_openssl_options
1377
1483
[ OpenSSL cipher list format documentation ] : https://www.openssl.org/docs/man1.1.0/apps/ciphers.html#CIPHER-LIST-FORMAT
1378
1484
[ Perfect Forward Secrecy ] : #tls_perfect_forward_secrecy
1485
+ [ RFC 2246 ] : https://www.ietf.org/rfc/rfc2246.txt
1486
+ [ RFC 5077 ] : https://tools.ietf.org/html/rfc5077
1379
1487
[ RFC 5929 ] : https://tools.ietf.org/html/rfc5929
1380
1488
[ SSL_METHODS ] : https://www.openssl.org/docs/man1.1.0/ssl/ssl.html#Dealing-with-Protocol-Methods
1489
+ [ Session Resumption ] : #tls_session_resumption
1381
1490
[ Stream ] : stream.html#stream_stream
1382
- [ TLS Session Tickets ] : https://www.ietf.org/rfc/rfc5077.txt
1383
1491
[ TLS recommendations ] : https://wiki.mozilla.org/Security/Server_Side_TLS
1384
1492
[ asn1.js ] : https://www.npmjs.com/package/asn1.js
1385
1493
[ modifying the default cipher suite ] : #tls_modifying_the_default_tls_cipher_suite
0 commit comments