Skip to content

Commit 2021eda

Browse files
authored
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.
1 parent 33cb77a commit 2021eda

9 files changed

Lines changed: 55 additions & 8 deletions

File tree

doc/admin-guide/files/records.yaml.en.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5214,6 +5214,19 @@ UDP Configuration
52145214
Enables (``1``) or disables (``0``) UDP GRO. When enabled, |TS| will try to use it
52155215
when reading the UDP socket.
52165216

5217+
5218+
PROXY protocol Configuration
5219+
=============================
5220+
5221+
.. ts:cv:: CONFIG proxy.config.proxy_protocol.max_header_size INT 109
5222+
:reloadable:
5223+
5224+
Sets the maximum size of PROXY protocol header to receive.
5225+
The default size is enough for PROXY protocol version 1. The size needs to be increased
5226+
if the version 2 is used with many TLV fields. Although you can set a number up to 65535,
5227+
setting a large number can affect performance.
5228+
5229+
52175230
Plug-in Configuration
52185231
=====================
52195232

include/iocore/net/NetVConnection.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ class NetVConnection : public VConnection, public PluginUserArgs<TS_USER_ARGS_VC
505505
void set_proxy_protocol_info(const ProxyProtocol &src);
506506
const ProxyProtocol &get_proxy_protocol_info() const;
507507

508-
bool has_proxy_protocol(IOBufferReader *);
508+
bool has_proxy_protocol(IOBufferReader *, int max_header_size);
509509
bool has_proxy_protocol(char *, int64_t *);
510510

511511
template <typename S> S *get_service() const;

include/iocore/net/ProxyProtocol.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ class ProxyProtocol
145145
const size_t PPv1_CONNECTION_HEADER_LEN_MAX = 108;
146146
const size_t PPv2_CONNECTION_HEADER_LEN = 16;
147147

148+
extern bool proxy_protocol_detect(swoc::TextView tv);
148149
extern size_t proxy_protocol_parse(ProxyProtocol *pp_info, swoc::TextView tv);
149150
extern size_t proxy_protocol_build(uint8_t *buf, size_t max_buf_len, const ProxyProtocol &pp_info,
150151
ProxyProtocolVersion force_version = ProxyProtocolVersion::UNDEFINED);

