pub struct IpBanManager { /* private fields */ }Expand description
The dynamic IP ban store over one shared in-memory map.
Build it once at startup and share the handle across requests; the
internal store is a mutex-guarded LRU, safe for concurrent services.
Trusted proxies are configured at construction
(IpBanManager::with_trusted_proxies) because they shape the
self-ban refusal, not per-request behavior.
Implementations§
Source§impl IpBanManager
impl IpBanManager
Sourcepub fn with_trusted_proxies<I>(entries: I) -> Result<Self, IpGateError>
pub fn with_trusted_proxies<I>(entries: I) -> Result<Self, IpGateError>
Build a ban store whose self-ban refusal also covers the given trusted proxy networks (a bare IP or a CIDR range per entry, same matching semantics as the IP gate’s lists).
§Errors
IpGateError naming the offending entry, exactly like
IpGateConfig::new fails closed.
Sourcepub fn with_trusted_proxies_and_clock<I>(
entries: I,
clock: Clock,
) -> Result<Self, IpGateError>
pub fn with_trusted_proxies_and_clock<I>( entries: I, clock: Clock, ) -> Result<Self, IpGateError>
Build a ban store whose self-ban refusal also covers the given
trusted-proxy networks and whose wall clock is injected: the combined
seam with_trusted_proxies and
with_clock cover separately. Adapters that run
deterministic expiry tests under a production-shaped proxy list use
this one.
§Errors
IpGateError naming the offending entry, exactly like
IpBanManager::with_trusted_proxies fails closed.
Sourcepub fn with_distributed_store(
self,
store: Arc<dyn BanStore>,
redis_prefix: &str,
) -> Self
pub fn with_distributed_store( self, store: Arc<dyn BanStore>, redis_prefix: &str, ) -> Self
Swap the wall clock. Test seam: production builds use the system
clock; deterministic expiry coverage injects a fake.
Run the ban engine over a distributed store (the reference
redis_handler seam): ban writes go to
{prefix}banned_ips:{ip} with the ban TTL (a failed write
degrades to the local store, the reference except branch), and
lookups fall through to the store on a local miss, caching the
answer (the reference _check_redis_exact). A failing lookup
surfaces the backend error through IpBanManager::try_is_banned
so a caller can fail secure the way the reference’s
GuardRedisError(503) propagates into the pipeline; the lossy
IpBanManager::is_banned keeps reading an error as unbanned.
pub fn with_clock(clock: Clock) -> Self
Sourcepub fn ban_ip(
&self,
ip: IpAddr,
duration: u64,
reason: &str,
) -> Result<bool, BanError>
pub fn ban_ip( &self, ip: IpAddr, duration: u64, reason: &str, ) -> Result<bool, BanError>
Ban ip for duration seconds, recording reason.
Returns Ok(true) when the ban was recorded, Ok(false) when it
was refused by the self-DoS guard (loopback or a trusted proxy:
banning those would take the deployment’s own view of client IPs
offline), and BanError::NonPositiveDuration for a zero duration.
Re-banning a live IP overwrites the record: the new expiry and
reason replace the old ones.
Durations beyond LOCAL_CACHE_TTL_CAP_SECONDS are clamped to it:
this is the in-memory store, and the references cap their local
store the same way (only the Redis backend honors longer bans).
§Errors
BanError::NonPositiveDuration when duration is zero.
Sourcepub fn is_banned(&self, ip: IpAddr) -> bool
pub fn is_banned(&self, ip: IpAddr) -> bool
Whether ip currently carries a live ban. An entry past its expiry
reads as unbanned and is dropped from the store.
This is the lossy form: a failing distributed lookup reads as
unbanned. Fail-secure callers use IpBanManager::try_is_banned,
which surfaces the backend error the way the reference’s
GuardRedisError(503) propagates into its pipeline.
Sourcepub fn try_is_banned(&self, ip: IpAddr) -> Result<bool, StoreError>
pub fn try_is_banned(&self, ip: IpAddr) -> Result<bool, StoreError>
IpBanManager::is_banned with the backend error surfaced: a
failing distributed ban lookup returns Err instead of reading
as unbanned, so a caller can fail secure (the reference
redis_handler.safe_operation raising GuardRedisError(503, "Redis operation failed") out of _check_redis_exact’s get_key).
§Errors
crate::distributed::StoreError when the distributed lookup
fails and the local cache holds no live answer.
Sourcepub fn ban_record(&self, ip: IpAddr) -> Option<BanRecord>
pub fn ban_record(&self, ip: IpAddr) -> Option<BanRecord>
The recorded ban for ip, if one is still live (test and
observability seam: the reason a ban was issued).
Sourcepub fn reset(&self)
pub fn reset(&self)
Drop every ban and every violation count (reset in the
references; test harnesses use it to isolate cases).
Sourcepub fn banned_count(&self) -> usize
pub fn banned_count(&self) -> usize
How many bans the store currently holds, live or expired (test and observability seam for the LRU cap).
Source§impl IpBanManager
impl IpBanManager
Sourcepub fn register_violations(
&self,
counters: &ViolationCounters,
ip: IpAddr,
categories: &[&str],
config: &IpBanConfig,
reason: &str,
) -> Option<ResolvedBan>
pub fn register_violations( &self, counters: &ViolationCounters, ip: IpAddr, categories: &[&str], config: &IpBanConfig, reason: &str, ) -> Option<ResolvedBan>
The auto-ban engine’s one-call shape: record the categories for
ip, resolve the thresholds, and apply the ban when one crossed.
Some(..) means a ban now stands (the stage answers with the
family’s banned shape), None means nothing fired - banning
disabled, no threshold crossed, or the self-DoS guard refusing the
target. Violations are counted regardless of the banning switch,
mirroring the reference: enabling banning later starts from observed
history.
Trait Implementations§
Source§impl Clone for IpBanManager
impl Clone for IpBanManager
Source§fn clone(&self) -> Self
fn clone(&self) -> Self
A clone shares the ban store and the clock, exactly the references’ singleton semantics: bans recorded through any handle are visible to every handle. Trusted proxies are copied (they shape the self-DoS refusal only).
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more