会话票证
服务器加密整个会话状态并将其作为"票证"发送给客户端。 当重新连接时,在初始连接时将状态发送到服务器。 这种机制避免了服务器端会话缓存的需要。 如果服务器不使用票证,出于任何原因(无法解密、太旧等),则它将创建新的会话并发送新的票证。 请参阅 RFC 5077 了解更多信息。
当发出 HTTPS 请求时,许多网络浏览器普遍支持使用会话票证恢复。
对于 Node.js,客户端使用相同的 API 来恢复会话标识符和恢复会话票证。
用于调试,如果 tls.TLSSocket.getTLSTicket()
返回值,则会话数据包含票证,否则包含客户端会话状态。
使用 TLSv1.3,请注意服务器可能会发送多个票证,从而导致多个 'session'
事件,请参阅 'session'
了解更多信息。
单进程服务器不需要特定的实现来使用会话票证。 要在服务器重新启动或负载平衡器之间使用会话票证,服务器必须都具有相同的票证密钥。 内部有三个 16 字节的密钥,但 tls API 为方便起见将它们公开为单个 48 字节的缓冲区。
可以通过在一个服务器实例上调用 server.getTicketKeys()
来获取票证密钥然后分发它们,但是安全地生成 48 字节的安全随机数据并使用 tls.createServer()
的 ticketKeys
选项设置它们更合理。
应该定期重新生成密钥,并且可以使用 server.setTicketKeys()
重置服务器的密钥。
会话票证密钥是加密密钥,它们必须安全存储。 使用 TLS 1.2 及更低版本,如果它们被泄露,所有使用用它们加密的票证的会话都可以解密。 它们不应该存储在磁盘上,应该定期重新生成。
如果客户端宣传支持票证,则服务器将发送它们。
服务器可以通过在 secureOptions
中提供 require('constants').SSL_OP_NO_TICKET
来禁用票证。
会话标识符和会话票证都超时,导致服务器创建新会话。
超时时间可以用 tls.createServer()
的 sessionTimeout
选项配置。
对于所有机制,当恢复失败时,服务器将创建新会话。
由于无法恢复会话不会导致 TLS/HTTPS 连接失败,所以很容易不会注意到 TLS 性能不必要的糟糕。
OpenSSL CLI 可用于验证服务器是否正在恢复会话。
使用 -reconnect
选项到 openssl s_client
,例如:
$ openssl s_client -connect localhost:443 -reconnect
通过调试输出读取。 第一个连接应该说 "New",例如:
New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
后续连接应该说 "Reused",例如:
Reused, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
The servers encrypt the entire session state and send it to the client as a "ticket". When reconnecting, the state is sent to the server in the initial connection. This mechanism avoids the need for server-side session cache. If the server doesn't use the ticket, for any reason (failure to decrypt it, it's too old, etc.), it will create a new session and send a new ticket. See RFC 5077 for more information.
Resumption using session tickets is becoming commonly supported by many web browsers when making HTTPS requests.
For Node.js, clients use the same APIs for resumption with session identifiers
as for resumption with session tickets. For debugging, if
tls.TLSSocket.getTLSTicket()
returns a value, the session data contains a
ticket, otherwise it contains client-side session state.
With TLSv1.3, be aware that multiple tickets may be sent by the server,
resulting in multiple 'session'
events, see 'session'
for more
information.
Single process servers need no specific implementation to use session tickets. To use session tickets across server restarts or load balancers, servers must all have the same ticket keys. There are three 16-byte keys internally, but the tls API exposes them as a single 48-byte buffer for convenience.
Its possible to get the ticket keys by calling server.getTicketKeys()
on
one server instance and then distribute them, but it is more reasonable to
securely generate 48 bytes of secure random data and set them with the
ticketKeys
option of tls.createServer()
. The keys should be regularly
regenerated and server's keys can be reset with
server.setTicketKeys()
.
Session ticket keys are cryptographic keys, and they must be stored securely. With TLS 1.2 and below, if they are compromised all sessions that used tickets encrypted with them can be decrypted. They should not be stored on disk, and they should be regenerated regularly.
If clients advertise support for tickets, the server will send them. The
server can disable tickets by supplying
require('constants').SSL_OP_NO_TICKET
in secureOptions
.
Both session identifiers and session tickets timeout, causing the server to
create new sessions. The timeout can be configured with the sessionTimeout
option of tls.createServer()
.
For all the mechanisms, when resumption fails, servers will create new sessions.
Since failing to resume the session does not cause TLS/HTTPS connection
failures, it is easy to not notice unnecessarily poor TLS performance. The
OpenSSL CLI can be used to verify that servers are resuming sessions. Use the
-reconnect
option to openssl s_client
, for example:
$ openssl s_client -connect localhost:443 -reconnect
Read through the debug output. The first connection should say "New", for example:
New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Subsequent connections should say "Reused", for example:
Reused, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256