HttpHardening

Struct HttpHardening 

Source
pub struct HttpHardening {
    pub http1_max_headers: usize,
    pub http1_max_buf_size: usize,
    pub http1_header_read_timeout: Duration,
    pub h2_max_concurrent_streams: u32,
    pub h2_initial_stream_window: u32,
    pub h2_initial_connection_window: u32,
    pub h2_max_send_buf_size: usize,
    pub request_body_gap: Option<Duration>,
}
Expand description

Resolved hardening configuration (see the module docs for the knob table, defaults, and the attack each bound addresses).

Fields§

§http1_max_headers: usize

HTTP/1 max header count per request/section.

§http1_max_buf_size: usize

HTTP/1 read-buffer cap, in BYTES.

§http1_header_read_timeout: Duration

HTTP/1 header-read (slowloris) timeout.

§h2_max_concurrent_streams: u32

HTTP/2 max concurrent streams (enforced and advertised).

§h2_initial_stream_window: u32

HTTP/2 initial per-stream flow-control window, in BYTES.

§h2_initial_connection_window: u32

HTTP/2 initial connection flow-control window, in BYTES.

§h2_max_send_buf_size: usize

HTTP/2 per-connection send-buffer cap, in BYTES.

§request_body_gap: Option<Duration>

Inbound request-body inactivity gap; None disables the wrapper (the body then streams through untouched).

Implementations§

Source§

impl HttpHardening

Source

pub fn from_env() -> Self

Read the knob set from the environment; invalid or absent values fall back to the documented defaults.

Source

pub fn apply<E>(&self, builder: &mut Builder<E>)

Apply the connection-level bounds to a hyper-util auto builder (h1 + h2). Used by every serving surface: data-plane listeners and the admin listener share one hardening posture.

Source

pub fn apply_listener_h2<E>( &self, builder: &mut Builder<E>, config: &Http2ListenerConfig, )

Apply per-listener HTTP/2 overrides (PERF-11, #244). Called after apply to override the process-wide h2 defaults with listener-specific values. Only the fields present in the config are overridden; absent fields keep the process default.

Source

pub fn wrap_request_body<B>(&self, body: B) -> InboundBody<B>
where B: Body<Data = Bytes>, B::Error: Into<Box<dyn Error + Send + Sync>>,

Wrap an inbound request body with the inactivity-gap timeout. A thin passthrough when the knob is disabled.

Source

pub async fn guard_connection<S>(&self, stream: S) -> Option<PrefixedStream<S>>
where S: AsyncRead + AsyncWrite + Unpin,

Pre-parse smuggling guard for one connection (DW-023). Reads ahead just enough of the first request head to apply the CL+TE rejection policy BEFORE hyper normalizes the head away (hyper’s HTTP/1 parser gives Transfer-Encoding precedence and DROPS the Content-Length header, which is desync-safe behind this gateway but erases the evidence an explicit rejection needs). Returns the stream to hand to the connection builder (with the sniffed bytes replayed in front), or None when the connection was rejected and answered.

Behavior:

  • Bytes beginning with PRI (the h2c preface) pass through untouched the moment the first bytes identify it — h2 has its own framing rules (Transfer-Encoding is forbidden there; hyper rejects it) and needs no h1 head sniff.
  • A first HTTP/1 head carrying BOTH a Content-Length and a Transfer-Encoding header (any order) is answered with a bare 400 Bad Request + close and never reaches the dataplane.
  • A head containing an obs-fold (RFC 7230 3.2.4 obsolete line folding: any header line starting with SP/HTAB) is likewise answered 400 + close. Folding can split a header NAME across lines (Transfer-\r\n Encoding: chunked), which the name-anchored CL+TE scan below cannot see — and obs-fold is illegal in HTTP/1.1 requests, which hyper also rejects, so refusing it at the sniff is strictly aligned with the parser, one layer earlier.
  • The head terminator is the FIRST blank line under either line-ending convention hyper tolerates (\r\n\r\n for RFC-strict clients, \n\n and the mixed forms for bare-LF clients): a legal LF-only client’s body must not be over-buffered into the sniff (spurious 431).
  • A head exceeding the HTTP/1 read-buffer cap is likewise refused.
  • The sniff’s read bound is per-read (http1_header_read_timeout applied to each individual read, see the module docs): a slow starter simply falls through to hyper, whose per-head slowloris timeout governs from there.
  • Documented limitation: only the FIRST request head on a connection is inspected; later keep-alive requests rely on hyper’s framing itself, which cannot desync behind this gateway (every forwarded request is rebuilt from parsed parts — there is no raw-passthrough path).

Trait Implementations§

Source§

impl Clone for HttpHardening

Source§

fn clone(&self) -> HttpHardening

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for HttpHardening

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for HttpHardening

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl PartialEq for HttpHardening

Source§

fn eq(&self, other: &HttpHardening) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for HttpHardening

Source§

impl StructuralPartialEq for HttpHardening

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> AnyExt for T
where T: Any + ?Sized,

§

fn downcast_ref<T>(this: &Self) -> Option<&T>
where T: Any,

Attempts to downcast this to T behind reference
§

fn downcast_mut<T>(this: &mut Self) -> Option<&mut T>
where T: Any,

Attempts to downcast this to T behind mutable reference
§

fn downcast_rc<T>(this: Rc<Self>) -> Result<Rc<T>, Rc<Self>>
where T: Any,

Attempts to downcast this to T behind Rc pointer
§

fn downcast_arc<T>(this: Arc<Self>) -> Result<Arc<T>, Arc<Self>>
where T: Any,

Attempts to downcast this to T behind Arc pointer
§

fn downcast_box<T>(this: Box<Self>) -> Result<Box<T>, Box<Self>>
where T: Any,

Attempts to downcast this to T behind Box pointer
§

fn downcast_move<T>(this: Self) -> Option<T>
where T: Any, Self: Sized,

Attempts to downcast owned Self to T, useful only in generic context as a workaround for specialization
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<T, X> CoerceTo<T> for X
where T: CoerceFrom<X> + ?Sized,

§

fn coerce_rc_to(self: Rc<X>) -> Rc<T>

§

fn coerce_box_to(self: Box<X>) -> Box<T>

§

fn coerce_ref_to(&self) -> &T

§

fn coerce_mut_to(&mut self) -> &mut T

Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T> ServiceExt for T

§

fn map_response_body<F>(self, f: F) -> MapResponseBody<Self, F>
where Self: Sized,

Apply a transformation to the response body. Read more
§

fn trace_for_http(self) -> Trace<Self, SharedClassifier<ServerErrorsAsFailures>>
where Self: Sized,

High level tracing that classifies responses using HTTP status codes. Read more
§

fn trace_for_grpc(self) -> Trace<Self, SharedClassifier<GrpcErrorsAsFailures>>
where Self: Sized,

High level tracing that classifies responses using gRPC headers. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,