From 4314fc5acf0d74a5459a88f6b69a5170cd7bfe2b Mon Sep 17 00:00:00 2001 From: Yuchen Dai Date: Fri, 12 Apr 2024 22:42:55 +0000 Subject: [PATCH] transportsocket: add interface to improve reusable tls session Signed-off-by: Yuchen Dai --- envoy/network/transport_socket.h | 6 ++++++ .../network/transport_socket_options_impl.h | 12 +++++++++--- source/common/tls/context_impl.cc | 16 ++++++++++++++-- source/common/tls/context_impl.h | 5 ++++- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/envoy/network/transport_socket.h b/envoy/network/transport_socket.h index 36d9edca1084..bb9cb5166e62 100644 --- a/envoy/network/transport_socket.h +++ b/envoy/network/transport_socket.h @@ -279,6 +279,12 @@ class TransportSocketOptions { * that are marked as shared with the upstream connection. */ virtual const StreamInfo::FilterState::Objects& downstreamSharedFilterStateObjects() const PURE; + + /** + * @return the tag as the hint to select SSL session. This value does not participate the conn + * pool key. + */ + virtual absl::optional sslSessionTag() const PURE; }; using TransportSocketOptionsConstSharedPtr = std::shared_ptr; diff --git a/source/common/network/transport_socket_options_impl.h b/source/common/network/transport_socket_options_impl.h index 2390abface8a..4b4bf8576d45 100644 --- a/source/common/network/transport_socket_options_impl.h +++ b/source/common/network/transport_socket_options_impl.h @@ -36,6 +36,9 @@ class AlpnDecoratingTransportSocketOptions : public TransportSocketOptions { const StreamInfo::FilterState::Objects& downstreamSharedFilterStateObjects() const override { return inner_options_->downstreamSharedFilterStateObjects(); } + absl::optional sslSessionTag() const override { + return inner_options_->sslSessionTag(); + } private: const std::vector alpn_fallback_; @@ -51,15 +54,16 @@ class TransportSocketOptionsImpl : public TransportSocketOptions { absl::optional proxy_proto_options = absl::nullopt, StreamInfo::FilterState::ObjectsPtr filter_state_objects = std::make_unique(), - std::unique_ptr&& proxy_info = nullptr) + std::unique_ptr&& proxy_info = nullptr, + absl::optional ssl_session_tag = absl::nullopt) : override_server_name_(override_server_name.empty() ? absl::nullopt : absl::optional(override_server_name)), override_verify_san_list_{std::move(override_verify_san_list)}, override_alpn_list_{std::move(override_alpn)}, alpn_fallback_{std::move(fallback_alpn)}, proxy_protocol_options_(proxy_proto_options), - filter_state_objects_(std::move(filter_state_objects)), proxy_info_(std::move(proxy_info)) { - } + filter_state_objects_(std::move(filter_state_objects)), proxy_info_(std::move(proxy_info)), + ssl_session_tag_(ssl_session_tag) {} // Network::TransportSocketOptions const absl::optional& serverNameOverride() const override { @@ -86,6 +90,7 @@ class TransportSocketOptionsImpl : public TransportSocketOptions { const StreamInfo::FilterState::Objects& downstreamSharedFilterStateObjects() const override { return *filter_state_objects_; } + absl::optional sslSessionTag() const override { return ssl_session_tag_; } private: const absl::optional override_server_name_; @@ -96,6 +101,7 @@ class TransportSocketOptionsImpl : public TransportSocketOptions { const StreamInfo::FilterState::ObjectsPtr filter_state_objects_; const StreamInfo::FilterStateSharedPtr filter_state_; std::unique_ptr proxy_info_; + const absl::optional ssl_session_tag_; }; class TransportSocketOptionsUtility { diff --git a/source/common/tls/context_impl.cc b/source/common/tls/context_impl.cc index 2669fd8559f5..3586351707dc 100644 --- a/source/common/tls/context_impl.cc +++ b/source/common/tls/context_impl.cc @@ -684,7 +684,16 @@ ClientContextImpl::ClientContextImpl(Stats::Scope& scope, static_cast(SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl))); ClientContextImpl* client_context_impl = dynamic_cast(context_impl); RELEASE_ASSERT(client_context_impl != nullptr, ""); // for Coverity - return client_context_impl->newSessionKey(session); + + const auto* transport_socket_options_shared_ptr_ptr = + static_cast( + SSL_get_app_data(ssl)); + if (transport_socket_options_shared_ptr_ptr == nullptr) { + // 0 indicates that the session is not taken ownership of. + return 0; + } + return client_context_impl->newSessionKey( + (*transport_socket_options_shared_ptr_ptr)->sslSessionTag(), session); }); } } @@ -771,7 +780,10 @@ ClientContextImpl::newSsl(const Network::TransportSocketOptionsConstSharedPtr& o return ssl_con; } -int ClientContextImpl::newSessionKey(SSL_SESSION* session) { +int ClientContextImpl::newSessionKey([[maybe_unused]] absl::optional session_tag, + SSL_SESSION* session) { + // TODO(lambdai): save the session according to ``session_tag``. + // In case we ever store single-use session key (TLS 1.3), // we need to switch to using write/write locks. if (SSL_SESSION_should_be_single_use(session)) { diff --git a/source/common/tls/context_impl.h b/source/common/tls/context_impl.h index 71f04229af51..4f6a84698201 100644 --- a/source/common/tls/context_impl.h +++ b/source/common/tls/context_impl.h @@ -180,7 +180,10 @@ class ClientContextImpl : public ContextImpl, public Envoy::Ssl::ClientContext { newSsl(const Network::TransportSocketOptionsConstSharedPtr& options) override; private: - int newSessionKey(SSL_SESSION* session); + /** + * @return 1 ClientContextImpl retains the reference, 0 otherwise. + */ + int newSessionKey(absl::optional session_tag, SSL_SESSION* session); const std::string server_name_indication_; const bool allow_renegotiation_;