quic: add TLS session ticket resumption support #42734
Envoy/macOS (success)
Check has finished
Details
Check run finished (success ✔️)
The check run can be viewed here:
Envoy/macOS (pr/42734/main@d7a87e4)
Check started by
Request (pr/42734/main@d7a87e4)
@bellatoris
d7a87e4 #42734
merge main@27ea276
quic: add TLS session ticket resumption support
Commit Message: quic: add session ticket resumption support using configured session ticket keys
Additional Description:Summary
TLS session resumption is essential for QUIC performance. Without it, every connection requires a full TLS handshake, and 0-RTT becomes meaningless since there's no session state to resume from. As noted in #42682, TLS-related data accounts for roughly 1/3 of bytes during connection establishment - session resumption eliminates most of this overhead.
Currently, Envoy's QUIC implementation does not support session resumption across workers or processes. While users can configure
session_ticket_keysorsession_ticket_keys_sds_secret_configin downstream TLS context, these settings have no effect on QUIC connections. This limitation is documented in #25418, which explicitly states that session ticket key plumbing is missing from the QUIC implementation.This PR bridges that gap by enabling QUIC to use the same session ticket keys configured for TCP TLS, allowing session resumption to work across workers and processes.
Implementation
We subclass QUICHE's
TlsServerHandshakerasEnvoyTlsServerHandshakerand install a session-ticket key callback on the shared QUICHESSL_CTX. The callback reusesServerContextImpl::sessionTicketProcess()so QUIC and TCP TLS share identical session-ticket handling (same keys, same format, same rotation semantics).Key design decisions:
Per-connection pinning of
ServerContextImpl: EachEnvoyTlsServerHandshakerholds aServerContextSharedPtrcaptured at connection creation, and storesthisin SSL ex_data. The static ticket callback retrieves the handshaker from ex_data and delegates to the pinned context'ssessionTicketProcess(). Because the shared pointer keeps the context alive, an SDS update that rotates the factory's active context does not invalidate in-flight connections — matching TCP TLS behavior where each connection is bound to theServerContextImplactive at connection creation.
SSL_CTX_set_tlsext_ticket_key_cboverSSL_CTX_set_ticket_aead_method: We use the same callback mechanism as TCP TLS rather than QUICHE'sTicketCrypterinterface, soServerContextImpl::sessionTicketProcess()can be reused unchanged.Graceful fallback: If the runtime guard is toggled between
OnNewSslCtx(which installs the callback on the sharedSSL_CTX) and connection creation (which may fall back to the vanilla handshaker), the ticket callback finds a null handshaker in ex_data and returns 0 to skip ticket issuance for that connection rather than crashing.Flow
Server startup (once per SSL_CTX): EnvoyQuicProofSource::OnNewSslCtx() └─ if runtime flag on: SSL_CTX_set_tlsext_ticket_key_cb(ssl_ctx, EnvoyTlsServerHandshaker::ticketKeyCallback) Per connection: EnvoyQuicCryptoServerStreamFactoryImpl::createEnvoyQuicCryptoServerStream() └─ reads SessionTicketConfig from QuicServerTransportSocketFactory └─ constructs EnvoyTlsServerHandshaker(session, crypto_config, factory.sslCtx(), disable_resumption) └─ pins ServerContextSharedPtr └─ SSL_set_ex_data(ssl, handshakerExDataIndex(), this) └─ if disable_resumption || no ticket keys: DisableResumption() // SSL_OP_NO_TICKET During handshake (BoringSSL-driven): ticketKeyCallback(ssl, ...) └─ handshaker = SSL_get_ex_data(ssl, handshakerExDataIndex()) └─ if null: return 0 // guard toggled after OnNewSslCtx — skip ticket └─ return handshaker->pinnedServerContext()->sessionTicketProcess(ssl, ...)Risk Level: Low (behind runtime guard, disabled by default)
Testing: New unit tests forEnvoyTlsServerHandshakerandEnvoyQuicProofSource; new integration coverage insds_dynamic_integration_test(SessionTicketKeysViaSds,SessionTicketKeysRemovedViaSds) and inquic_http_integration_test(SessionTicketResumptionWithStaticKeys,NoSessionTicketResumptionWithoutKeys).
Docs Changes: N/A
Release Notes: Added
Platform Specific Features: N/A
[Optional Runtime guard:]envoy.reloadable_features.quic_session_ticket_support(default: false)
[Optional Fixes #Issue] Partially addresses #25418
Environment
Request variables
| Key | Value |
|---|---|
| ref | dd8ba6f |
| sha | d7a87e4 |
| pr | 42734 |
| base-sha | 27ea276 |
| actor | |
| message | quic: add TLS session ticket resumption support... |
| started | 1777336846.015763 |
| target-branch | main |
| trusted | false |
Build image
Container image/s (as used in this CI run)
| Key | Value |
|---|---|
| default | docker.io/envoyproxy/envoy-build:86873047235e9b8232df989a5999b9bebf9db69c |
| mobile | docker.io/envoyproxy/envoy-build:mobile-86873047235e9b8232df989a5999b9bebf9db69c |
Version
Envoy version (as used in this CI run)
| Key | Value |
|---|---|
| major | 1 |
| minor | 39 |
| patch | 0 |
| dev | true |