Architecture
One engine, several entry points. The protection logic lives in the
engine crate, which decides a verdict for a connection or a request and
does no I/O. The proxy and the binary are thin wrappers that feed it and
carry out what it decides.
Request path
client
|
v
listener TCP or TLS (ALPN h2, http/1.1), bounded handshakes
|
v
identity peer address, or X-Forwarded-For from a trusted proxy
|
v
rate limit token bucket per client -> 429 + Retry-After
|
v
detection heavy hitters, baseline, entropy -> observe: log only
| enforce: 403, slower buckets
v
proxy HTTP/1.1, HTTP/2 (h2c or ALPN) or a WebSocket tunnel
|
v
upstream
Local errors on a gRPC request come back gRPC-shaped (HTTP 200 with
grpc-status), so clients see a status code instead of a broken stream.
Crates
| Crate | Role |
|---|---|
engine |
Verdicts, token buckets, detection sketches. No I/O, no async runtime, so it can embed anywhere |
l7 |
tower layers that run the engine on each request |
proxy |
Server loop, TLS, HTTP/2 limits, upstream client, WebSocket tunnels |
dvarapala |
The binary: config, metrics endpoint, signals |
Dependencies point inward: the binary depends on the rest, engine on no
other workspace crate. More crates (l4, store, xdp, ffi) arrive
with the RFC that needs them.
Modes
| Mode | Entry point | Status |
|---|---|---|
| Reverse proxy | dvarapala serve --config <file> |
shipped |
| Forward proxy | egress rate shaping toward third-party APIs | RFC 0007, draft |
| Embedded (Rust) | tower::Layer and a listener wrapper |
planned |
| Embedded (other) | C ABI for Go, Python, Node | planned |
Failure policy
The protection path fails closed: when a limit cannot be decided, the request does not pass. It fails open only where an RFC says so, and logs it. Shutdown drains in-flight requests and open tunnels for up to 30 s.
Stack
Rust for a small footprint without a GC and memory safety at the trust
boundary: tokio, hyper, tower, rustls, and metrics with the
Prometheus exporter. The idle binary has an RSS budget that CI checks on
every change.