Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Pre-warm TLS Tunnel #7661

Merged
merged 1 commit into from
Oct 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ proxy/http/remap/test_PluginDso
proxy/http/remap/test_PluginFactory
proxy/http/remap/test_RemapPluginInfo
proxy/http/test_proxy_http
proxy/http/test_PreWarm
proxy/http/remap/test_*
proxy/http2/test_libhttp2
proxy/http2/test_Http2DependencyTree
Expand Down
24 changes: 24 additions & 0 deletions doc/admin-guide/files/records.config.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3949,6 +3949,30 @@ SNI Routing
Frequency of checking the activity of SNI Routing Tunnel. Set to ``0`` to disable monitoring of the activity of the SNI tunnels.
The feature is disabled by default.

.. ts:cv:: CONFIG proxy.config.tunnel.prewarm INT 0

Enable :ref:`pre-warming-tls-tunnel`. The feature is disabled by default.

.. ts:cv:: CONFIG proxy.config.tunnel.prewarm.max_stats_size INT 100

Max size of :ref:`dynamic stats for Pre-warming TLS Tunnel <pre-warming-tls-tunnel-stats>`.

.. ts:cv:: CONFIG proxy.config.tunnel.prewarm.algorithm INT 2

Version of pre-warming algorithm.

===== ======================================================================
Value Description
===== ======================================================================
``1`` Periodical pre-warming only
``2`` Event based pre-warming + Periodical pre-warming
===== ======================================================================

.. ts:cv:: CONFIG proxy.config.tunnel.prewarm.event_period INT 1000
:units: milliseconds

Frequency of periodical pre-warming in milli-seconds.

OCSP Stapling Configuration
===========================

Expand Down
21 changes: 21 additions & 0 deletions doc/admin-guide/files/sni.yaml.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,27 @@ tunnel_alpn Inbound List of ALPN Protocol Ids for Partial Blind
This only works with ``partial_blind_route``.
========================= ========= ========================================================================================

Pre-warming TLS Tunnel
----------------------

=============================== ========================================================================================
Key Meaning
=============================== ========================================================================================
tunnel_prewarm Override :ts:cv:`proxy.config.tunnel.prewarm` in records.config.

tunnel_prewarm_srv Enable SRV record lookup on pre-warming. Default is ``false``.

tunnel_prewarm_rate Rate of how many connections to pre-warm. Default is ``1.0``.

tunnel_prewarm_min Minimum number of pre-warming queue size (per thread). Default is ``0``.

tunnel_prewarm_max Maximum number of pre-warming queue size (per thread). Default is ``-1`` (unlimited).

tunnel_prewarm_connect_timeout Timeout for TCP/TLS handshake (in seconds).

tunnel_prewarm_inactive_timeout Inactive timeout for connections in the pool (in seconds).
=============================== ========================================================================================

Client verification, via ``verify_client``, corresponds to setting
:ts:cv:`proxy.config.ssl.client.certification_level` for this connection as noted below.

Expand Down
48 changes: 48 additions & 0 deletions doc/admin-guide/layer-4-routing.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,51 @@ tunneled connection like this, the only transaction hooks that will be triggered
:c:macro:`TS_HTTP_TXN_START_HOOK` and :c:macro:`TS_HTTP_TXN_CLOSE_HOOK`. In addition, because |TS|
does not terminate (and therefore does not decrypt) the connection, it cannot be cached or served from
cache.

.. _pre-warming-tls-tunnel:

Pre-warming TLS Tunnel
======================

Pre-warming TLS Tunnel reduces the latency of TLS connections (``forward_route`` and ``partial_blind_route`` type SNI
Routing). When this feature is enabled, each ET_NET thread makes TLS connections pool per routing type, SNI, and ALPN.

.. figure:: ../uml/images/l4-pre-warming-overview.svg
:align: center

Stats for connection pools are registered dynamically on start up. Details in :ref:`pre-warming-tls-tunnel-stats`.

Examples
--------

.. code:: yaml

sni:
- fqdn: foo.com
http2: off
partial_blind_route: bar.com
client_sni_policy: server_name
tunnel_prewarm: true
tunnel_prewarm_connect_timeout: 10
tunnel_prewarm_inactive_timeout: 150
tunnel_prewarm_max: 100
tunnel_prewarm_min: 10
tunnel_alpn:
- h2

.. code::

