Skip to content

quic: add TLS session ticket resumption support#42734

Open
bellatoris wants to merge 36 commits intoenvoyproxy:mainfrom
bellatoris:doogie/quic-proof-source-update
Open

quic: add TLS session ticket resumption support#42734
bellatoris wants to merge 36 commits intoenvoyproxy:mainfrom
bellatoris:doogie/quic-proof-source-update

Conversation

@bellatoris
Copy link
Copy Markdown
Contributor

@bellatoris bellatoris commented Dec 22, 2025

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_keys or session_ticket_keys_sds_secret_config in 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 TlsServerHandshaker as EnvoyTlsServerHandshaker and install a session-ticket key callback on the shared QUICHE SSL_CTX. The callback reuses ServerContextImpl::sessionTicketProcess() so QUIC and TCP TLS share identical session-ticket handling (same keys, same format, same rotation semantics).

Key design decisions:

  1. Per-connection pinning of ServerContextImpl: Each EnvoyTlsServerHandshaker holds a ServerContextSharedPtr captured at connection creation, and stores this in SSL ex_data. The static ticket callback retrieves the handshaker from ex_data and delegates to the pinned context's sessionTicketProcess(). 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 the ServerContextImpl active at connection creation.

  2. SSL_CTX_set_tlsext_ticket_key_cb over SSL_CTX_set_ticket_aead_method: We use the same callback mechanism as TCP TLS rather than QUICHE's TicketCrypter interface, so ServerContextImpl::sessionTicketProcess() can be reused unchanged.

  3. Graceful fallback: If the runtime guard is toggled between OnNewSslCtx (which installs the callback on the shared SSL_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 for EnvoyTlsServerHandshaker and EnvoyQuicProofSource; new integration coverage in sds_dynamic_integration_test (SessionTicketKeysViaSds, SessionTicketKeysRemovedViaSds) and in quic_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

This change enables TLS session ticket resumption for QUIC connections,
allowing clients to resume TLS sessions without full handshakes when
reconnecting across server instances.

Implementation details:
- Add EnvoyTlsServerHandshaker that provides custom ProofSourceHandle
  to intercept certificate selection and configure session ticket options
- Store filter chain pointer in SSL ex_data during handshake to enable
  session ticket callback to access the correct transport socket factory
- Delegate session ticket encryption/decryption to ServerContextImpl
  which uses configured session_ticket_keys
- Add runtime guard envoy.reloadable_features.quic_session_ticket_support
  (default false) to control feature enablement

The feature integrates with existing DownstreamTlsContext configuration:
- Uses session_ticket_keys from TLS context for ticket encryption
- Respects disable_stateless_session_resumption setting
- Honors handles_session_resumption capability flag

Risk Level: Low (behind runtime guard, disabled by default)

Signed-off-by: Doogie Min <doogie.min@sendbird.com>
@repokitteh-read-only
Copy link
Copy Markdown

Hi @bellatoris, welcome and thank you for your contribution.

We will try to review your Pull Request as quickly as possible.

In the meantime, please take a look at the contribution guidelines if you have not done so already.

🐱

Caused by: #42734 was opened by bellatoris.

see: more, trace.

@repokitteh-read-only
Copy link
Copy Markdown

CC @envoyproxy/runtime-guard-changes: FYI only for changes made to (source/common/runtime/runtime_features.cc).

🐱

Caused by: #42734 was opened by bellatoris.

see: more, trace.

@ravenblackx
Copy link
Copy Markdown
Contributor

Please fix format.

/wait

Signed-off-by: Doogie Min <doogie.min@sendbird.com>
@kyessenov
Copy link
Copy Markdown
Contributor

Please merge main.
/wait

@bellatoris
Copy link
Copy Markdown
Contributor Author

Please merge main.

done

@nezdolik
Copy link
Copy Markdown
Member

@bellatoris looks like some CI checks need to be fixed

@bellatoris bellatoris force-pushed the doogie/quic-proof-source-update branch from a5c20f4 to a290a7e Compare January 30, 2026 12:42
@bellatoris
Copy link
Copy Markdown
Contributor Author

@nezdolik seems like they are flaky ones. except code coverage, all tests is passed.

@KBaichoo
Copy link
Copy Markdown
Contributor

KBaichoo commented Feb 5, 2026

/wait

Need merge of main

@ggreenway
Copy link
Copy Markdown
Member

Adding @RyanTheOptimist as a reviewer as @danzh2010 hasn't gotten to this yet.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 7, 2026

This pull request has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions!

@github-actions github-actions Bot added the stale stalebot believes this issue/PR has not been touched recently label Mar 7, 2026
@ggreenway
Copy link
Copy Markdown
Member

@RyanTheOptimist or @danzh2010 please review

@github-actions github-actions Bot removed the stale stalebot believes this issue/PR has not been touched recently label Mar 9, 2026
Signed-off-by: Doogie Min <doogie.min@sendbird.com>
@bellatoris
Copy link
Copy Markdown
Contributor Author

/retest

@danzh2010
Copy link
Copy Markdown
Contributor

Sorry, is it my turn to review this PR or it's still WIP?

@bellatoris
Copy link
Copy Markdown
Contributor Author

bellatoris commented Apr 21, 2026

@danzh2010 please review it 😄. It is ready for review.

Signed-off-by: Doogie Min <doogie.min@sendbird.com>
Comment thread source/common/quic/envoy_tls_server_handshaker.h Outdated
Comment thread test/common/quic/quic_transport_socket_factory_test.cc
Comment thread test/integration/sds_dynamic_integration_test.cc
Comment thread test/common/quic/envoy_quic_proof_source_test.cc Outdated
Comment thread source/common/quic/envoy_quic_proof_source.h Outdated
- Expand EnvoyTlsServerHandshaker class comment to explain pinning rationale,
  ServerContext lifetime, and how it matches TCP TLS behavior
- Restore original order of private members in envoy_quic_proof_source.h
  (zero diff against main for this file)
- Add comment on CreateDownstreamTransportSocketPanics explaining why the
  QUIC transport socket factory is not used to create transport sockets
- Swap order of expectCertChainAndPrivateKey and loadCertsIntoFactory for
  cleaner diff against main

Signed-off-by: Doogie Min <doogie.min@sendbird.com>
The CI spelling checker accepts QUICHE (in tools/spelling/spelling_dictionary.txt)
but not the possessive form QUICHE's. Rewrote the sentence to avoid it.

Signed-off-by: Doogie Min <doogie.min@sendbird.com>
@RyanTheOptimist
Copy link
Copy Markdown
Contributor

Are the comments from @danzh2010 addressed?
Looks like this needs a main merge.
/wait

Signed-off-by: Doogie Min <doogie.min@sendbird.com>
@bellatoris
Copy link
Copy Markdown
Contributor Author

Are the comments from @danzh2010 addressed?

yes

Looks like this needs a main merge.

done

@bellatoris bellatoris requested a review from danzh2010 April 24, 2026 04:00
@bellatoris
Copy link
Copy Markdown
Contributor Author

/retest

danzh2010
danzh2010 previously approved these changes Apr 24, 2026
Copy link
Copy Markdown
Contributor

@danzh2010 danzh2010 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for contributing to QUIC stack!

@danzh2010
Copy link
Copy Markdown
Contributor

Please update the PR description with new implementation approach

@bellatoris
Copy link
Copy Markdown
Contributor Author

Please update the PR description with new implementation approach

@danzh2010 Done, thank you for the review.

Signed-off-by: Doogie Min <doogie.min@sendbird.com>
Signed-off-by: Doogie Min <doogie.min@sendbird.com>
@bellatoris
Copy link
Copy Markdown
Contributor Author

Looks like current.yaml was merged incorrectly in this PR. #44287

@bellatoris
Copy link
Copy Markdown
Contributor Author

/retest

danzh2010
danzh2010 previously approved these changes Apr 27, 2026
@danzh2010
Copy link
Copy Markdown
Contributor

@RyanTheOptimist mind doing another pass? The code has diverged quite a bit since your last stamp.

Signed-off-by: Doogie Min <doogie.min@sendbird.com>
@bellatoris
Copy link
Copy Markdown
Contributor Author

/retest

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants