From d7680e30e48926a5a3f94a0986d39181d5ab2218 Mon Sep 17 00:00:00 2001 From: Noah Kennedy Date: Fri, 19 Jan 2024 12:16:42 -0600 Subject: [PATCH] feat(http2): add config for `max_local_error_reset_streams` in server (#3530) This change exposes a tunable for the max_local_error_reset_streams parameter in h2. --- Cargo.toml | 2 +- src/proto/h2/server.rs | 4 ++++ src/server/conn/http2.rs | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f722042e84..23ff17b63a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ tokio = { version = "1", features = ["sync"] } futures-channel = { version = "0.3", optional = true } futures-util = { version = "0.3", default-features = false, optional = true } -h2 = { version = "0.4", optional = true } +h2 = { version = "0.4.2", optional = true } http-body-util = { version = "0.1", optional = true } httparse = { version = "1.8", optional = true } httpdate = { version = "1.0", optional = true } diff --git a/src/proto/h2/server.rs b/src/proto/h2/server.rs index 2810f0f6c5..affda68987 100644 --- a/src/proto/h2/server.rs +++ b/src/proto/h2/server.rs @@ -41,6 +41,7 @@ const DEFAULT_MAX_FRAME_SIZE: u32 = 1024 * 16; // 16kb const DEFAULT_MAX_SEND_BUF_SIZE: usize = 1024 * 400; // 400kb // 16 MB "sane default" taken from golang http2 const DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE: u32 = 16 << 20; +const DEFAULT_MAX_LOCAL_ERROR_RESET_STREAMS: usize = 1024; #[derive(Clone, Debug)] pub(crate) struct Config { @@ -51,6 +52,7 @@ pub(crate) struct Config { pub(crate) enable_connect_protocol: bool, pub(crate) max_concurrent_streams: Option, pub(crate) max_pending_accept_reset_streams: Option, + pub(crate) max_local_error_reset_streams: Option, pub(crate) keep_alive_interval: Option, pub(crate) keep_alive_timeout: Duration, pub(crate) max_send_buffer_size: usize, @@ -67,6 +69,7 @@ impl Default for Config { enable_connect_protocol: false, max_concurrent_streams: Some(200), max_pending_accept_reset_streams: None, + max_local_error_reset_streams: Some(DEFAULT_MAX_LOCAL_ERROR_RESET_STREAMS), keep_alive_interval: None, keep_alive_timeout: Duration::from_secs(20), max_send_buffer_size: DEFAULT_MAX_SEND_BUF_SIZE, @@ -130,6 +133,7 @@ where .initial_connection_window_size(config.initial_conn_window_size) .max_frame_size(config.max_frame_size) .max_header_list_size(config.max_header_list_size) + .max_local_error_reset_streams(config.max_pending_accept_reset_streams) .max_send_buffer_size(config.max_send_buffer_size); if let Some(max) = config.max_concurrent_streams { builder.max_concurrent_streams(max); diff --git a/src/server/conn/http2.rs b/src/server/conn/http2.rs index 94e8462739..45eca4872c 100644 --- a/src/server/conn/http2.rs +++ b/src/server/conn/http2.rs @@ -132,6 +132,21 @@ impl Builder { self } + /// Configures the maximum number of local reset streams allowed before a GOAWAY will be sent. + /// + /// If not set, hyper will use a default, currently of 1024. + /// + /// If `None` is supplied, hyper will not apply any limit. + /// This is not advised, as it can potentially expose servers to DOS vulnerabilities. + /// + /// See for more information. + #[cfg(feature = "http2")] + #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] + pub fn max_local_error_reset_streams(mut self, max: impl Into>) -> Self { + self.h2_builder.max_local_error_reset_streams = max.into(); + self + } + /// Sets the [`SETTINGS_INITIAL_WINDOW_SIZE`][spec] option for HTTP2 /// stream-level flow control. ///