From beade2856a9279a3a25800dffe622493b27bf26e Mon Sep 17 00:00:00 2001 From: Fei Deng Date: Wed, 3 Feb 2021 13:37:45 -0600 Subject: [PATCH] origin session reuse --- doc/admin-guide/files/records.config.en.rst | 15 ++ iocore/net/Makefile.am | 4 +- iocore/net/P_SSLConfig.h | 5 + iocore/net/SSLClientUtils.cc | 39 ++++ iocore/net/SSLConfig.cc | 10 + iocore/net/SSLSessionCache.cc | 72 ++++++ iocore/net/SSLSessionCache.h | 17 ++ iocore/net/SSLStats.cc | 4 + iocore/net/SSLStats.h | 1 + iocore/net/SSLUtils.cc | 37 ++++ mgmt/RecordsConfig.cc | 4 + .../tls/tls_origin_session_reuse.test.py | 206 ++++++++++++++++++ 12 files changed, 412 insertions(+), 2 deletions(-) create mode 100644 tests/gold_tests/tls/tls_origin_session_reuse.test.py diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index 8519daf1ed5..8d29b0aecfb 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -3437,6 +3437,21 @@ SSL Termination a single segment after ~1 second of inactivity and the record size ramping mechanism is repeated again. +.. ts:cv:: CONFIG proxy.config.ssl.origin_session_cache INT 0 + + This configuration enables the SSL session cache for the origin server + when set to ``1``. + + Setting to ``0`` disables SSL session cache for the origin server. + +.. ts:cv:: CONFIG proxy.config.ssl.origin_session_cache.size INT 10240 + + This configuration specifies the maximum number of entries + the SSL session cache for the origin server may contain. + + Setting a value less than or equal to ``0`` effectively disables + SSL session cache for the origin server. + .. ts:cv:: CONFIG proxy.config.ssl.session_cache INT 2 Enables the SSL session cache: diff --git a/iocore/net/Makefile.am b/iocore/net/Makefile.am index 34d9fff3586..a07c6114bdd 100644 --- a/iocore/net/Makefile.am +++ b/iocore/net/Makefile.am @@ -150,7 +150,7 @@ libinknet_a_SOURCES = \ P_SSLNextProtocolSet.h \ P_SSLSNI.h \ P_SSLUtils.h \ - P_SSLClientCoordinator.h \ + P_SSLClientCoordinator.h \ P_SSLClientUtils.h \ P_OCSPStapling.h \ P_UDPConnection.h \ @@ -168,7 +168,7 @@ libinknet_a_SOURCES = \ ProxyProtocol.cc \ Socks.cc \ SSLCertLookup.cc \ - SSLClientCoordinator.cc \ + SSLClientCoordinator.cc \ SSLClientUtils.cc \ SSLConfig.cc \ SSLDiags.cc \ diff --git a/iocore/net/P_SSLConfig.h b/iocore/net/P_SSLConfig.h index 382cd079ee2..0ecab2de7dc 100644 --- a/iocore/net/P_SSLConfig.h +++ b/iocore/net/P_SSLConfig.h @@ -78,6 +78,8 @@ struct SSLConfigParams : public ConfigInfo { int configExitOnLoadError; int clientCertLevel; int verify_depth; + int ssl_origin_session_cache; + int ssl_origin_session_cache_size; int ssl_session_cache; // SSL_SESSION_CACHE_MODE int ssl_session_cache_size; int ssl_session_cache_num_buckets; @@ -118,6 +120,8 @@ struct SSLConfigParams : public ConfigInfo { static int ssl_handshake_timeout_in; char *ssl_ocsp_response_path_only; + static int origin_session_cache; + static size_t origin_session_cache_size; static size_t session_cache_number_buckets; static size_t session_cache_max_bucket_size; static bool session_cache_skip_on_lock_contention; @@ -218,3 +222,4 @@ struct SSLTicketKeyConfig { }; extern SSLSessionCache *session_cache; +extern SSLOriginSessionCache *origin_sess_cache; diff --git a/iocore/net/SSLClientUtils.cc b/iocore/net/SSLClientUtils.cc index 012db75b624..d7651788f91 100644 --- a/iocore/net/SSLClientUtils.cc +++ b/iocore/net/SSLClientUtils.cc @@ -29,10 +29,13 @@ #include "P_SSLClientUtils.h" #include "YamlSNIConfig.h" #include "SSLDiags.h" +#include "SSLSessionCache.h" #include #include +SSLOriginSessionCache *origin_sess_cache; + int verify_callback(int signature_ok, X509_STORE_CTX *ctx) { @@ -152,6 +155,37 @@ ssl_client_cert_callback(SSL *ssl, void * /*arg*/) return 1; } +static int +ssl_new_session_callback(SSL *ssl, SSL_SESSION *sess) +{ + const char *tlsext_host_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + if (tlsext_host_name) { + std::string sni(tlsext_host_name); + origin_sess_cache->insert_session(sni, sess); + } else { + int sock_fd = SSL_get_fd(ssl); + sockaddr_storage addr; + socklen_t addr_len = sizeof(addr); + std::string addr_s; + if (sock_fd >= 0) { + getpeername(sock_fd, reinterpret_cast(&addr), &addr_len); + if (addr.ss_family == AF_INET || addr.ss_family == AF_INET6) { + addr_s.assign(reinterpret_cast(&addr), addr_len); + origin_sess_cache->insert_session(addr_s, sess); + } else { + if (is_debug_tag_set("ssl.origin_session_cache")) { + Debug("ssl.origin_session_cache", "unknown address family: %d", addr.ss_family); + } + return 0; + } + } else { + return 0; + } + } + + return 1; +} + SSL_CTX * SSLInitClientContext(const SSLConfigParams *params) { @@ -208,6 +242,11 @@ SSLInitClientContext(const SSLConfigParams *params) SSL_CTX_set_cert_cb(client_ctx, ssl_client_cert_callback, nullptr); + if (params->ssl_origin_session_cache == 1) { + SSL_CTX_set_session_cache_mode(client_ctx, SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_AUTO_CLEAR | SSL_SESS_CACHE_NO_INTERNAL); + SSL_CTX_sess_set_new_cb(client_ctx, ssl_new_session_callback); + } + return client_ctx; fail: diff --git a/iocore/net/SSLConfig.cc b/iocore/net/SSLConfig.cc index 4c34d674522..befa4bb1755 100644 --- a/iocore/net/SSLConfig.cc +++ b/iocore/net/SSLConfig.cc @@ -61,6 +61,8 @@ int SSLConfigParams::ssl_ocsp_cache_timeout = 3600; int SSLConfigParams::ssl_ocsp_request_timeout = 10; int SSLConfigParams::ssl_ocsp_update_period = 60; int SSLConfigParams::ssl_handshake_timeout_in = 0; +int SSLConfigParams::origin_session_cache = 0; +size_t SSLConfigParams::origin_session_cache_size = 10240; size_t SSLConfigParams::session_cache_number_buckets = 1024; bool SSLConfigParams::session_cache_skip_on_lock_contention = false; size_t SSLConfigParams::session_cache_max_bucket_size = 100; @@ -317,6 +319,8 @@ SSLConfigParams::initialize() ats_free(CACertRelativePath); // SSL session cache configurations + REC_ReadConfigInteger(ssl_origin_session_cache, "proxy.config.ssl.origin_session_cache"); + REC_ReadConfigInteger(ssl_origin_session_cache_size, "proxy.config.ssl.origin_session_cache.size"); REC_ReadConfigInteger(ssl_session_cache, "proxy.config.ssl.session_cache"); REC_ReadConfigInteger(ssl_session_cache_size, "proxy.config.ssl.session_cache.size"); REC_ReadConfigInteger(ssl_session_cache_num_buckets, "proxy.config.ssl.session_cache.num_buckets"); @@ -324,6 +328,8 @@ SSLConfigParams::initialize() REC_ReadConfigInteger(ssl_session_cache_timeout, "proxy.config.ssl.session_cache.timeout"); REC_ReadConfigInteger(ssl_session_cache_auto_clear, "proxy.config.ssl.session_cache.auto_clear"); + SSLConfigParams::origin_session_cache = ssl_origin_session_cache; + SSLConfigParams::origin_session_cache_size = ssl_origin_session_cache_size; SSLConfigParams::session_cache_max_bucket_size = static_cast(ceil(static_cast(ssl_session_cache_size) / ssl_session_cache_num_buckets)); SSLConfigParams::session_cache_skip_on_lock_contention = ssl_session_cache_skip_on_contention; @@ -333,6 +339,10 @@ SSLConfigParams::initialize() session_cache = new SSLSessionCache(); } + if (ssl_origin_session_cache == 1 && ssl_origin_session_cache_size > 0) { + origin_sess_cache = new SSLOriginSessionCache(); + } + // SSL record size REC_EstablishStaticConfigInt32(ssl_maxrecord, "proxy.config.ssl.max_record_size"); diff --git a/iocore/net/SSLSessionCache.cc b/iocore/net/SSLSessionCache.cc index 60ec19edb95..e28da8025d9 100644 --- a/iocore/net/SSLSessionCache.cc +++ b/iocore/net/SSLSessionCache.cc @@ -299,3 +299,75 @@ SSLSessionBucket::removeSession(const SSLSessionID &id) SSLSessionBucket::SSLSessionBucket() {} SSLSessionBucket::~SSLSessionBucket() {} + +SSLOriginSessionCache::SSLOriginSessionCache() {} + +SSLOriginSessionCache::~SSLOriginSessionCache() +{ + for (auto &x : origin_sessions) { + SSL_SESSION_free(x.second); + } +} + +void +SSLOriginSessionCache::insert_session(std::string lookup_key, SSL_SESSION *sess) +{ + if (is_debug_tag_set("ssl.origin_session_cache")) { + Debug("ssl.origin_session_cache", "insert session: %lx = %p", std::hash{}(lookup_key), sess); + } + + std::unique_lock lock(mutex); + auto node = origin_sessions.find(lookup_key); + if (node != origin_sessions.end()) { + SSL_SESSION_free(node->second); + } else if (origin_sessions.size() >= SSLConfigParams::origin_session_cache_size) { + remove_oldest_session(lock); + } + origin_sessions[lookup_key] = sess; +} + +void +SSLOriginSessionCache::remove_session(std::string lookup_key) +{ + if (is_debug_tag_set("ssl.origin_session_cache")) { + Debug("ssl.origin_session_cache", "remove session: %lx", std::hash{}(lookup_key)); + } + + std::unique_lock lock(mutex); + auto node = origin_sessions.find(lookup_key); + if (node != origin_sessions.end()) { + SSL_SESSION_free(node->second); + origin_sessions.erase(node); + } +} + +SSL_SESSION * +SSLOriginSessionCache::get_session(std::string lookup_key) +{ + if (is_debug_tag_set("ssl.origin_session_cache")) { + Debug("ssl.origin_session_cache", "get session: %lx", std::hash{}(lookup_key)); + } + + std::shared_lock lock(mutex); + auto node = origin_sessions.find(lookup_key); + if (node == origin_sessions.end()) { + return nullptr; + } + return node->second; +} + +void +SSLOriginSessionCache::remove_oldest_session(const std::unique_lock &lock) +{ + // Caller must hold the bucket shared_mutex with unique_lock. + ink_assert(lock.owns_lock()); + + auto node = origin_sessions.begin(); + + if (is_debug_tag_set("ssl.origin_session_cache")) { + Debug("ssl.origin_session_cache", "remove oldest session: %lx = %p", std::hash{}(node->first), node->second); + } + + SSL_SESSION_free(node->second); + origin_sessions.erase(node); +} diff --git a/iocore/net/SSLSessionCache.h b/iocore/net/SSLSessionCache.h index 05a59307ad0..4e0fc084bfc 100644 --- a/iocore/net/SSLSessionCache.h +++ b/iocore/net/SSLSessionCache.h @@ -198,3 +198,20 @@ class SSLSessionCache SSLSessionBucket *session_bucket = nullptr; size_t nbuckets; }; + +class SSLOriginSessionCache +{ +public: + SSLOriginSessionCache(); + ~SSLOriginSessionCache(); + + void insert_session(std::string lookup_key, SSL_SESSION *sess); + void remove_session(std::string lookup_key); + SSL_SESSION *get_session(std::string lookup_key); + +private: + mutable std::shared_mutex mutex; + std::map origin_sessions; + + void remove_oldest_session(const std::unique_lock &lock); +}; diff --git a/iocore/net/SSLStats.cc b/iocore/net/SSLStats.cc index e3ef2b69b3f..5abd9947b81 100644 --- a/iocore/net/SSLStats.cc +++ b/iocore/net/SSLStats.cc @@ -217,6 +217,10 @@ SSLInitializeStatistics() RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.early_data_received", RECD_INT, RECP_PERSISTENT, (int)ssl_early_data_received_count, RecRawStatSyncCount); + // Origin Server Session Reuse stats + RecRegisterRawStat(ssl_rsb, RECT_PROCESS, "proxy.process.ssl.origin_session_reused", RECD_INT, RECP_PERSISTENT, + (int)ssl_origin_session_reused_count, RecRawStatSyncCount); + // Get and register the SSL cipher stats. Note that we are using the default SSL context to obtain // the cipher list. This means that the set of ciphers is fixed by the build configuration and not // filtered by proxy.config.ssl.server.cipher_suite. This keeps the set of cipher suites stable across diff --git a/iocore/net/SSLStats.h b/iocore/net/SSLStats.h index 9a3bd2f820e..671efa60c78 100644 --- a/iocore/net/SSLStats.h +++ b/iocore/net/SSLStats.h @@ -85,6 +85,7 @@ enum SSL_Stats { ssl_session_cache_lock_contention, ssl_session_cache_new_session, ssl_early_data_received_count, // how many times we received early data + ssl_origin_session_reused_count, /* error stats */ ssl_error_syscall, diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc index 1c2398aae20..a37e8dadd8f 100644 --- a/iocore/net/SSLUtils.cc +++ b/iocore/net/SSLUtils.cc @@ -1888,8 +1888,45 @@ ssl_error_t SSLConnect(SSL *ssl) { ERR_clear_error(); + + SSL_SESSION *sess = nullptr; + std::string lookup_key; + if (SSLConfigParams::origin_session_cache == 1 && SSLConfigParams::origin_session_cache_size > 0) { + const char *tlsext_host_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + if (tlsext_host_name) { + lookup_key.assign(tlsext_host_name); + sess = origin_sess_cache->get_session(lookup_key); + } else { + int sock_fd = SSL_get_fd(ssl); + sockaddr_storage addr; + socklen_t addr_len = sizeof(addr); + if (sock_fd >= 0) { + getpeername(sock_fd, reinterpret_cast(&addr), &addr_len); + if (addr.ss_family == AF_INET || addr.ss_family == AF_INET6) { + lookup_key.assign(reinterpret_cast(&addr), addr_len); + sess = origin_sess_cache->get_session(lookup_key); + } + } + } + } + + if (sess) { + SSL_set_session(ssl, sess); + } + int ret = SSL_connect(ssl); + if (ret > 0) { + if (sess && SSL_session_reused(ssl)) { + SSL_INCREMENT_DYN_STAT(ssl_origin_session_reused_count); + if (is_debug_tag_set("ssl.origin_session_cache")) { + Debug("ssl.origin_session_cache", "reused session to origin: %lx = %p", std::hash{}(lookup_key), sess); + } + } else { + if (is_debug_tag_set("ssl.origin_session_cache")) { + Debug("ssl.origin_session_cache", "new session to origin: %lx = %p", std::hash{}(lookup_key), sess); + } + } return SSL_ERROR_NONE; } int ssl_error = SSL_get_error(ssl, ret); diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc index a7f7db2e379..261aae800dc 100644 --- a/mgmt/RecordsConfig.cc +++ b/mgmt/RecordsConfig.cc @@ -1132,6 +1132,10 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.ssl.client.sni_policy", RECD_STRING, "host", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , + {RECT_CONFIG, "proxy.config.ssl.origin_session_cache", RECD_INT, "0", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + , + {RECT_CONFIG, "proxy.config.ssl.origin_session_cache.size", RECD_INT, "10240", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + , {RECT_CONFIG, "proxy.config.ssl.session_cache", RECD_INT, "2", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_CONFIG, "proxy.config.ssl.session_cache.size", RECD_INT, "102400", RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} diff --git a/tests/gold_tests/tls/tls_origin_session_reuse.test.py b/tests/gold_tests/tls/tls_origin_session_reuse.test.py new file mode 100644 index 00000000000..750e272f507 --- /dev/null +++ b/tests/gold_tests/tls/tls_origin_session_reuse.test.py @@ -0,0 +1,206 @@ +''' +''' +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +import re +Test.Summary = ''' +Test tls origin session reuse +''' + +# Define default ATS +ts1 = Test.MakeATSProcess("ts1", select_ports=True, enable_tls=True) +ts2 = Test.MakeATSProcess("ts2", select_ports=True, enable_tls=True) +ts3 = Test.MakeATSProcess("ts3", select_ports=True, enable_tls=True) +ts4 = Test.MakeATSProcess("ts4", select_ports=True, enable_tls=True) +ts5 = Test.MakeATSProcess("ts5", select_ports=True, enable_tls=True) +server = Test.MakeOriginServer("server") + +# Add info the origin server responses +request_header = { + 'headers': 'GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n', + 'timestamp': '1469733493.993', + 'body': '' +} +response_header = { + 'headers': 'HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n', + 'timestamp': '1469733493.993', + 'body': 'curl test' +} +server.addResponse("sessionlog.json", request_header, response_header) + +# add ssl materials like key, certificates for the server +ts1.addSSLfile("ssl/server.pem") +ts1.addSSLfile("ssl/server.key") +ts2.addSSLfile("ssl/server.pem") +ts2.addSSLfile("ssl/server.key") +ts3.addSSLfile("ssl/server.pem") +ts3.addSSLfile("ssl/server.key") +ts4.addSSLfile("ssl/server.pem") +ts4.addSSLfile("ssl/server.key") +ts5.addSSLfile("ssl/server.pem") +ts5.addSSLfile("ssl/server.key") + +ts1.Disk.remap_config.AddLine( + 'map / http://127.0.0.1:{0}'.format(server.Variables.Port) +) +ts2.Disk.remap_config.AddLine( + 'map / http://127.0.0.1:{0}'.format(server.Variables.Port) +) +ts3.Disk.remap_config.AddLines([ + 'map /ts1 https://127.0.0.1:{0}'.format(ts1.Variables.ssl_port), + 'map /ts2 https://127.0.0.1:{0}'.format(ts2.Variables.ssl_port) +]) +ts4.Disk.remap_config.AddLine( + 'map / http://127.0.0.1:{0}'.format(server.Variables.Port) +) +ts5.Disk.remap_config.AddLine( + 'map / https://127.0.0.1:{0}'.format(ts4.Variables.ssl_port) +) + +ts1.Disk.ssl_multicert_config.AddLine( + 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key' +) +ts2.Disk.ssl_multicert_config.AddLine( + 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key' +) +ts3.Disk.ssl_multicert_config.AddLine( + 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key' +) +ts4.Disk.ssl_multicert_config.AddLine( + 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key' +) +ts5.Disk.ssl_multicert_config.AddLine( + 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key' +) + +ts1.Disk.records_config.update({ + 'proxy.config.http.cache.http': 0, + 'proxy.config.ssl.server.cert.path': '{0}'.format(ts1.Variables.SSLDir), + 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts1.Variables.SSLDir), + 'proxy.config.ssl.server.cipher_suite': 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2', + 'proxy.config.exec_thread.autoconfig.scale': 1.0, + 'proxy.config.ssl.session_cache': 2, + 'proxy.config.ssl.session_cache.size': 4096, + 'proxy.config.ssl.session_cache.num_buckets': 256, + 'proxy.config.ssl.session_cache.skip_cache_on_bucket_contention': 0, + 'proxy.config.ssl.session_cache.timeout': 0, + 'proxy.config.ssl.session_cache.auto_clear': 1, + 'proxy.config.ssl.server.session_ticket.enable': 1, + 'proxy.config.ssl.origin_session_cache': 1, + 'proxy.config.ssl.origin_session_cache.size': 1 +}) +ts2.Disk.records_config.update({ + 'proxy.config.http.cache.http': 0, + 'proxy.config.ssl.server.cert.path': '{0}'.format(ts2.Variables.SSLDir), + 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts2.Variables.SSLDir), + 'proxy.config.ssl.server.cipher_suite': 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2', + 'proxy.config.exec_thread.autoconfig.scale': 1.0, + 'proxy.config.ssl.session_cache': 2, + 'proxy.config.ssl.session_cache.size': 4096, + 'proxy.config.ssl.session_cache.num_buckets': 256, + 'proxy.config.ssl.session_cache.skip_cache_on_bucket_contention': 0, + 'proxy.config.ssl.session_cache.timeout': 0, + 'proxy.config.ssl.session_cache.auto_clear': 1, + 'proxy.config.ssl.server.session_ticket.enable': 1, + 'proxy.config.ssl.origin_session_cache': 1, + 'proxy.config.ssl.origin_session_cache.size': 1 +}) +ts3.Disk.records_config.update({ + 'proxy.config.http.cache.http': 0, + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.diags.debug.tags': 'ssl.origin_session_cache', + 'proxy.config.ssl.server.cert.path': '{0}'.format(ts3.Variables.SSLDir), + 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts3.Variables.SSLDir), + 'proxy.config.ssl.server.cipher_suite': 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2', + 'proxy.config.exec_thread.autoconfig.scale': 1.0, + 'proxy.config.ssl.session_cache': 2, + 'proxy.config.ssl.session_cache.size': 4096, + 'proxy.config.ssl.session_cache.num_buckets': 256, + 'proxy.config.ssl.session_cache.skip_cache_on_bucket_contention': 0, + 'proxy.config.ssl.session_cache.timeout': 0, + 'proxy.config.ssl.session_cache.auto_clear': 1, + 'proxy.config.ssl.server.session_ticket.enable': 1, + 'proxy.config.ssl.origin_session_cache': 1, + 'proxy.config.ssl.origin_session_cache.size': 1 +}) +ts4.Disk.records_config.update({ + 'proxy.config.http.cache.http': 0, + 'proxy.config.ssl.server.cert.path': '{0}'.format(ts4.Variables.SSLDir), + 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts4.Variables.SSLDir), + 'proxy.config.ssl.server.cipher_suite': 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2', + 'proxy.config.exec_thread.autoconfig.scale': 1.0, + 'proxy.config.ssl.session_cache': 2, + 'proxy.config.ssl.session_cache.size': 4096, + 'proxy.config.ssl.session_cache.num_buckets': 256, + 'proxy.config.ssl.session_cache.skip_cache_on_bucket_contention': 0, + 'proxy.config.ssl.session_cache.timeout': 0, + 'proxy.config.ssl.session_cache.auto_clear': 1, + 'proxy.config.ssl.server.session_ticket.enable': 0, + 'proxy.config.ssl.origin_session_cache': 1, + 'proxy.config.ssl.origin_session_cache.size': 1 +}) +ts5.Disk.records_config.update({ + 'proxy.config.http.cache.http': 0, + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.diags.debug.tags': 'ssl.origin_session_cache', + 'proxy.config.ssl.server.cert.path': '{0}'.format(ts5.Variables.SSLDir), + 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts5.Variables.SSLDir), + 'proxy.config.ssl.server.cipher_suite': 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2', + 'proxy.config.exec_thread.autoconfig.scale': 1.0, + 'proxy.config.ssl.session_cache': 2, + 'proxy.config.ssl.session_cache.size': 4096, + 'proxy.config.ssl.session_cache.num_buckets': 256, + 'proxy.config.ssl.session_cache.skip_cache_on_bucket_contention': 0, + 'proxy.config.ssl.session_cache.timeout': 0, + 'proxy.config.ssl.session_cache.auto_clear': 1, + 'proxy.config.ssl.server.session_ticket.enable': 0, + 'proxy.config.ssl.origin_session_cache': 1, + 'proxy.config.ssl.origin_session_cache.size': 1 +}) + +tr = Test.AddTestRun('new session then reuse') +tr.Processes.Default.Command = 'curl https://127.0.0.1:{0}/ts1 -k && curl https://127.0.0.1:{0}/ts1 -k'.format( + ts3.Variables.ssl_port) +tr.Processes.Default.ReturnCode = 0 +tr.Processes.Default.StartBefore(server) +tr.Processes.Default.StartBefore(ts1) +tr.Processes.Default.StartBefore(ts3) +tr.Processes.Default.Streams.All = Testers.ContainsExpression('curl test', 'Making sure the basics still work') +ts3.Streams.All = Testers.ContainsExpression('new session to origin', '') +ts3.Streams.All += Testers.ContainsExpression('reused session to origin', '') +tr.StillRunningAfter = server +tr.StillRunningAfter += ts3 + +tr = Test.AddTestRun('remove oldest session, new session then reuse') +tr.Processes.Default.Command = 'curl https://127.0.0.1:{0}/ts2 -k && curl https://127.0.0.1:{0}/ts2 -k'.format( + ts3.Variables.ssl_port) +tr.Processes.Default.ReturnCode = 0 +tr.Processes.Default.StartBefore(ts2) +tr.Processes.Default.Streams.All = Testers.ContainsExpression('curl test', 'Making sure the basics still work') +ts3.Streams.All = Testers.ContainsExpression('remove oldest session', '') +ts3.Streams.All += Testers.ContainsExpression('new session to origin', '') +ts3.Streams.All += Testers.ContainsExpression('reused session to origin', '') +tr.StillRunningAfter = server + +tr = Test.AddTestRun('disable tls tickets, reuse should fail') +tr.Processes.Default.Command = 'curl https://127.0.0.1:{0} -k && curl https://127.0.0.1:{0} -k'.format(ts5.Variables.ssl_port) +tr.Processes.Default.ReturnCode = 0 +tr.Processes.Default.StartBefore(ts4) +tr.Processes.Default.StartBefore(ts5) +tr.Processes.Default.Streams.All = Testers.ContainsExpression('curl test', 'Making sure the basics still work') +ts5.Streams.All = Testers.ContainsExpression('new session to origin', '') +ts5.Streams.All += Testers.ExcludesExpression('reused session to origin', '')