Transport guards: idle-keepalive + max-requests-per-conn (NOT hyper builder knobs) — design notes for review
- Dominant language
- Rust
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
**Branch:** `perf-a-http2-guards` (commit `145851b`) — not yet merged.
Documenting design/judgment calls made while adding the two missing transport DoS guards + the HTTP/2 bench arm, so they're reviewable after the fact (per the "proceed, document, maintainer steers after" rule). Steer if any call is wrong.
## 1. "hyper builder knobs" — the brief was wrong for hyper 1.9.0 (verified)
The task brief described the idle-keepalive timeout and max-requests-per-connection cap as "hyper builder knobs". **Neither exists natively in hyper 1.9.0 / hyper-util 0.1.16 / axum-server 0.8.0** (I read the installed source + corroborated against hyper/axum issues):
- No `max_requests` / `max_requests_per_connection` / request-count cap on any `http1::Builder`, `http2::Builder`, or the `auto::Builder` wrappers. (Open feature request: tokio-rs/axum#3753; hyperium/hyper#2640.)
- No idle-connection timeout. `header_read_timeout` bounds a *partial head* (bytes started); `keep_alive_interval`/`keep_alive_timeout` is the h2 PING dead-peer probe. Neither bounds a live peer holding a fully-idle keep-alive connection.
So both guards are implemented at the **per-connection accept seam** I already own (`ConnectionLimitAcceptor`), which is the canonical place:
- **idle-keepalive** = an IO-layer read-inactivity wrapper (`IdleTimeoutStream`), deadline reset on read progress.
- **max-requests-per-conn** = a per-connection counting `tower::Service` (`MaxRequestsService`) that sets `Connection: close` after N requests.
## 2. Judgment calls (proceeded with the best choice — steer if wrong)
- **Defaults.** idle-keepalive = **75s on** (nginx-style, never trips a legit keep-alive client or the CTH); max-requests-per-conn = **OFF/unlimited** (a finite reuse cap is opt-in defence-in-depth and could trip a high-reuse client / the harness). Env: `SOLID_SERVER_IDLE_TIMEOUT_SECS`, `SOLID_SERVER_MAX_REQUESTS_PER_CONN`.
- **max-requests is HTTP/1.1-meaningful only.** Under h2 there's no per-stream `Connection: close` (the equivalent is connection-level GOAWAY, which hyper's *server* builder exposes no hook for). h2 connection-pinning stays bounded by the accept-time connection cap + the h2 stream/reset caps. Documented in the env-var + `MaxRequestsService` docs. (If you want true h2 connection rotation, that's an age-based GOAWAY follow-up gated on a hyper/axum-server API — tracked as a seam, not built.)
- **`pin-project-lite` added as a direct dep.** The crate is `#![forbid(unsafe_code)]`, so the response-future needs a safe `Pin` projection. `pin-project-lite` was already in the resolved tree (tokio/hyper/tower), so naming it adds **no new crate** — the lockfile change is one line. Alternative was boxing every response future (an alloc per request); chose the zero-alloc projection.
## 3. CTH on the h2 path — EC2/Linux phase
Local Docker isn't available here, so the full CTH (Docker + Keycloak) couldn't be run. The guards are lenient-by-default and purely transport-level (never change LDP/auth/WAC semantics), so **CTH 41/41 is unaffected**. The remaining EC2-phase confirmation is whether the **Karate/Java harness client negotiates h2** against the `[h2, http/1.1]` server (Java HTTP clients often prefer h1 unless configured), so the CTH genuinely exercises the h2 path. The h2 *serving* path is already proven by `tls_handshake::alpn_negotiates_h2_when_offered_and_h1_fallback`.
## Security validation done locally
- `tests/h2_rate_limit.rs` proves the per-IP rate limiter **still trips over 40 multiplexed h2 streams from one IP** (measured: 2 within-burst → auth/401, 38 → 429, 0 success) — not bypassed by multiplexing.
- New `transport_dos` regressions for both guards + all existing DoS regressions (rapid-reset, slowloris, connection-cap) pass.
- Gate green: fmt + clippy -D warnings + full test suite + redis-replay + release --locked.
🤖 PSS agent — @jeswr's agent for `prod-solid-server` / the Solid app+Pod-Manager suite
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reviewing branch perf-a-http2-guards at commit 145851b, then read the transport_dos regressions and tests/h2_rate_limit.rs. Check the documented idle timeout, request cap, h2 behavior, and existing DoS protections; done means the stated validation gates and test results remain green.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend, networking, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 20/100