5.4 KiB
Hostile-input and overload protection
Tracking: #15
Rendezvous treats every public HTTP request and UDP datagram as hostile. The server applies bounded fixed-window request budgets and concurrency ceilings in two stages so malformed input is discarded before expensive work while valid traffic is also isolated by its authenticated scope.
Enforcement order
- Kestrel and the HTTP abuse middleware cap request bodies at 16 KiB. A known
oversized body receives a typed
413response before endpoint dispatch. - Every HTTP request consumes global, source-prefix, and operation budgets and
acquires the corresponding concurrency leases. IPv4 sources share a
/24budget and IPv6 sources share a/56budget; raw addresses are not retained. Non-lease operations also consume a smaller optional-work budget, leaving a configured global and source-prefix reserve for renew, update, and delete operations during shedding. Health probes use their own source-prefix budget so public API overload cannot make a healthy instance fail its orchestrator probes, while health traffic is still bounded. - Once an endpoint has safely derived identities, it also acquires applicable tenant, principal or capability, and listing/attempt budgets. Secret capabilities are represented only by bounded SHA-256 fingerprints.
- Every UDP envelope consumes global, source-prefix, and wire-operation budgets before decoding. A structurally and cryptographically valid request then consumes capability, role, and mediation-handle budgets before state mutation or introduction.
- HTTP overload returns the stable
RateLimitederror, status429, and a boundedRetry-Aftervalue in both the header and response contract. UDP overload and every invalid UDP input are silently dropped.
The same HTTP identity budget is computed whether or not a listing or attempt exists. Rejection therefore does not disclose resource existence. Publisher authentication also completes before any tenant/resource operation, while the pre-authentication source budget prevents invalid credentials from bypassing load shedding.
Bounded state and recovery
Rendezvous:AbuseProtection:MaxTrackedKeys is a hard combined ceiling for rate
and active-concurrency keys. General HTTP and UDP traffic cannot consume the
configured CriticalTrackedKeyReserve; lease operations and health probes may
use that reserve but never exceed the hard ceiling. A request that would exceed
its applicable ceiling fails closed without adding state. Fixed-window rate keys
are cleared at the next window boundary; concurrency keys are removed as their
request leases finish. HTTP and UDP trackers have separate locks and cardinality
partitions, so a UDP flood cannot block HTTP admission on a shared lock or
consume HTTP key capacity. This gives
deterministic burst recovery and prevents an attacker from growing a permanent
high-cardinality address, credential, or resource table.
The complete default profile is checked into
src/FinalFactory.Rendezvous.Server/appsettings.json. Operators may lower or
tune limits for a measured deployment profile, but must preserve all dimensions
and leave the tracker ceiling above the maximum simultaneous key set. A rolling
deployment should use the same profile on every instance. These per-process
limits are a final service boundary; an edge proxy may add stricter distributed
limits but is not a substitute for them.
When an HTTP reverse proxy is used, every immediate proxy address must be
allowlisted in Rendezvous:AbuseProtection:TrustedProxyAddresses (or indexed
environment variables such as
Rendezvous__AbuseProtection__TrustedProxyAddresses__0). Only one forwarded
hop is accepted. With an empty allowlist, forwarded headers are ignored and the
direct TCP peer is the source. Never add a broad network range or accept
untrusted X-Forwarded-For input: that would let a caller choose its own rate
partition.
Reflection, disclosure, and logging rules
- UDP sends nothing for malformed, oversized, unauthenticated, stale, replayed, wrong-role, or rate-limited input.
- Introductions are emitted only after both role-scoped capabilities bind to their observed gameplay-socket sources. HTTP never supplies a public introduction target.
- Private candidates must be same-family private unicast addresses and are used only for peers observed behind the same public address.
- Abuse keys, exceptions, and responses never include bearer credentials, capabilities, tickets, raw endpoints, metadata values, or hostile markup.
- Endpoint and capability values are not used as metric labels or log fields.
Verification
The deterministic test corpora use the recorded seeds 0x152026, 0x154A50,
and 0x1557A7E. They exercise 10,000 arbitrary UDP envelopes through the
production decoder, 5,000 arbitrary HTTP/credential parser inputs, and 1,000
mutated state transitions, including the oversized and configured-capacity
boundaries.
Focused tests cover IPv4 and IPv6 prefix
partitioning, tenant/principal/resource concurrency, tracker exhaustion,
window recovery, wire-operation isolation, a steady-state allocation ceiling,
typed 429/413 responses, secret fingerprint redaction, and silent
authenticated UDP shedding. The existing state, contract, HTTP, client,
and mediator suites continue to cover cross-tenant access, replay, role swaps,
credential rotation, bounded metadata, endpoint validation, and one-shot
amplification behavior.