include/proxy/http/HttpConfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,7 @@ struct HttpConfigParams : public ConfigInfo {
888888

889889
MgmtInt http_request_line_max_size = 65535;
890890
MgmtInt http_hdr_field_max_size = 131070;
891+
MgmtInt pp_hdr_max_size = 109;
891892

892893
MgmtByte http_host_sni_policy = 0;
893894
MgmtByte scheme_proto_mismatch_policy = 2;

src/iocore/net/NetVConnection.cc

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,19 @@ DbgCtl dbg_ctl_ssl{"ssl"};
5151
If the buffer has PROXY Protocol, it will be consumed by this function.
5252
*/
5353
bool
54-
NetVConnection::has_proxy_protocol(IOBufferReader *reader)
54+
NetVConnection::has_proxy_protocol(IOBufferReader *reader, int max_header_size)
5555
{
56-
char buf[PPv1_CONNECTION_HEADER_LEN_MAX + 1];
5756
swoc::TextView tv;
58-
tv.assign(buf, reader->memcpy(buf, sizeof(buf), 0));
57+
58+
char preface[PPv2_CONNECTION_HEADER_LEN];
59+
tv.assign(preface, reader->memcpy(preface, sizeof(preface), 0));
60+
if (!proxy_protocol_detect(tv)) {
61+
return false;
62+
}
63+
64+
int bufsize = max_header_size;
65+
char buf[bufsize];
66+
tv.assign(buf, reader->memcpy(buf, bufsize, 0));
5967

6068
size_t len = proxy_protocol_parse(&this->pp_info, tv);
6169

src/iocore/net/ProxyProtocol.cc

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
*/
2323

2424
#include "iocore/net/ProxyProtocol.h"
25+
#include "tscore/Diags.h"
2526
#include "tscore/ink_assert.h"
2627
#include "tscore/ink_string.h"
2728
#include "tscore/ink_inet.h"
@@ -237,7 +238,7 @@ proxy_protocol_v2_parse(ProxyProtocol *pp_info, const swoc::TextView &msg)
237238
uint16_t tlv_len = 0;
238239

239240
if (msg.size() < total_len) {
240-
Dbg(dbg_ctl_proxyprotocol_v2, "The amount of available data is smaller than the expected size");
241+
Error("The size of PP header received (%zu) is smaller than the expected size (%zu)", msg.size(), total_len);
241242
return 0;
242243
}
243244

@@ -453,6 +454,18 @@ proxy_protocol_v2_build(uint8_t *buf, size_t max_buf_len, const ProxyProtocol &p
453454

454455
} // namespace
455456

457+
bool
458+
proxy_protocol_detect(swoc::TextView tv)
459+
{
460+
if (tv.size() >= PPv1_CONNECTION_HEADER_LEN_MIN && tv.starts_with(PPv1_CONNECTION_PREFACE)) {
461+
return true;
462+
} else if (tv.size() >= PPv2_CONNECTION_HEADER_LEN && tv.starts_with(PPv2_CONNECTION_PREFACE)) {
463+
return true;
464+
} else {
465+
return false;
466+
}
467+
}
468+
456469
/**
457470
PROXY Protocol Parser
458471
*/

src/proxy/ProtocolProbeSessionAccept.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,10 @@ struct ProtocolProbeTrampoline : public Continuation, public ProtocolProbeSessio
127127
"ioCompletionEvent: proxy protocol DOES NOT have a configured allowlist of trusted IPs but proxy protocol is "
128128
"ernabled on this port - processing all connections");
129129
}
130-
131-
if (netvc->has_proxy_protocol(reader)) {
130+
HttpConfigParams *param = HttpConfig::acquire();
131+
int max_header_size = param->pp_hdr_max_size;
132+
HttpConfig::release(param);
133+
if (netvc->has_proxy_protocol(reader, max_header_size)) {
132134
Dbg(dbg_ctl_proxyprotocol, "ioCompletionEvent: http has proxy protocol header");
133135
} else {
134136
Dbg(dbg_ctl_proxyprotocol, "ioCompletionEvent: proxy protocol was enabled, but Proxy Protocol header was not present");

src/proxy/http/HttpConfig.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,7 @@ HttpConfig::startup()
963963

964964
HttpEstablishStaticConfigLongLong(c.http_request_line_max_size, "proxy.config.http.request_line_max_size");
965965
HttpEstablishStaticConfigLongLong(c.http_hdr_field_max_size, "proxy.config.http.header_field_max_size");
966+
HttpEstablishStaticConfigLongLong(c.pp_hdr_max_size, "proxy.config.proxy_protocol.max_header_size");
966967

967968
HttpEstablishStaticConfigByte(c.disable_ssl_parenting, "proxy.config.http.parent_proxy.disable_connect_tunneling");
968969
HttpEstablishStaticConfigByte(c.oride.forward_connect_method, "proxy.config.http.forward_connect_method");
@@ -1275,6 +1276,7 @@ HttpConfig::reconfigure()
12751276

12761277
params->http_request_line_max_size = m_master.http_request_line_max_size;
12771278
params->http_hdr_field_max_size = m_master.http_hdr_field_max_size;
1279+
params->pp_hdr_max_size = m_master.pp_hdr_max_size;
12781280

12791281
if (params->oride.connection_tracker_config.server_max > 0 &&
12801282
params->oride.connection_tracker_config.server_max < params->oride.connection_tracker_config.server_min) {

src/records/RecordsConfig.cc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1544,7 +1544,14 @@ static constexpr RecordElement RecordsConfig[] =
15441544
//# Thread watchdog
15451545
//#
15461546
//###########
1547-
{RECT_CONFIG, "proxy.config.exec_thread.watchdog.timeout_ms", RECD_INT, "0", RECU_RESTART_TS, RR_NULL, RECC_INT, "[0-10000]", RECA_NULL}
1547+
{RECT_CONFIG, "proxy.config.exec_thread.watchdog.timeout_ms", RECD_INT, "0", RECU_RESTART_TS, RR_NULL, RECC_INT, "[0-10000]", RECA_NULL},
1548+
1549+
//###########
1550+
//#
1551+
//# PROXY protocol
1552+
//#
1553+
//###########
1554+
{RECT_CONFIG, "proxy.config.proxy_protocol.max_header_size", RECD_INT, "109", RECU_DYNAMIC, RR_NULL, RECC_INT, "[109-65535]", RECA_NULL},
15481555
};
15491556
// clang-format on
15501557

0 commit comments

Comments
 (0)