proxy.process.tunnel.prewarm.bar.com:443.tls.current_init 0
proxy.process.tunnel.prewarm.bar.com:443.tls.current_open 10
proxy.process.tunnel.prewarm.bar.com:443.tls.total_hit 0
proxy.process.tunnel.prewarm.bar.com:443.tls.total_miss 0
proxy.process.tunnel.prewarm.bar.com:443.tls.total_handshake_time 1106250000
proxy.process.tunnel.prewarm.bar.com:443.tls.total_handshake_count 10
proxy.process.tunnel.prewarm.bar.com:443.tls.total_retry 0
proxy.process.tunnel.prewarm.bar.com:443.tls.http2.current_init 0
proxy.process.tunnel.prewarm.bar.com:443.tls.http2.current_open 10
proxy.process.tunnel.prewarm.bar.com:443.tls.http2.total_hit 0
proxy.process.tunnel.prewarm.bar.com:443.tls.http2.total_miss 0
proxy.process.tunnel.prewarm.bar.com:443.tls.http2.total_handshake_time 1142368000
proxy.process.tunnel.prewarm.bar.com:443.tls.http2.total_handshake_count 10
proxy.process.tunnel.prewarm.bar.com:443.tls.http2.total_retry 0
42 changes: 42 additions & 0 deletions doc/admin-guide/monitoring/statistics/core/ssl.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,45 @@ SSL/TLS
:type: gauge

A gauge of current active SNI Routing Tunnels.

.. _pre-warming-tls-tunnel-stats:

Pre-warming TLS Tunnel
----------------------

Stats for Pre-warming TLS Tunnel is registered dynamically. The ``POOL`` in below represents combination of ``<Hostname of destination>.<Type of Tunnel>.<ALPN Name (if there)>``.

.. ts:stat:: global proxy.process.tunnel.prewarm.POOL.current_init integer
:type: gauge

Represents the current number of initializing connections in the pool.

.. ts:stat:: global proxy.process.tunnel.prewarm.POOL.current_open integer
:type: gauge

Represents the current number of established connections in the pool.

.. ts:stat:: global proxy.process.tunnel.prewarm.POOL.total_hit integer
:type: counter

Represents the total number of pre-warmed connection is used.

.. ts:stat:: global proxy.process.tunnel.prewarm.POOL.total_miss integer
:type: counter

Represents the total number of pre-warmed connection is not used.

.. ts:stat:: global proxy.process.tunnel.prewarm.POOL.total_handshake_time integer
:type: counter

Represents the total number of handshake duration of pre-warming.

.. ts:stat:: global proxy.process.tunnel.prewarm.POOL.total_handshake_count integer
:type: counter

Represents the total number of handshake time of pre-warming.

.. ts:stat:: global proxy.process.tunnel.prewarm.POOL.total_retry integer
:type: counter

Represents the total number of pre-warming retry.
32 changes: 32 additions & 0 deletions doc/uml/l4-pre-warming-overview.uml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
' Licensed under the Apache License, Version 2.0 (the "License");
' you may not use this file except in compliance with the License.
' You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
' Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
' on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
' See the License for the specific language governing permissions and limitations under the License.

@startuml
'title Pre-warm TLS Tunnel
skinparam sequenceMessageAlign direction
skinparam ParticipantPadding 75
'skinparam monochrome reverse
skinparam backgroundColor #white
hide footbox

participant client
participant proxy
participant origin_server

group pre-warm connection pool
proxy -> origin_server : open connection
proxy -> origin_server : open connection
proxy -> origin_server : open connection
...
end
...
group pool size > 0
client -> proxy : open connection
hnote over proxy #white: use pre-warmed connection from pool
rnote over client, origin_server #lightgreen: TLS Partial Blind Tunnel
end
@enduml
3 changes: 3 additions & 0 deletions iocore/eventsystem/I_EThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ struct DiskHandler;
struct EventIO;

class ServerSessionPool;
class PreWarmQueue;

class Event;
class Continuation;

Expand Down Expand Up @@ -349,6 +351,7 @@ class EThread : public Thread
Event *start_event = nullptr;

ServerSessionPool *server_session_pool = nullptr;
PreWarmQueue *prewarm_queue = nullptr;

