408 lines
21 KiB
Diff
408 lines
21 KiB
Diff
From b8c6a23b74af1772e5cb0de25b38c234a418cb1d Mon Sep 17 00:00:00 2001
|
|
From: Masakazu Kitajo <maskit@apache.org>
|
|
Date: Wed, 3 Apr 2024 09:31:37 -0600
|
|
Subject: [PATCH] proxy.config.http2.max_continuation_frames_per_minute
|
|
(#11206)
|
|
|
|
Origin: https://github.com/apache/trafficserver/commit/b8c6a23b74af1772e5cb0de25b38c234a418cb1d
|
|
|
|
This adds the ability to rate limite HTTP/2 CONTINUATION frames per
|
|
stream per minute.
|
|
|
|
Co-authored-by: Brian Neradt <brian.neradt@gmail.com>
|
|
---
|
|
doc/admin-guide/files/records.config.en.rst | 11 +++-
|
|
.../statistics/core/http-connection.en.rst | 11 +++-
|
|
iocore/net/P_SNIActionPerformer.h | 17 +++++
|
|
iocore/net/SSLSNIConfig.cc | 4 ++
|
|
iocore/net/TLSSNISupport.h | 1 +
|
|
iocore/net/YamlSNIConfig.cc | 4 ++
|
|
iocore/net/YamlSNIConfig.h | 2 +
|
|
mgmt/RecordsConfig.cc | 2 +
|
|
proxy/http2/HTTP2.cc | 66 ++++++++++---------
|
|
proxy/http2/HTTP2.h | 2 +
|
|
proxy/http2/Http2ConnectionState.cc | 36 ++++++++--
|
|
proxy/http2/Http2ConnectionState.h | 12 ++--
|
|
12 files changed, 126 insertions(+), 42 deletions(-)
|
|
|
|
diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst
|
|
index f3df888708e..979c8bda2f4 100644
|
|
--- a/doc/admin-guide/files/records.config.en.rst
|
|
+++ b/doc/admin-guide/files/records.config.en.rst
|
|
@@ -4287,8 +4287,15 @@ HTTP/2 Configuration
|
|
-.. ts:cv:: CONFIG proxy.config.http2.max_rst_stream_frames_per_minute INT 14
|
|
+.. ts:cv:: CONFIG proxy.config.http2.max_rst_stream_frames_per_minute INT 200
|
|
:reloadable:
|
|
|
|
- Specifies how many RST_STREAM frames |TS| receives for a minute at maximum.
|
|
- Clients exceeded this limit will be immediately disconnected with an error
|
|
+ Specifies how many RST_STREAM frames |TS| receives per minute at maximum.
|
|
+ Clients exceeding this limit will be immediately disconnected with an error
|
|
+ code of ENHANCE_YOUR_CALM.
|
|
+
|
|
+.. ts:cv:: CONFIG proxy.config.http2.max_continuation_frames_per_minute INT 120
|
|
+ :reloadable:
|
|
+
|
|
+ Specifies how many CONTINUATION frames |TS| receives per minute at maximum.
|
|
+ Clients exceeding this limit will be immediately disconnected with an error
|
|
code of ENHANCE_YOUR_CALM.
|
|
|
|
.. ts:cv:: CONFIG proxy.config.http2.min_avg_window_update FLOAT 2560.0
|
|
diff --git a/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst b/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst
|
|
index b22da8e1c66..ee47a147c01 100644
|
|
--- a/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst
|
|
+++ b/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst
|
|
@@ -263,10 +263,17 @@ HTTP/2
|
|
.. ts:stat:: global proxy.process.http2.max_rst_stream_frames_per_minute_exceeded integer
|
|
:type: counter
|
|
|
|
- Represents the total number of closed HTTP/2 connections for exceeding the
|
|
- maximum allowed number of rst_stream frames per minute limit which is configured by
|
|
+ Represents the total number of HTTP/2 connections closed for exceeding the
|
|
+ maximum allowed number of ``RST_STREAM`` frames per minute limit which is configured by
|
|
:ts:cv:`proxy.config.http2.max_rst_stream_frames_per_minute`.
|
|
|
|
+.. ts:stat:: global proxy.process.http2.max_continuation_frames_per_minute_exceeded integer
|
|
+ :type: counter
|
|
+
|
|
+ Represents the total number of HTTP/2 connections closed for exceeding the
|
|
+ maximum allowed number of ``CONTINUATION`` frames per minute limit which is
|
|
+ configured by :ts:cv:`proxy.config.http2.max_continuation_frames_per_minute`.
|
|
+
|
|
.. ts:stat:: global proxy.process.http2.insufficient_avg_window_update integer
|
|
:type: counter
|
|
|
|
diff --git a/iocore/net/P_SNIActionPerformer.h b/iocore/net/P_SNIActionPerformer.h
|
|
index e223ac7d0ba..eebe44b75a1 100644
|
|
--- a/iocore/net/P_SNIActionPerformer.h
|
|
+++ b/iocore/net/P_SNIActionPerformer.h
|
|
@@ -186,6 +186,23 @@ class HTTP2MaxRstStreamFramesPerMinute : public ActionItem
|
|
int value = -1;
|
|
};
|
|
|
|
+class HTTP2MaxContinuationFramesPerMinute : public ActionItem
|
|
+{
|
|
+public:
|
|
+ HTTP2MaxContinuationFramesPerMinute(int value) : value(value) {}
|
|
+ ~HTTP2MaxContinuationFramesPerMinute() override {}
|
|
+
|
|
+ int
|
|
+ SNIAction(TLSSNISupport *snis, const Context &ctx) const override
|
|
+ {
|
|
+ snis->hints_from_sni.http2_max_continuation_frames_per_minute = value;
|
|
+ return SSL_TLSEXT_ERR_OK;
|
|
+ }
|
|
+
|
|
+private:
|
|
+ int value = -1;
|
|
+};
|
|
+
|
|
class TunnelDestination : public ActionItem
|
|
{
|
|
public:
|
|
diff --git a/iocore/net/SSLSNIConfig.cc b/iocore/net/SSLSNIConfig.cc
|
|
index a7071013f6a..942e6c420f0 100644
|
|
--- a/iocore/net/SSLSNIConfig.cc
|
|
+++ b/iocore/net/SSLSNIConfig.cc
|
|
@@ -151,6 +151,10 @@ SNIConfigParams::load_sni_config()
|
|
ai->actions.push_back(
|
|
std::make_unique<HTTP2MaxRstStreamFramesPerMinute>(item.http2_max_rst_stream_frames_per_minute.value()));
|
|
}
|
|
+ if (item.http2_max_continuation_frames_per_minute.has_value()) {
|
|
+ ai->actions.push_back(
|
|
+ std::make_unique<HTTP2MaxContinuationFramesPerMinute>(item.http2_max_continuation_frames_per_minute.value()));
|
|
+ }
|
|
|
|
ai->actions.push_back(std::make_unique<SNI_IpAllow>(item.ip_allow, item.fqdn));
|
|
|
|
diff --git a/iocore/net/TLSSNISupport.h b/iocore/net/TLSSNISupport.h
|
|
index ba2d13e9300..e8614ffa9b8 100644
|
|
--- a/iocore/net/TLSSNISupport.h
|
|
+++ b/iocore/net/TLSSNISupport.h
|
|
@@ -56,6 +56,7 @@ class TLSSNISupport
|
|
std::optional<uint32_t> http2_max_ping_frames_per_minute;
|
|
std::optional<uint32_t> http2_max_priority_frames_per_minute;
|
|
std::optional<uint32_t> http2_max_rst_stream_frames_per_minute;
|
|
+ std::optional<uint32_t> http2_max_continuation_frames_per_minute;
|
|
} hints_from_sni;
|
|
|
|
protected:
|
|
diff --git a/iocore/net/YamlSNIConfig.cc b/iocore/net/YamlSNIConfig.cc
|
|
index 9a777b806f2..7286197c9c7 100644
|
|
--- a/iocore/net/YamlSNIConfig.cc
|
|
+++ b/iocore/net/YamlSNIConfig.cc
|
|
@@ -148,6 +148,7 @@ std::set<std::string> valid_sni_config_keys = {TS_fqdn,
|
|
TS_http2_max_ping_frames_per_minute,
|
|
TS_http2_max_priority_frames_per_minute,
|
|
TS_http2_max_rst_stream_frames_per_minute,
|
|
+ TS_http2_max_continuation_frames_per_minute,
|
|
TS_ip_allow,
|
|
#if TS_USE_HELLO_CB || defined(OPENSSL_IS_BORINGSSL)
|
|
TS_valid_tls_versions_in,
|
|
@@ -193,6 +194,9 @@ template <> struct convert<YamlSNIConfig::Item> {
|
|
if (node[TS_http2_max_rst_stream_frames_per_minute]) {
|
|
item.http2_max_rst_stream_frames_per_minute = node[TS_http2_max_rst_stream_frames_per_minute].as<int>();
|
|
}
|
|
+ if (node[TS_http2_max_continuation_frames_per_minute]) {
|
|
+ item.http2_max_continuation_frames_per_minute = node[TS_http2_max_continuation_frames_per_minute].as<int>();
|
|
+ }
|
|
|
|
// enum
|
|
if (node[TS_verify_client]) {
|
|
diff --git a/iocore/net/YamlSNIConfig.h b/iocore/net/YamlSNIConfig.h
|
|
index b297bd5c16e..8165dc336c5 100644
|
|
--- a/iocore/net/YamlSNIConfig.h
|
|
+++ b/iocore/net/YamlSNIConfig.h
|
|
@@ -60,6 +60,7 @@ TSDECL(http2_max_settings_frames_per_minute);
|
|
TSDECL(http2_max_ping_frames_per_minute);
|
|
TSDECL(http2_max_priority_frames_per_minute);
|
|
TSDECL(http2_max_rst_stream_frames_per_minute);
|
|
+TSDECL(http2_max_continuation_frames_per_minute);
|
|
TSDECL(host_sni_policy);
|
|
#undef TSDECL
|
|
|
|
@@ -94,6 +95,7 @@ struct YamlSNIConfig {
|
|
std::optional<int> http2_max_ping_frames_per_minute;
|
|
std::optional<int> http2_max_priority_frames_per_minute;
|
|
std::optional<int> http2_max_rst_stream_frames_per_minute;
|
|
+ std::optional<int> http2_max_continuation_frames_per_minute;
|
|
|
|
bool tunnel_prewarm_srv = false;
|
|
uint32_t tunnel_prewarm_min = 0;
|
|
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
|
|
index b63e0523c2b..a3752ea8359 100644
|
|
--- a/mgmt/RecordsConfig.cc
|
|
+++ b/mgmt/RecordsConfig.cc
|
|
@@ -1395,6 +1395,8 @@ static const RecordElement RecordsConfig[] =
|
|
,
|
|
{RECT_CONFIG, "proxy.config.http2.max_rst_stream_frames_per_minute", RECD_INT, "200", RECU_DYNAMIC, RR_NULL, RECC_STR, "^[0-9]+$", RECA_NULL}
|
|
,
|
|
+ {RECT_CONFIG, "proxy.config.http2.max_continuation_frames_per_minute", RECD_INT, "120", RECU_DYNAMIC, RR_NULL, RECC_STR, "^[0-9]+$", RECA_NULL}
|
|
+ ,
|
|
{RECT_CONFIG, "proxy.config.http2.min_avg_window_update", RECD_FLOAT, "2560.0", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
|
|
,
|
|
{RECT_CONFIG, "proxy.config.http2.header_table_size_limit", RECD_INT, "65536", RECU_DYNAMIC, RR_NULL, RECC_STR, "^[0-9]+$", RECA_NULL}
|
|
diff --git a/proxy/http2/HTTP2.cc b/proxy/http2/HTTP2.cc
|
|
index 04813d2212b..a3a5a0ac781 100644
|
|
--- a/proxy/http2/HTTP2.cc
|
|
+++ b/proxy/http2/HTTP2.cc
|
|
@@ -85,6 +85,8 @@ static const char *const HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED_NAME
|
|
"proxy.process.http2.max_priority_frames_per_minute_exceeded";
|
|
static const char *const HTTP2_STAT_MAX_RST_STREAM_FRAMES_PER_MINUTE_EXCEEDED_NAME =
|
|
"proxy.process.http2.max_rst_stream_frames_per_minute_exceeded";
|
|
+static const char *const HTTP2_STAT_MAX_CONTINUATION_FRAMES_PER_MINUTE_EXCEEDED_NAME =
|
|
+ "proxy.process.http2.max_continuation_frames_per_minute_exceeded";
|
|
static const char *const HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE_NAME = "proxy.process.http2.insufficient_avg_window_update";
|
|
static const char *const HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_IN_NAME =
|
|
"proxy.process.http2.max_concurrent_streams_exceeded_in";
|
|
@@ -798,36 +800,37 @@ http2_decode_header_blocks(HTTPHdr *hdr, const uint8_t *buf_start, const uint32_
|
|
}
|
|
|
|
// Initialize this subsystem with librecords configs (for now)
|
|
-uint32_t Http2::max_concurrent_streams_in = 100;
|
|
-uint32_t Http2::min_concurrent_streams_in = 10;
|
|
-uint32_t Http2::max_active_streams_in = 0;
|
|
-bool Http2::throttling = false;
|
|
-uint32_t Http2::stream_priority_enabled = 0;
|
|
-uint32_t Http2::initial_window_size = 65535;
|
|
-uint32_t Http2::max_frame_size = 16384;
|
|
-uint32_t Http2::header_table_size = 4096;
|
|
-uint32_t Http2::max_header_list_size = 4294967295;
|
|
-uint32_t Http2::accept_no_activity_timeout = 120;
|
|
-uint32_t Http2::no_activity_timeout_in = 120;
|
|
-uint32_t Http2::active_timeout_in = 0;
|
|
-uint32_t Http2::push_diary_size = 256;
|
|
-uint32_t Http2::zombie_timeout_in = 0;
|
|
-float Http2::stream_error_rate_threshold = 0.1;
|
|
-uint32_t Http2::stream_error_sampling_threshold = 10;
|
|
-uint32_t Http2::max_settings_per_frame = 7;
|
|
-uint32_t Http2::max_settings_per_minute = 14;
|
|
-uint32_t Http2::max_settings_frames_per_minute = 14;
|
|
-uint32_t Http2::max_ping_frames_per_minute = 60;
|
|
-uint32_t Http2::max_priority_frames_per_minute = 120;
|
|
-uint32_t Http2::max_rst_stream_frames_per_minute = 200;
|
|
-float Http2::min_avg_window_update = 2560.0;
|
|
-uint32_t Http2::con_slow_log_threshold = 0;
|
|
-uint32_t Http2::stream_slow_log_threshold = 0;
|
|
-uint32_t Http2::header_table_size_limit = 65536;
|
|
-uint32_t Http2::write_buffer_block_size = 262144;
|
|
-float Http2::write_size_threshold = 0.5;
|
|
-uint32_t Http2::write_time_threshold = 100;
|
|
-uint32_t Http2::buffer_water_mark = 0;
|
|
+uint32_t Http2::max_concurrent_streams_in = 100;
|
|
+uint32_t Http2::min_concurrent_streams_in = 10;
|
|
+uint32_t Http2::max_active_streams_in = 0;
|
|
+bool Http2::throttling = false;
|
|
+uint32_t Http2::stream_priority_enabled = 0;
|
|
+uint32_t Http2::initial_window_size = 65535;
|
|
+uint32_t Http2::max_frame_size = 16384;
|
|
+uint32_t Http2::header_table_size = 4096;
|
|
+uint32_t Http2::max_header_list_size = 4294967295;
|
|
+uint32_t Http2::accept_no_activity_timeout = 120;
|
|
+uint32_t Http2::no_activity_timeout_in = 120;
|
|
+uint32_t Http2::active_timeout_in = 0;
|
|
+uint32_t Http2::push_diary_size = 256;
|
|
+uint32_t Http2::zombie_timeout_in = 0;
|
|
+float Http2::stream_error_rate_threshold = 0.1;
|
|
+uint32_t Http2::stream_error_sampling_threshold = 10;
|
|
+uint32_t Http2::max_settings_per_frame = 7;
|
|
+uint32_t Http2::max_settings_per_minute = 14;
|
|
+uint32_t Http2::max_settings_frames_per_minute = 14;
|
|
+uint32_t Http2::max_ping_frames_per_minute = 60;
|
|
+uint32_t Http2::max_priority_frames_per_minute = 120;
|
|
+uint32_t Http2::max_rst_stream_frames_per_minute = 200;
|
|
+uint32_t Http2::max_continuation_frames_per_minute = 120;
|
|
+float Http2::min_avg_window_update = 2560.0;
|
|
+uint32_t Http2::con_slow_log_threshold = 0;
|
|
+uint32_t Http2::stream_slow_log_threshold = 0;
|
|
+uint32_t Http2::header_table_size_limit = 65536;
|
|
+uint32_t Http2::write_buffer_block_size = 262144;
|
|
+float Http2::write_size_threshold = 0.5;
|
|
+uint32_t Http2::write_time_threshold = 100;
|
|
+uint32_t Http2::buffer_water_mark = 0;
|
|
|
|
void
|
|
Http2::init()
|
|
@@ -853,6 +856,7 @@ Http2::init()
|
|
REC_EstablishStaticConfigInt32U(max_ping_frames_per_minute, "proxy.config.http2.max_ping_frames_per_minute");
|
|
REC_EstablishStaticConfigInt32U(max_priority_frames_per_minute, "proxy.config.http2.max_priority_frames_per_minute");
|
|
REC_EstablishStaticConfigInt32U(max_rst_stream_frames_per_minute, "proxy.config.http2.max_rst_stream_frames_per_minute");
|
|
+ REC_EstablishStaticConfigInt32U(max_continuation_frames_per_minute, "proxy.config.http2.max_continuation_frames_per_minute");
|
|
REC_EstablishStaticConfigFloat(min_avg_window_update, "proxy.config.http2.min_avg_window_update");
|
|
REC_EstablishStaticConfigInt32U(con_slow_log_threshold, "proxy.config.http2.connection.slow.log.threshold");
|
|
REC_EstablishStaticConfigInt32U(stream_slow_log_threshold, "proxy.config.http2.stream.slow.log.threshold");
|
|
@@ -923,6 +927,8 @@ Http2::init()
|
|
static_cast<int>(HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum);
|
|
RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_RST_STREAM_FRAMES_PER_MINUTE_EXCEEDED_NAME, RECD_INT, RECP_PERSISTENT,
|
|
static_cast<int>(HTTP2_STAT_MAX_RST_STREAM_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum);
|
|
+ RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_CONTINUATION_FRAMES_PER_MINUTE_EXCEEDED_NAME, RECD_INT,
|
|
+ RECP_PERSISTENT, static_cast<int>(HTTP2_STAT_MAX_CONTINUATION_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum);
|
|
RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE_NAME, RECD_INT, RECP_PERSISTENT,
|
|
static_cast<int>(HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE), RecRawStatSyncSum);
|
|
RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_IN_NAME, RECD_INT, RECP_PERSISTENT,
|
|
diff --git a/proxy/http2/HTTP2.h b/proxy/http2/HTTP2.h
|
|
index 5847865a9a4..857b199c05d 100644
|
|
--- a/proxy/http2/HTTP2.h
|
|
+++ b/proxy/http2/HTTP2.h
|
|
@@ -105,6 +105,7 @@ enum {
|
|
HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED,
|
|
HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED,
|
|
HTTP2_STAT_MAX_RST_STREAM_FRAMES_PER_MINUTE_EXCEEDED,
|
|
+ HTTP2_STAT_MAX_CONTINUATION_FRAMES_PER_MINUTE_EXCEEDED,
|
|
HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE,
|
|
HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_IN,
|
|
HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_OUT,
|
|
@@ -404,6 +405,7 @@ class Http2
|
|
static uint32_t max_ping_frames_per_minute;
|
|
static uint32_t max_priority_frames_per_minute;
|
|
static uint32_t max_rst_stream_frames_per_minute;
|
|
+ static uint32_t max_continuation_frames_per_minute;
|
|
static float min_avg_window_update;
|
|
static uint32_t con_slow_log_threshold;
|
|
static uint32_t stream_slow_log_threshold;
|
|
diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc
|
|
index b36e5c11793..b089048eb1d 100644
|
|
--- a/proxy/http2/Http2ConnectionState.cc
|
|
+++ b/proxy/http2/Http2ConnectionState.cc
|
|
@@ -924,6 +924,18 @@ rcv_continuation_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
|
|
}
|
|
}
|
|
|
|
+ // Update CONTINUATION frame count per minute.
|
|
+ cstate.increment_received_continuation_frame_count();
|
|
+ // Close this connection if its CONTINUATION frame count exceeds a limit.
|
|
+ if (cstate.configured_max_continuation_frames_per_minute != 0 &&
|
|
+ cstate.get_received_continuation_frame_count() > cstate.configured_max_continuation_frames_per_minute) {
|
|
+ HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_CONTINUATION_FRAMES_PER_MINUTE_EXCEEDED, this_ethread());
|
|
+ Http2StreamDebug(cstate.session, stream_id, "Observed too frequent CONTINUATION frames: %u frames within a last minute",
|
|
+ cstate.get_received_continuation_frame_count());
|
|
+ return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
|
|
+ "reset too frequent CONTINUATION frames");
|
|
+ }
|
|
+
|
|
uint32_t header_blocks_offset = stream->header_blocks_length;
|
|
stream->header_blocks_length += payload_length;
|
|
|
|
@@ -1088,10 +1100,11 @@ Http2ConnectionState::init(Http2CommonSession *ssn)
|
|
dependency_tree = new DependencyTree(Http2::max_concurrent_streams_in);
|
|
}
|
|
|
|
- configured_max_settings_frames_per_minute = Http2::max_settings_frames_per_minute;
|
|
- configured_max_ping_frames_per_minute = Http2::max_ping_frames_per_minute;
|
|
- configured_max_priority_frames_per_minute = Http2::max_priority_frames_per_minute;
|
|
- configured_max_rst_stream_frames_per_minute = Http2::max_rst_stream_frames_per_minute;
|
|
+ configured_max_settings_frames_per_minute = Http2::max_settings_frames_per_minute;
|
|
+ configured_max_ping_frames_per_minute = Http2::max_ping_frames_per_minute;
|
|
+ configured_max_priority_frames_per_minute = Http2::max_priority_frames_per_minute;
|
|
+ configured_max_rst_stream_frames_per_minute = Http2::max_rst_stream_frames_per_minute;
|
|
+ configured_max_continuation_frames_per_minute = Http2::max_continuation_frames_per_minute;
|
|
if (auto snis = dynamic_cast<TLSSNISupport *>(session->get_netvc()); snis) {
|
|
if (snis->hints_from_sni.http2_max_settings_frames_per_minute.has_value()) {
|
|
configured_max_settings_frames_per_minute = snis->hints_from_sni.http2_max_settings_frames_per_minute.value();
|
|
@@ -1105,6 +1118,9 @@ Http2ConnectionState::init(Http2CommonSession *ssn)
|
|
if (snis->hints_from_sni.http2_max_rst_stream_frames_per_minute.has_value()) {
|
|
configured_max_rst_stream_frames_per_minute = snis->hints_from_sni.http2_max_rst_stream_frames_per_minute.value();
|
|
}
|
|
+ if (snis->hints_from_sni.http2_max_continuation_frames_per_minute.has_value()) {
|
|
+ configured_max_continuation_frames_per_minute = snis->hints_from_sni.http2_max_continuation_frames_per_minute.value();
|
|
+ }
|
|
}
|
|
|
|
_cop = ActivityCop<Http2Stream>(this->mutex, &stream_list, 1);
|
|
@@ -2140,6 +2156,18 @@ Http2ConnectionState::get_received_rst_stream_frame_count()
|
|
return this->_received_rst_stream_frame_counter.get_count();
|
|
}
|
|
|
|
+void
|
|
+Http2ConnectionState::increment_received_continuation_frame_count()
|
|
+{
|
|
+ this->_received_continuation_frame_counter.increment();
|
|
+}
|
|
+
|
|
+uint32_t
|
|
+Http2ConnectionState::get_received_continuation_frame_count()
|
|
+{
|
|
+ return this->_received_continuation_frame_counter.get_count();
|
|
+}
|
|
+
|
|
// Return min_concurrent_streams_in when current client streams number is larger than max_active_streams_in.
|
|
// Main purpose of this is preventing DDoS Attacks.
|
|
unsigned
|
|
diff --git a/proxy/http2/Http2ConnectionState.h b/proxy/http2/Http2ConnectionState.h
|
|
index 76d2e2a8e17..fff7763f2a1 100644
|
|
--- a/proxy/http2/Http2ConnectionState.h
|
|
+++ b/proxy/http2/Http2ConnectionState.h
|
|
@@ -102,10 +102,11 @@ class Http2ConnectionState : public Continuation
|
|
Http2ConnectionSettings server_settings;
|
|
Http2ConnectionSettings client_settings;
|
|
|
|
- uint32_t configured_max_settings_frames_per_minute = 0;
|
|
- uint32_t configured_max_ping_frames_per_minute = 0;
|
|
- uint32_t configured_max_priority_frames_per_minute = 0;
|
|
- uint32_t configured_max_rst_stream_frames_per_minute = 0;
|
|
+ uint32_t configured_max_settings_frames_per_minute = 0;
|
|
+ uint32_t configured_max_ping_frames_per_minute = 0;
|
|
+ uint32_t configured_max_priority_frames_per_minute = 0;
|
|
+ uint32_t configured_max_rst_stream_frames_per_minute = 0;
|
|
+ uint32_t configured_max_continuation_frames_per_minute = 0;
|
|
|
|
void init(Http2CommonSession *ssn);
|
|
void send_connection_preface();
|
|
@@ -174,6 +175,8 @@ class Http2ConnectionState : public Continuation
|
|
uint32_t get_received_priority_frame_count();
|
|
void increment_received_rst_stream_frame_count();
|
|
uint32_t get_received_rst_stream_frame_count();
|
|
+ void increment_received_continuation_frame_count();
|
|
+ uint32_t get_received_continuation_frame_count();
|
|
|
|
ssize_t client_rwnd() const;
|
|
Http2ErrorCode increment_client_rwnd(size_t amount);
|
|
@@ -220,6 +223,7 @@ class Http2ConnectionState : public Continuation
|
|
Http2FrequencyCounter _received_ping_frame_counter;
|
|
Http2FrequencyCounter _received_priority_frame_counter;
|
|
Http2FrequencyCounter _received_rst_stream_frame_counter;
|
|
+ Http2FrequencyCounter _received_continuation_frame_counter;
|
|
|
|
// NOTE: Id of stream which MUST receive CONTINUATION frame.
|
|
// - [RFC 7540] 6.2 HEADERS
|