Skip to main content

IpBanManager

Struct IpBanManager 

Source
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

Source

pub fn new() -> Self

Build a ban store with no trusted proxies (loopback refusal only).

Source

pub fn with_trusted_proxies<I>(entries: I) -> Result<Self, IpGateError>
where I: IntoIterator, I::Item: AsRef<str>,

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.

Source

pub fn with_trusted_proxies_and_clock<I>( entries: I, clock: Clock, ) -> Result<Self, IpGateError>
where I: IntoIterator, I::Item: AsRef<str>,

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.

Source

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.

Source

pub fn with_clock(clock: Clock) -> Self

Source

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.

Source

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.

Source

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.

Source

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).

Source

pub fn unban(&self, ip: IpAddr)

Lift ip’s ban, live or expired (unban in the references).

Source

pub fn reset(&self)

Drop every ban and every violation count (reset in the references; test harnesses use it to isolate cases).

Source

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

Source

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

Source§

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)

Performs copy-assignment from source. Read more
Source§

impl Debug for IpBanManager

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for IpBanManager

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.