Expand description
Distributed state for Light WAF over Redis.
One RedisStore (one connection pool) provides:
- cluster-wide rate limiting — an implementation of the core’s
waf_core::StateStoretrait, injected withProxy::builder(&cfg).state_store(..)without forking the core; - IP reputation — the
ReputationStore(read) andReputationWriter(write) traits, used bywaf-threatintel; - a shared certificate store —
SharedCertStore+DistributedLock, used bywaf-tls-managedso one node issues an ACME certificate and every node serves it (the private key encrypted at rest withCertCipher, AES-256-GCM).
Behavior:
- Atomic refill-then-consume in a single server-side Lua script, so two nodes can never both
allow from the same bucket. Time comes from Redis
TIME; memory is bounded by per-key TTL. - Fail-open at runtime by default (
RedisStoreOptions::fail_open): a down rate limiter must not block legitimate traffic. An unreachable Redis at boot is always an error (RedisStore::connectpings), so the store never silently degrades to single-node. - NOSCRIPT recovery (
EVALSHAfalls back toEVALwhen the script cache was flushed). - No worker starvation: the blocking pooled call runs inside
block_in_placeon a multi-threaded runtime.
Structs§
- Cert
Cipher - AES-256-GCM authenticated encryption for the stored private key. The key is derived from the operator secret via HKDF-SHA256; a fresh random 96-bit nonce is generated per encryption and prepended to the ciphertext. Storing the derived key (not the passphrase) keeps the passphrase out of memory after construction.
- Decrypt
Error - Decryption failed (wrong key, or tampered / truncated ciphertext).
- Redis
Store - A distributed token-bucket
StateStoreover Redis. The same pool also backsReputationStoreand (when aCertCipheris attached)SharedCertStore. - Redis
Store Options - Tunables for
RedisStore(wired from[enterprise]in the config file). Defaults: a pool ofDEFAULT_POOL_SIZEand fail-open on runtime Redis errors (a down limiter must not block legitimate traffic). - Shared
Cert - A managed TLS certificate as the driver sees it: the issued chain, OUR private key, and the
cert’s expiry.
key_pemis the PLAINTEXT key — the type deliberately does NOT deriveSerialize, so it can never be persisted in the clear by accident (the on-wireStoredBlobcarries the encrypted key instead).
Enums§
- Connect
Error - Why constructing a
RedisStorefailed (boot-time only; runtime errors fail-open). - Reputation
- Reputation verdict for an IP.
Unknown= no opinion (also the fail-safe on any error).
Traits§
- Distributed
Lock - A minimal distributed lock (acquire / release) for cluster-wide single-writer coordination,
separate from the cert issuance lock (its own
feed_lock:namespace). The threat-intel feed uses it so exactly ONE node fetches + writes the reputation snapshot per cycle (avoids N× external fetches of a possibly-metered subscription). Unlike the cert lock there is no heartbeat/extend (F4): the feed cycle is short, and if the leader dies the next cycle another node simply acquires — liveness is covered by the entries’ TTL, not by holding the lock. - Reputation
Store - Read-only cluster-wide IP-reputation lookup — the enterprise injection seam a premium
reputation module consumes (the analogue of
StateStore, but enterprise-side). - Reputation
Writer - Write side of cluster-wide IP-reputation — the seam the threat-intel feed (§6) consumes to
populate the same
rep:<ip>keyspace theReputationStorereads. Deliberately a separate trait from the read: the datapath never writes, and keeping it here (next torep_keyandReputation::as_wire) means the key + value encoding live in ONE crate, shared by both sides. - Shared
Cert Store - Cluster-wide TLS cert storage + single-writer issuance lock — the enterprise injection seam
the DNS-01 driver consumes (the cert analogue of
StateStore).keyis the caller’s logical identifier (the sorted-domain-set hash); the store owns the Redis keyspace derived from it.