autodrop: cache the autodrop-command set (config_gen-tagged) instead of re-splitting autodrop_commands on every packet from an unregistered socket — the path runs hottest under the scanner flood it defends against
This commit is contained in:
parent
09b4adabbf
commit
1da913a249
1 changed files with 24 additions and 3 deletions
|
|
@ -7,10 +7,18 @@
|
||||||
//! autodrop_commands = GET POST HEAD CONNECT PUT DELETE OPTIONS TRACE PATCH
|
//! autodrop_commands = GET POST HEAD CONNECT PUT DELETE OPTIONS TRACE PATCH
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
use crate::map::HashSet;
|
||||||
use crate::module::{ModResult, Module};
|
use crate::module::{ModResult, Module};
|
||||||
use crate::server::Server;
|
use crate::server::Server;
|
||||||
use crate::Uid;
|
use crate::Uid;
|
||||||
|
|
||||||
|
/// The autodrop-command set, parsed once and re-parsed only on rehash.
|
||||||
|
#[derive(Default)]
|
||||||
|
struct DropCache {
|
||||||
|
gen: u64,
|
||||||
|
cmds: HashSet<String>, // uppercased
|
||||||
|
}
|
||||||
|
|
||||||
pub struct AutoDrop;
|
pub struct AutoDrop;
|
||||||
|
|
||||||
impl Module for AutoDrop {
|
impl Module for AutoDrop {
|
||||||
|
|
@ -29,10 +37,23 @@ impl Module for AutoDrop {
|
||||||
if s.users.get(&uid).map(|u| u.registered).unwrap_or(true) {
|
if s.users.get(&uid).map(|u| u.registered).unwrap_or(true) {
|
||||||
return ModResult::Passthru;
|
return ModResult::Passthru;
|
||||||
}
|
}
|
||||||
|
// cache the set (config_gen-tagged): this hook runs hottest under the exact
|
||||||
|
// scanner flood it defends against, so don't re-split the config per packet.
|
||||||
|
let gen = s.config_gen;
|
||||||
|
let stale = s.ext.get::<DropCache>().map(|c| c.gen != gen).unwrap_or(true);
|
||||||
|
if stale {
|
||||||
|
let cmds: HashSet<String> = s
|
||||||
|
.conf_all("autodrop_commands")
|
||||||
|
.iter()
|
||||||
|
.flat_map(|line| line.split_whitespace())
|
||||||
|
.map(|w| w.to_ascii_uppercase())
|
||||||
|
.collect();
|
||||||
|
s.ext.set(DropCache { gen, cmds });
|
||||||
|
}
|
||||||
let hit = s
|
let hit = s
|
||||||
.conf_all("autodrop_commands")
|
.ext
|
||||||
.iter()
|
.get::<DropCache>()
|
||||||
.any(|line| line.split_whitespace().any(|w| w.eq_ignore_ascii_case(cmd)));
|
.is_some_and(|c| c.cmds.contains(&cmd.to_ascii_uppercase()));
|
||||||
if hit {
|
if hit {
|
||||||
s.send(uid, "ERROR :Closing link (dropped)".to_string());
|
s.send(uid, "ERROR :Closing link (dropped)".to_string());
|
||||||
s.remove_user(uid, "Autodropped");
|
s.remove_user(uid, "Autodropped");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue