This is an automated email from the ASF dual-hosted git repository.
bneradt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 13b94b9417 Add server_cipher_suite to sni.yaml (#12110)
13b94b9417 is described below
commit 13b94b94175b184025ee4f08f8b8641d2b62496b
Author: Brian Neradt <[email protected]>
AuthorDate: Thu Mar 20 10:55:30 2025 -0500
Add server_cipher_suite to sni.yaml (#12110)
Allow the override of records.yaml configurations:
* proxy.config.ssl.server.cipher_suite
* proxy.config.ssl.server.TLSv1_3.cipher_suites
By the following new sni.yaml configurations:
* server_cipher_suite
* server_TLSv1_3_cipher_suites.
---
doc/admin-guide/files/sni.yaml.en.rst | 12 +++++++++
include/iocore/net/TLSBasicSupport.h | 4 +++
include/iocore/net/YamlSNIConfig.h | 4 +++
src/iocore/net/SNIActionPerformer.cc | 31 ++++++++++++++++++++++
src/iocore/net/SNIActionPerformer.h | 31 ++++++++++++++++++++++
src/iocore/net/TLSBasicSupport.cc | 16 +++++++++++
src/iocore/net/YamlSNIConfig.cc | 16 +++++++++++
.../tls/tls_client_versions_minmax.test.py | 11 ++++----
8 files changed, 119 insertions(+), 6 deletions(-)
diff --git a/doc/admin-guide/files/sni.yaml.en.rst
b/doc/admin-guide/files/sni.yaml.en.rst
index 14f04ddeea..2640f2f3e8 100644
--- a/doc/admin-guide/files/sni.yaml.en.rst
+++ b/doc/admin-guide/files/sni.yaml.en.rst
@@ -155,6 +155,18 @@ verify_client_ca_certs Both
Specifies an alternate set of
``verify_client_ca_certs``
can only be used with capabilities provided by
OpenSSL 1.0.2 or later.
+server_cipher_suite Inbound Specifies an override to
the global :ts:cv:`proxy.config.ssl.server.cipher_suite`
+ :file:`records.yaml`
configuration. See the
+ `OpenSSL
SSL_CTX_set_cipher_list
<https://docs.openssl.org/3.1/man3/SSL_CTX_set_cipher_list/>`_
+ documentation. Note that
this configures the cipher suite used for inbound TLS
+ (version 1.2 and below)
connections.
+
+server_TLSv1_3_cipher_suites Inbound Specifies an override to
the global :ts:cv:`proxy.config.ssl.server.TLSv1_3.cipher_suites`
+ :file:`records.yaml`
configuration. See the
+ `OpenSSL
SSL_set_ciphersuites <https://docs.openssl.org/3.1/man3/SSL_set_ciphersuites/>`_
+ documentation. Note that
this configures the cipher suite used for inbound TLSv1.3 and
+ above connections.
+
host_sni_policy Inbound One of the values
:code:`DISABLED`, :code:`PERMISSIVE`, or :code:`ENFORCED`.
If not specified, the value
of :ts:cv:`proxy.config.http.host_sni_policy` is used.
diff --git a/include/iocore/net/TLSBasicSupport.h
b/include/iocore/net/TLSBasicSupport.h
index c269c51c0f..ea5c9aae27 100644
--- a/include/iocore/net/TLSBasicSupport.h
+++ b/include/iocore/net/TLSBasicSupport.h
@@ -24,6 +24,8 @@
#pragma once
+#include <string>
+
#include <openssl/ssl.h>
#include "tscore/ink_hrtime.h"
@@ -59,6 +61,8 @@ public:
void set_valid_tls_version_min(int min);
void set_valid_tls_version_max(int max);
void set_valid_tls_protocols(unsigned long proto_mask, unsigned long
max_mask);
+ void set_legacy_cipher_suite(std::string const &cipher_suite);
+ void set_cipher_suite(std::string const &cipher_suite);
/**
* Give the plugin access to the data structure passed in during the
underlying
diff --git a/include/iocore/net/YamlSNIConfig.h
b/include/iocore/net/YamlSNIConfig.h
index ea7c67377d..3a11dc5a57 100644
--- a/include/iocore/net/YamlSNIConfig.h
+++ b/include/iocore/net/YamlSNIConfig.h
@@ -56,6 +56,8 @@ TSDECL(verify_origin_server);
TSDECL(client_cert);
TSDECL(client_key);
TSDECL(client_sni_policy);
+TSDECL(server_cipher_suite);
+TSDECL(server_TLSv1_3_cipher_suites);
TSDECL(ip_allow);
TSDECL(valid_tls_versions_in);
TSDECL(valid_tls_version_min_in);
@@ -101,6 +103,8 @@ struct YamlSNIConfig {
std::string client_cert;
std::string client_key;
std::string client_sni_policy;
+ std::string server_cipher_suite;
+ std::string server_TLSv1_3_cipher_suites;
std::string ip_allow;
bool protocol_unset = true;
unsigned long protocol_mask;
diff --git a/src/iocore/net/SNIActionPerformer.cc
b/src/iocore/net/SNIActionPerformer.cc
index c34cb652ee..3a83a5772a 100644
--- a/src/iocore/net/SNIActionPerformer.cc
+++ b/src/iocore/net/SNIActionPerformer.cc
@@ -462,3 +462,34 @@ ServerMaxEarlyData::SNIAction([[maybe_unused]] SSL &ssl,
const Context & /* ctx
#endif
return SSL_TLSEXT_ERR_OK;
}
+
+int
+ServerCipherSuite::SNIAction(SSL &ssl, const Context & /* ctx ATS_UNUSED */)
const
+{
+ if (server_cipher_suite.empty()) {
+ return SSL_TLSEXT_ERR_OK;
+ }
+ auto tbs = TLSBasicSupport::getInstance(&ssl);
+ if (tbs == nullptr) {
+ return SSL_TLSEXT_ERR_OK;
+ }
+ Dbg(dbg_ctl_ssl_sni, "Setting pre TLSv1.3 cipher suite from
server_cipher_suite to %s", server_cipher_suite.c_str());
+ tbs->set_legacy_cipher_suite(server_cipher_suite);
+ return SSL_TLSEXT_ERR_OK;
+}
+
+int
+ServerTLSv1_3CipherSuites::SNIAction(SSL &ssl, const Context & /* ctx
ATS_UNUSED */) const
+{
+ if (server_TLSV1_3_cipher_suites.empty()) {
+ return SSL_TLSEXT_ERR_OK;
+ }
+ auto tbs = TLSBasicSupport::getInstance(&ssl);
+ if (tbs == nullptr) {
+ return SSL_TLSEXT_ERR_OK;
+ }
+ Dbg(dbg_ctl_ssl_sni, "Setting TLSv1.3 or later cipher suites from
server_TLSv1_3_cipher_suites to %s",
+ server_TLSV1_3_cipher_suites.c_str());
+ tbs->set_cipher_suite(server_TLSV1_3_cipher_suites);
+ return SSL_TLSEXT_ERR_OK;
+}
diff --git a/src/iocore/net/SNIActionPerformer.h
b/src/iocore/net/SNIActionPerformer.h
index 09236eaf73..f2e8b60e26 100644
--- a/src/iocore/net/SNIActionPerformer.h
+++ b/src/iocore/net/SNIActionPerformer.h
@@ -28,6 +28,7 @@
#include "iocore/net/YamlSNIConfig.h"
#include "tscore/ink_inet.h"
+#include <string>
#include "swoc/TextView.h"
#include <vector>
@@ -311,3 +312,33 @@ private:
uint32_t server_max_early_data = 0;
#endif
};
+
+/**
+ Override proxy.config.ssl.server.cipher_suite by server_cipher_suite in
sni.yaml
+ */
+class ServerCipherSuite : public ActionItem
+{
+public:
+ ServerCipherSuite(std::string const &p) : server_cipher_suite(p) {}
+ ~ServerCipherSuite() override {}
+
+ int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+private:
+ std::string const server_cipher_suite{};
+};
+
+/**
+ Override proxy.config.ssl.server.TLSv1_3.cipher_suites by
server_TLSv1_3_cipher_suites in sni.yaml
+ */
+class ServerTLSv1_3CipherSuites : public ActionItem
+{
+public:
+ ServerTLSv1_3CipherSuites(std::string const &p) :
server_TLSV1_3_cipher_suites(p) {}
+ ~ServerTLSv1_3CipherSuites() override {}
+
+ int SNIAction(SSL &ssl, const Context &ctx) const override;
+
+private:
+ std::string const server_TLSV1_3_cipher_suites{};
+};
diff --git a/src/iocore/net/TLSBasicSupport.cc
b/src/iocore/net/TLSBasicSupport.cc
index add717fb1c..6737d734ae 100644
--- a/src/iocore/net/TLSBasicSupport.cc
+++ b/src/iocore/net/TLSBasicSupport.cc
@@ -169,6 +169,22 @@ TLSBasicSupport::set_valid_tls_version_max(int max)
SSL_set_max_proto_version(ssl, ver);
}
+void
+TLSBasicSupport::set_legacy_cipher_suite(std::string const &cipher_suite)
+{
+ auto ssl = this->_get_ssl_object();
+ SSL_set_cipher_list(ssl, cipher_suite.c_str());
+}
+
+void
+TLSBasicSupport::set_cipher_suite([[maybe_unused]] std::string const
&cipher_suite)
+{
+#if TS_USE_TLS_SET_CIPHERSUITES
+ auto ssl = this->_get_ssl_object();
+ SSL_set_ciphersuites(ssl, cipher_suite.c_str());
+#endif
+}
+
int
TLSBasicSupport::verify_certificate(X509_STORE_CTX *ctx)
{
diff --git a/src/iocore/net/YamlSNIConfig.cc b/src/iocore/net/YamlSNIConfig.cc
index df53e7f363..c5dfd70c7d 100644
--- a/src/iocore/net/YamlSNIConfig.cc
+++ b/src/iocore/net/YamlSNIConfig.cc
@@ -155,6 +155,12 @@ YamlSNIConfig::Item::populate_sni_actions(action_vector_t
&actions)
if (!client_sni_policy.empty()) {
actions.push_back(std::make_unique<OutboundSNIPolicy>(client_sni_policy));
}
+ if (!server_cipher_suite.empty()) {
+
actions.push_back(std::make_unique<ServerCipherSuite>(server_cipher_suite));
+ }
+ if (!server_TLSv1_3_cipher_suites.empty()) {
+
actions.push_back(std::make_unique<ServerTLSv1_3CipherSuites>(server_TLSv1_3_cipher_suites));
+ }
if (http2_buffer_water_mark.has_value()) {
actions.push_back(std::make_unique<HTTP2BufferWaterMark>(http2_buffer_water_mark.value()));
}
@@ -216,6 +222,10 @@ std::set<std::string> valid_sni_config_keys = {TS_fqdn,
TS_client_cert,
TS_client_key,
TS_client_sni_policy,
+ TS_server_cipher_suite,
+#if TS_USE_TLS_SET_CIPHERSUITES
+ TS_server_TLSv1_3_cipher_suites,
+#endif
TS_http2,
TS_http2_buffer_water_mark,
TS_http2_initial_window_size_in,
@@ -442,6 +452,12 @@ template <> struct convert<YamlSNIConfig::Item> {
if (node[TS_client_sni_policy]) {
item.client_sni_policy = node[TS_client_sni_policy].as<std::string>();
}
+ if (node[TS_server_cipher_suite]) {
+ item.server_cipher_suite =
node[TS_server_cipher_suite].as<std::string>();
+ }
+ if (node[TS_server_TLSv1_3_cipher_suites]) {
+ item.server_TLSv1_3_cipher_suites =
node[TS_server_TLSv1_3_cipher_suites].as<std::string>();
+ }
if (node[TS_ip_allow]) {
item.ip_allow = node[TS_ip_allow].as<std::string>();
diff --git a/tests/gold_tests/tls/tls_client_versions_minmax.test.py
b/tests/gold_tests/tls/tls_client_versions_minmax.test.py
index e4054fc82a..9e13b2468c 100644
--- a/tests/gold_tests/tls/tls_client_versions_minmax.test.py
+++ b/tests/gold_tests/tls/tls_client_versions_minmax.test.py
@@ -42,16 +42,10 @@ ts.addSSLfile("ssl/server.key")
# Make sure the TS server certs are different from the origin certs
ts.Disk.ssl_multicert_config.AddLine('dest_ip=* ssl_cert_name=server.pem
ssl_key_name=server.key')
-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'
-
-if Condition.HasOpenSSLVersion("3.0.0"):
- cipher_suite += ":@SECLEVEL=0"
-
ts.Disk.records_config.update(
{
'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir),
'proxy.config.ssl.server.private_key.path':
'{0}'.format(ts.Variables.SSLDir),
- 'proxy.config.ssl.server.cipher_suite': cipher_suite,
'proxy.config.ssl.client.CA.cert.path':
'{0}'.format(ts.Variables.SSLDir),
'proxy.config.url_remap.pristine_host_hdr': 1,
'proxy.config.ssl.server.version.min': 2,
@@ -62,6 +56,10 @@ ts.Disk.records_config.update(
'proxy.config.diags.debug.tags': 'ssl',
})
+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'
+if Condition.HasOpenSSLVersion("3.0.0"):
+ cipher_suite += ":@SECLEVEL=0"
+
# foo.com should only offer the older TLS protocols
# bar.com should terminate.
# empty SNI should tunnel to server_bar
@@ -72,6 +70,7 @@ ts.Disk.sni_yaml.AddLines(
' valid_tls_versions_in: [ TLSv1_2 ]', # This setting should be
ignored in favor of a version range setting
' valid_tls_version_min_in: TLSv1',
' valid_tls_version_max_in: TLSv1_1',
+ f' server_cipher_suite: {cipher_suite}',
])
# Target foo.com for TLSv1_2. Should fail