Skip to main content

Module ip_gate

Module ip_gate 

Source
Expand description

The global IP gate: whitelist, blacklist, and exempt_ips.

This is the Rust family’s minimal port of the reference engine’s global IP stage (guard-core check_ip_access, frozen by the ecosystem exempt_ips contract). One call, IpGateConfig::evaluate, decides a request IP:

if a whitelist is configured and the IP is not on it:  deny (not in whitelist)
otherwise, if the IP is on the blacklist:              deny (blacklisted)
allowed: is_whitelisted = matched the whitelist
         is_exempt     = matched exempt_ips

§The exempt_ips contract

exempt_ips is the skip-list for known-friendly automation (monitoring probes, VPN egress, a partner’s server). A match sets the same skip state a whitelist match sets (IpGateDecision::is_exempt), but it carries no deny path of its own: exemption can never open the whitelist gate, and an exempt IP on the blacklist is still denied. whitelist keeps its allowlist semantics untouched: when it is non-empty, every unlisted IP is denied exactly as before, exemption included.

Matching semantics are identical for all three lists: an entry is a bare IP or a CIDR range (host bits are cleared at parse time, so 1.2.3.4/24 and 1.2.3.0/24 are the same network), an IPv4-mapped request address (::ffff:203.0.113.7) matches its IPv4 canonical form, and families never cross (an IPv4 entry never matches an unrelated IPv6 address).

Invalid entries are config errors: IpGateConfig::new fails closed, so an adapter that builds its gate at startup never serves with a broken list.

§Example

use std::net::IpAddr;
use std::str::FromStr;

use guard_core_engine::ip_gate::{IpGateConfig, IpGateVerdict};

let gate = IpGateConfig::new(
    [] as [&str; 0],
    ["203.0.113.9"],
    ["198.51.100.7", "198.51.100.16/28"],
)
.expect("valid lists");

// An exempt IP passes with the skip flag set.
let exempt = gate.evaluate(IpAddr::from_str("198.51.100.7").unwrap());
assert!(matches!(exempt, IpGateVerdict::Allowed(decision) if decision.is_exempt));

// A CIDR entry matches the whole range, the flag carried along.
let in_range = gate.evaluate(IpAddr::from_str("198.51.100.20").unwrap());
assert!(matches!(in_range, IpGateVerdict::Allowed(decision) if decision.is_exempt));

// The blacklist wins over exemption: no deny path is added, but none is
// removed either.
assert_eq!(
    gate.evaluate(IpAddr::from_str("203.0.113.9").unwrap()),
    IpGateVerdict::Denied(guard_core_engine::ip_gate::IpGateDenial::Blacklisted)
);

// Everyone else passes unimpeded: an empty whitelist denies nobody.
let other = gate.evaluate(IpAddr::from_str("192.0.2.1").unwrap());
assert!(matches!(other, IpGateVerdict::Allowed(decision) if !decision.is_exempt));

Structs§

IpGateConfig
The global IP gate: the parsed whitelist, blacklist, and exempt_ips lists.
IpGateDecision
The skip state a request carries after it passed the global IP gate.
IpGateError
An invalid list entry: the config error IpGateConfig::new fails with.
RouteAccess
The combined route verdict of RouteIpGate::evaluate_access: the reference check_route_ip_access result plus the skip flag the reference derives from the route’s country verdict.
RouteIpGate
The route-level IP gate: a route decorator’s ip_whitelist and ip_blacklist (RouteConfig.ip_whitelist / .ip_blacklist).

Enums§

IpGateDenial
Why the global IP gate denied a request.
IpGateVerdict
The outcome of the global IP gate for one request IP.
RouteIpVerdict
The outcome of the route-level IP gate for one request IP (check_route_ip_access’s tri-state, the country arms aside; see RouteIpGate::evaluate_access for the combined verdict).