/** Default handler used until it is overridden.

Expand Down
1 change: 1 addition & 0 deletions iocore/eventsystem/I_Thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ class Thread
ProxyAllocator ioDataAllocator;
ProxyAllocator ioAllocator;
ProxyAllocator ioBlockAllocator;
ProxyAllocator preWarmSMAllocator;
// From InkAPI (plugins wrappers)
ProxyAllocator apiHookAllocator;
ProxyAllocator INKContAllocator;
Expand Down
12 changes: 7 additions & 5 deletions iocore/net/P_SNIActionPerformer.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,9 @@ class ControlH2 : public ActionItem
class TunnelDestination : public ActionItem
{
public:
TunnelDestination(const std::string_view &dest, SNIRoutingType type, const std::vector<int> &alpn)
: destination(dest), type(type), alpn_ids(alpn)
TunnelDestination(const std::string_view &dest, SNIRoutingType type, YamlSNIConfig::TunnelPreWarm prewarm,
const std::vector<int> &alpn)
: destination(dest), type(type), tunnel_prewarm(prewarm), alpn_ids(alpn)
{
need_fix = (destination.find_first_of('$') != std::string::npos);
}
Expand All @@ -115,10 +116,10 @@ class TunnelDestination : public ActionItem
// If needed, we will try to amend the tunnel destination.
if (ctx._fqdn_wildcard_captured_groups && need_fix) {
const auto &fixed_dst = replace_match_groups(destination, *ctx._fqdn_wildcard_captured_groups);
ssl_netvc->set_tunnel_destination(fixed_dst, type);
ssl_netvc->set_tunnel_destination(fixed_dst, type, tunnel_prewarm);
Debug("ssl_sni", "Destination now is [%s], configured [%s], fqdn [%s]", fixed_dst.c_str(), destination.c_str(), servername);
} else {
ssl_netvc->set_tunnel_destination(destination, type);
ssl_netvc->set_tunnel_destination(destination, type, tunnel_prewarm);
Debug("ssl_sni", "Destination now is [%s], fqdn [%s]", destination.c_str(), servername);
}

Expand Down Expand Up @@ -202,7 +203,8 @@ class TunnelDestination : public ActionItem
}

std::string destination;
SNIRoutingType type = SNIRoutingType::NONE;
SNIRoutingType type = SNIRoutingType::NONE;
YamlSNIConfig::TunnelPreWarm tunnel_prewarm = YamlSNIConfig::TunnelPreWarm::UNSET;
const std::vector<int> &alpn_ids;
bool need_fix;
};
Expand Down
23 changes: 17 additions & 6 deletions iocore/net/P_SSLNetVConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,11 +298,13 @@ class SSLNetVConnection : public UnixNetVConnection,
bool decrypt_tunnel() const;
bool upstream_tls() const;
SNIRoutingType tunnel_type() const;
YamlSNIConfig::TunnelPreWarm tunnel_prewarm() const;

void
set_tunnel_destination(const std::string_view &destination, SNIRoutingType type)
set_tunnel_destination(const std::string_view &destination, SNIRoutingType type, YamlSNIConfig::TunnelPreWarm prewarm)
{
_tunnel_type = type;
_tunnel_type = type;
_tunnel_prewarm = prewarm;

auto pos = destination.find(":");
if (nullptr != tunnel_host) {
Expand Down Expand Up @@ -484,10 +486,13 @@ class SSLNetVConnection : public UnixNetVConnection,
HANDSHAKE_HOOKS_DONE
} sslHandshakeHookState = HANDSHAKE_HOOKS_PRE;

int64_t redoWriteSize = 0;
char *tunnel_host = nullptr;
in_port_t tunnel_port = 0;
SNIRoutingType _tunnel_type = SNIRoutingType::NONE;
int64_t redoWriteSize = 0;

char *tunnel_host = nullptr;
in_port_t tunnel_port = 0;
SNIRoutingType _tunnel_type = SNIRoutingType::NONE;
YamlSNIConfig::TunnelPreWarm _tunnel_prewarm = YamlSNIConfig::TunnelPreWarm::UNSET;

X509_STORE_CTX *verify_cert = nullptr;

// Null-terminated string, or nullptr if there is no SNI server name.
Expand Down Expand Up @@ -521,6 +526,12 @@ SSLNetVConnection::tunnel_type() const
return _tunnel_type;
}

inline YamlSNIConfig::TunnelPreWarm
SSLNetVConnection::tunnel_prewarm() const
{
return _tunnel_prewarm;
}

/**
Returns true if this vc was configured for forward_route or partial_blind_route
*/
Expand Down
8 changes: 7 additions & 1 deletion iocore/net/SSLSNIConfig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
****************************************************************************/

#include "P_SSLSNI.h"

#include "PreWarmManager.h"

#include "tscore/Diags.h"
#include "tscore/SimpleTokenizer.h"
#include "tscore/ink_memory.h"
Expand Down Expand Up @@ -77,7 +80,8 @@ SNIConfigParams::loadSNIConfig()
ai->actions.push_back(std::make_unique<TLSValidProtocols>(item.protocol_mask));
}
if (item.tunnel_destination.length() > 0) {
ai->actions.push_back(std::make_unique<TunnelDestination>(item.tunnel_destination, item.tunnel_type, item.tunnel_alpn));
ai->actions.push_back(
std::make_unique<TunnelDestination>(item.tunnel_destination, item.tunnel_type, item.tunnel_prewarm, item.tunnel_alpn));
}
if (!item.client_sni_policy.empty()) {
ai->actions.push_back(std::make_unique<OutboundSNIPolicy>(item.client_sni_policy));
Expand Down Expand Up @@ -200,6 +204,8 @@ SNIConfig::reconfigure()

params->Initialize();
configid = configProcessor.set(configid, params);

prewarmManager.reconfigure();
}

SNIConfigParams *
Expand Down
Loading