connectban: never flood-ban loopback (127.0.0.1/::1) and add a connectban_exempt glob/cidr list

This commit is contained in:
Jean Chevronnet 2026-08-15 23:25:16 +00:00
parent 59b0439b79
commit 7d57e4ed34
3 changed files with 19 additions and 0 deletions

View file

@ -67,12 +67,25 @@ fn range_of(ip: IpAddr, v4cidr: u8, v6cidr: u8) -> (String, String) {
}
}
/// Whether `ip` matches a configured `connectban_exempt` glob/CIDR (repeatable).
fn connectban_exempt(s: &Server, ip: IpAddr) -> bool {
let ipstr = ip.to_string();
s.conf_all("connectban_exempt")
.iter()
.any(|m| crate::modules::connclass::ip_matches(m, &ipstr))
}
/// Record a new connection from `ip`, z-lining its range if it crosses the limit.
/// No-op when connectban is disabled or still inside the boot-grace window.
pub fn on_connect(s: &mut Server, ip: IpAddr) {
if !s.conf_bool("connectban", false) {
return;
}
// never connect-ban loopback (local services, bridges, admin tooling all dial in
// over 127.0.0.1 / ::1) or an admin-configured exempt range
if ip.is_loopback() || connectban_exempt(s, ip) {
return;
}
let threshold = s.conf_num("connectban_threshold", 10u32).max(2);
let v4 = s.conf_num("connectban_ipv4cidr", 32u8).clamp(1, 32);
let v6 = s.conf_num("connectban_ipv6cidr", 128u8).clamp(1, 128);

View file

@ -24,6 +24,10 @@ fn cfg(s: &Server) -> Option<(u32, u64)> {
/// Record a connection from `ip`; returns true when it exceeds the limit (the
/// caller should refuse it). No-op → false when connflood is unconfigured.
pub fn over_limit(s: &mut Server, ip: IpAddr) -> bool {
// loopback (local services / bridges / admin) is never connection-throttled
if ip.is_loopback() {
return false;
}
let Some((max, secs)) = cfg(s) else {
return false;
};