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

Reply via email to