This is an automated email from the ASF dual-hosted git repository.

maskit 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 2021eda2a1 Add a setting to adjust the maximum PP header size (#12961)
2021eda2a1 is described below

commit 2021eda2a1bfbe61fdf564395ed6325d5baa1e88
Author: Masakazu Kitajo <[email protected]>
AuthorDate: Fri Mar 20 22:04:47 2026 -0600

    Add a setting to adjust the maximum PP header size (#12961)
    
    Add a setting to adjust the maximum PP header size
    
    The original hard coded size is too small if PP version2 is used and the 
header contains many TLV fields.
    This adds a new setting proxy.config.proxy_protocol.max_header_size to read 
a larger but limited amount of data to parse PP header.
    
    This also adds a quick check to detect whether PP header exists. The check 
avoids copying a large amount of data if PP is definitely unused.
---
 doc/admin-guide/files/records.yaml.en.rst | 13 +++++++++++++
 include/iocore/net/NetVConnection.h       |  2 +-
 include/iocore/net/ProxyProtocol.h        |  1 +
 include/proxy/http/HttpConfig.h           |  1 +
 src/iocore/net/NetVConnection.cc          | 14 +++++++++++---
 src/iocore/net/ProxyProtocol.cc           | 15 ++++++++++++++-
 src/proxy/ProtocolProbeSessionAccept.cc   |  6 ++++--
 src/proxy/http/HttpConfig.cc              |  2 ++
 src/records/RecordsConfig.cc              |  9 ++++++++-
 9 files changed, 55 insertions(+), 8 deletions(-)

diff --git a/doc/admin-guide/files/records.yaml.en.rst 
b/doc/admin-guide/files/records.yaml.en.rst
index 43bf2ab7bb..46651a5d66 100644
--- a/doc/admin-guide/files/records.yaml.en.rst
+++ b/doc/admin-guide/files/records.yaml.en.rst
@@ -5214,6 +5214,19 @@ UDP Configuration
    Enables (``1``) or disables (``0``) UDP GRO. When enabled, |TS| will try to 
use it
    when reading the UDP socket.
 
+
+PROXY protocol Configuration
+=============================
+
+.. ts:cv:: CONFIG proxy.config.proxy_protocol.max_header_size INT 109
+   :reloadable:
+
+   Sets the maximum size of PROXY protocol header to receive.
+   The default size is enough for PROXY protocol version 1. The size needs to 
be increased
+   if the version 2 is used with many TLV fields. Although you can set a 
number up to 65535,
+   setting a large number can affect performance.
+
+
 Plug-in Configuration
 =====================
 
diff --git a/include/iocore/net/NetVConnection.h 
b/include/iocore/net/NetVConnection.h
index fedb7328ad..4da6053539 100644
--- a/include/iocore/net/NetVConnection.h
+++ b/include/iocore/net/NetVConnection.h
@@ -505,7 +505,7 @@ public:
   void                 set_proxy_protocol_info(const ProxyProtocol &src);
   const ProxyProtocol &get_proxy_protocol_info() const;
 
-  bool has_proxy_protocol(IOBufferReader *);
+  bool has_proxy_protocol(IOBufferReader *, int max_header_size);
   bool has_proxy_protocol(char *, int64_t *);
 
   template <typename S> S *get_service() const;
diff --git a/include/iocore/net/ProxyProtocol.h 
b/include/iocore/net/ProxyProtocol.h
index 5513ad4fcd..d3a7c73671 100644
--- a/include/iocore/net/ProxyProtocol.h
+++ b/include/iocore/net/ProxyProtocol.h
@@ -145,6 +145,7 @@ private:
 const size_t PPv1_CONNECTION_HEADER_LEN_MAX = 108;
 const size_t PPv2_CONNECTION_HEADER_LEN     = 16;
 
+extern bool                 proxy_protocol_detect(swoc::TextView tv);
 extern size_t               proxy_protocol_parse(ProxyProtocol *pp_info, 
swoc::TextView tv);
 extern size_t               proxy_protocol_build(uint8_t *buf, size_t 
max_buf_len, const ProxyProtocol &pp_info,
                                                  ProxyProtocolVersion 
force_version = ProxyProtocolVersion::UNDEFINED);
diff --git a/include/proxy/http/HttpConfig.h b/include/proxy/http/HttpConfig.h
index 86d3411512..b18dd5581e 100644
--- a/include/proxy/http/HttpConfig.h
+++ b/include/proxy/http/HttpConfig.h
@@ -888,6 +888,7 @@ public:
 
   MgmtInt http_request_line_max_size = 65535;
   MgmtInt http_hdr_field_max_size    = 131070;
+  MgmtInt pp_hdr_max_size            = 109;
 
   MgmtByte http_host_sni_policy         = 0;
   MgmtByte scheme_proto_mismatch_policy = 2;
diff --git a/src/iocore/net/NetVConnection.cc b/src/iocore/net/NetVConnection.cc
index 9453584301..bacfc0e354 100644
--- a/src/iocore/net/NetVConnection.cc
+++ b/src/iocore/net/NetVConnection.cc
@@ -51,11 +51,19 @@ DbgCtl dbg_ctl_ssl{"ssl"};
    If the buffer has PROXY Protocol, it will be consumed by this function.
  */
 bool
-NetVConnection::has_proxy_protocol(IOBufferReader *reader)
+NetVConnection::has_proxy_protocol(IOBufferReader *reader, int max_header_size)
 {
-  char           buf[PPv1_CONNECTION_HEADER_LEN_MAX + 1];
   swoc::TextView tv;
-  tv.assign(buf, reader->memcpy(buf, sizeof(buf), 0));
+
+  char preface[PPv2_CONNECTION_HEADER_LEN];
+  tv.assign(preface, reader->memcpy(preface, sizeof(preface), 0));
+  if (!proxy_protocol_detect(tv)) {
+    return false;
+  }
+
+  int  bufsize = max_header_size;
+  char buf[bufsize];
+  tv.assign(buf, reader->memcpy(buf, bufsize, 0));
 
   size_t len = proxy_protocol_parse(&this->pp_info, tv);
 
diff --git a/src/iocore/net/ProxyProtocol.cc b/src/iocore/net/ProxyProtocol.cc
index 472f544354..1b475c96c5 100644
--- a/src/iocore/net/ProxyProtocol.cc
+++ b/src/iocore/net/ProxyProtocol.cc
@@ -22,6 +22,7 @@
  */
 
 #include "iocore/net/ProxyProtocol.h"
+#include "tscore/Diags.h"
 #include "tscore/ink_assert.h"
 #include "tscore/ink_string.h"
 #include "tscore/ink_inet.h"
@@ -237,7 +238,7 @@ proxy_protocol_v2_parse(ProxyProtocol *pp_info, const 
swoc::TextView &msg)
   uint16_t       tlv_len   = 0;
 
   if (msg.size() < total_len) {
-    Dbg(dbg_ctl_proxyprotocol_v2, "The amount of available data is smaller 
than the expected size");
+    Error("The size of PP header received (%zu) is smaller than the expected 
size (%zu)", msg.size(), total_len);
     return 0;
   }
 
@@ -453,6 +454,18 @@ proxy_protocol_v2_build(uint8_t *buf, size_t max_buf_len, 
const ProxyProtocol &p
 
 } // namespace
 
+bool
+proxy_protocol_detect(swoc::TextView tv)
+{
+  if (tv.size() >= PPv1_CONNECTION_HEADER_LEN_MIN && 
tv.starts_with(PPv1_CONNECTION_PREFACE)) {
+    return true;
+  } else if (tv.size() >= PPv2_CONNECTION_HEADER_LEN && 
tv.starts_with(PPv2_CONNECTION_PREFACE)) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
 /**
    PROXY Protocol Parser
  */
diff --git a/src/proxy/ProtocolProbeSessionAccept.cc 
b/src/proxy/ProtocolProbeSessionAccept.cc
index 40ff286ea0..3ba94633f2 100644
--- a/src/proxy/ProtocolProbeSessionAccept.cc
+++ b/src/proxy/ProtocolProbeSessionAccept.cc
@@ -127,8 +127,10 @@ struct ProtocolProbeTrampoline : public Continuation, 
public ProtocolProbeSessio
             "ioCompletionEvent: proxy protocol DOES NOT have a configured 
allowlist of trusted IPs but proxy protocol is "
             "ernabled on this port - processing all connections");
       }
-
-      if (netvc->has_proxy_protocol(reader)) {
+      HttpConfigParams *param           = HttpConfig::acquire();
+      int               max_header_size = param->pp_hdr_max_size;
+      HttpConfig::release(param);
+      if (netvc->has_proxy_protocol(reader, max_header_size)) {
         Dbg(dbg_ctl_proxyprotocol, "ioCompletionEvent: http has proxy protocol 
header");
       } else {
         Dbg(dbg_ctl_proxyprotocol, "ioCompletionEvent: proxy protocol was 
enabled, but Proxy Protocol header was not present");
diff --git a/src/proxy/http/HttpConfig.cc b/src/proxy/http/HttpConfig.cc
index 7b0d167957..adcb6e8b86 100644
--- a/src/proxy/http/HttpConfig.cc
+++ b/src/proxy/http/HttpConfig.cc
@@ -963,6 +963,7 @@ HttpConfig::startup()
 
   HttpEstablishStaticConfigLongLong(c.http_request_line_max_size, 
"proxy.config.http.request_line_max_size");
   HttpEstablishStaticConfigLongLong(c.http_hdr_field_max_size, 
"proxy.config.http.header_field_max_size");
+  HttpEstablishStaticConfigLongLong(c.pp_hdr_max_size, 
"proxy.config.proxy_protocol.max_header_size");
 
   HttpEstablishStaticConfigByte(c.disable_ssl_parenting, 
"proxy.config.http.parent_proxy.disable_connect_tunneling");
   HttpEstablishStaticConfigByte(c.oride.forward_connect_method, 
"proxy.config.http.forward_connect_method");
@@ -1275,6 +1276,7 @@ HttpConfig::reconfigure()
 
   params->http_request_line_max_size = m_master.http_request_line_max_size;
   params->http_hdr_field_max_size    = m_master.http_hdr_field_max_size;
+  params->pp_hdr_max_size            = m_master.pp_hdr_max_size;
 
   if (params->oride.connection_tracker_config.server_max > 0 &&
       params->oride.connection_tracker_config.server_max < 
params->oride.connection_tracker_config.server_min) {
diff --git a/src/records/RecordsConfig.cc b/src/records/RecordsConfig.cc
index d042a8d153..f2c85649a7 100644
--- a/src/records/RecordsConfig.cc
+++ b/src/records/RecordsConfig.cc
@@ -1544,7 +1544,14 @@ static constexpr RecordElement RecordsConfig[] =
   //# Thread watchdog
   //#
   //###########
-  {RECT_CONFIG, "proxy.config.exec_thread.watchdog.timeout_ms", RECD_INT, "0", 
RECU_RESTART_TS, RR_NULL, RECC_INT, "[0-10000]", RECA_NULL}
+  {RECT_CONFIG, "proxy.config.exec_thread.watchdog.timeout_ms", RECD_INT, "0", 
RECU_RESTART_TS, RR_NULL, RECC_INT, "[0-10000]", RECA_NULL},
+
+  //###########
+  //#
+  //# PROXY protocol
+  //#
+  //###########
+  {RECT_CONFIG, "proxy.config.proxy_protocol.max_header_size", RECD_INT, 
"109", RECU_DYNAMIC, RR_NULL, RECC_INT, "[109-65535]", RECA_NULL},
 };
 // clang-format on
 

Reply via email to