@@ -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
@@ -433,17 +528,15 @@ existing server. Existing connections to the server are not interrupted.
433
528
added: v3.0.0
434
529
-->
435
530
436
- * ` keys ` {Buffer} The keys used for encryption/decryption of the
437
- [ TLS Session Tickets] [ ] .
438
-
439
- Updates the keys for encryption/decryption of the [ TLS Session Tickets] [ ] .
531
+ * ` keys ` {Buffer} A 48-byte buffer containing the session ticket keys.
440
532
441
- The key's ` Buffer ` should be 48 bytes long. See ` ticketKeys ` option in
442
- [ ` tls.createServer() ` ] for more information on how it is used.
533
+ Sets the session ticket keys.
443
534
444
535
Changes to the ticket keys are effective only for future server connections.
445
536
Existing or currently pending server connections will use the previous keys.
446
537
538
+ See [ Session Resumption] [ ] for more information.
539
+
447
540
## Class: tls.TLSSocket
448
541
<!-- YAML
449
542
added: v0.11.4
@@ -782,19 +875,28 @@ information.
782
875
added: v0.11.4
783
876
-->
784
877
785
- Returns the ASN.1 encoded TLS session or ` undefined ` if no session was
786
- negotiated. Can be used to speed up handshake establishment when reconnecting
787
- to the server.
878
+ * {Buffer}
879
+
880
+ Returns the TLS session data or ` undefined ` if no session was
881
+ negotiated. On the client, the data can be provided to the ` session ` option of
882
+ [ ` tls.connect() ` ] [ ] to resume the connection. On the server, it may be useful
883
+ for debugging.
884
+
885
+ See [ Session Resumption] [ ] for more information.
788
886
789
887
### tlsSocket.getTLSTicket()
790
888
<!-- YAML
791
889
added: v0.11.4
792
890
-->
793
891
794
- Returns the TLS session ticket or ` undefined ` if no session was negotiated.
892
+ * {Buffer}
893
+
894
+ For a client, returns the TLS session ticket if one is available, or
895
+ ` undefined ` . For a server, always returns ` undefined ` .
896
+
897
+ It may be useful for debugging.
795
898
796
- This only works with client TLS sockets. Useful only for debugging, for session
797
- reuse provide ` session ` option to [ ` tls.connect() ` ] [ ] .
899
+ See [ Session Resumption] [ ] for more information.
798
900
799
901
### tlsSocket.localAddress
800
902
<!-- YAML
@@ -1228,18 +1330,17 @@ changes:
1228
1330
* ` requestCert ` {boolean} If ` true ` the server will request a certificate from
1229
1331
clients that connect and attempt to verify that certificate. ** Default:**
1230
1332
` false ` .
1231
- * ` sessionTimeout ` {number} An integer specifying the number of seconds after
1232
- which the TLS session identifiers and TLS session tickets created by the
1233
- server will time out. See [ ` SSL_CTX_set_timeout ` ] for more details .
1333
+ * ` sessionTimeout ` {number} The number of seconds after which a TLS session
1334
+ created by the server will no longer be resumable. See
1335
+ [ Session Resumption ] [ ] for more information. ** Default: ** ` 300 ` .
1234
1336
* ` SNICallback(servername, cb) ` {Function} A function that will be called if
1235
1337
the client supports SNI TLS extension. Two arguments will be passed when
1236
1338
called: ` servername ` and ` cb ` . ` SNICallback ` should invoke ` cb(null, ctx) ` ,
1237
1339
where ` ctx ` is a ` SecureContext ` instance. (` tls.createSecureContext(...) `
1238
1340
can be used to get a proper ` SecureContext ` .) If ` SNICallback ` wasn't
1239
1341
provided the default callback with high-level API will be used (see below).
1240
- * ` ticketKeys ` : A 48-byte ` Buffer ` instance consisting of a 16-byte prefix,
1241
- a 16-byte HMAC key, and a 16-byte AES key. This can be used to accept TLS
1242
- session tickets on multiple instances of the TLS server.
1342
+ * ` ticketKeys ` : {Buffer} 48-bytes of cryptographically strong pseudo-random
1343
+ data. See [ Session Resumption] [ ] for more information.
1243
1344
* ...: Any [ ` tls.createSecureContext() ` ] [ ] option can be provided. For
1244
1345
servers, the identity options (` pfx ` or ` key ` /` cert ` ) are usually required.
1245
1346
* ` secureConnectionListener ` {Function}
@@ -1414,21 +1515,26 @@ secureSocket = tls.TLSSocket(socket, options);
1414
1515
1415
1516
where ` secureSocket ` has the same API as ` pair.cleartext ` .
1416
1517
1518
+ [ `'newSession'` ] : #tls_event_newsession
1519
+ [ `'resumeSession'` ] : #tls_event_resumesession
1417
1520
[ `'secureConnect'` ] : #tls_event_secureconnect
1418
1521
[ `'secureConnection'` ] : #tls_event_secureconnection
1419
1522
[ `--tls-cipher-list` ] : cli.html#cli_tls_cipher_list_list
1420
1523
[ `NODE_OPTIONS` ] : cli.html#cli_node_options_options
1421
- [ `SSL_CTX_set_timeout` ] : https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_timeout.html
1422
1524
[ `crypto.getCurves()` ] : crypto.html#crypto_crypto_getcurves
1423
1525
[ `dns.lookup()` ] : dns.html#dns_dns_lookup_hostname_options_callback
1424
1526
[ `net.Server.address()` ] : net.html#net_server_address
1425
1527
[ `net.Server` ] : net.html#net_class_net_server
1426
1528
[ `net.Socket` ] : net.html#net_class_net_socket
1427
1529
[ `server.getConnections()` ] : net.html#net_server_getconnections_callback
1530
+ [ `server.getTicketKeys()` ] : #tls_server_getticketkeys
1428
1531
[ `server.listen()` ] : net.html#net_server_listen
1532
+ [ `server.setTicketKeys()` ] : #tls_server_setticketkeys_keys
1429
1533
[ `tls.DEFAULT_ECDH_CURVE` ] : #tls_tls_default_ecdh_curve
1430
1534
[ `tls.Server` ] : #tls_class_tls_server
1431
1535
[ `tls.TLSSocket.getPeerCertificate()` ] : #tls_tlssocket_getpeercertificate_detailed
1536
+ [ `tls.TLSSocket.getSession()` ] : #tls_tlssocket_getsession
1537
+ [ `tls.TLSSocket.getTLSTicket()` ] : #tls_tlssocket_gettlsticket
1432
1538
[ `tls.TLSSocket` ] : #tls_class_tls_tlssocket
1433
1539
[ `tls.connect()` ] : #tls_tls_connect_options_callback
1434
1540
[ `tls.createSecureContext()` ] : #tls_tls_createsecurecontext_options
@@ -1443,10 +1549,12 @@ where `secureSocket` has the same API as `pair.cleartext`.
1443
1549
[ OpenSSL Options ] : crypto.html#crypto_openssl_options
1444
1550
[ OpenSSL cipher list format documentation ] : https://www.openssl.org/docs/man1.1.0/apps/ciphers.html#CIPHER-LIST-FORMAT
1445
1551
[ Perfect Forward Secrecy ] : #tls_perfect_forward_secrecy
1552
+ [ RFC 2246 ] : https://www.ietf.org/rfc/rfc2246.txt
1553
+ [ RFC 5077 ] : https://tools.ietf.org/html/rfc5077
1446
1554
[ RFC 5929 ] : https://tools.ietf.org/html/rfc5929
1447
1555
[ SSL_METHODS ] : https://www.openssl.org/docs/man1.1.0/ssl/ssl.html#Dealing-with-Protocol-Methods
1556
+ [ Session Resumption ] : #tls_session_resumption
1448
1557
[ Stream ] : stream.html#stream_stream
1449
- [ TLS Session Tickets ] : https://www.ietf.org/rfc/rfc5077.txt
1450
1558
[ TLS recommendations ] : https://wiki.mozilla.org/Security/Server_Side_TLS
1451
1559
[ asn1.js ] : https://www.npmjs.com/package/asn1.js
1452
1560
[ certificate object ] : #tls_certificate_object
0 commit comments