diff --git a/echoircd.conf.example b/echoircd.conf.example index 342b1b9..071a62f 100644 --- a/echoircd.conf.example +++ b/echoircd.conf.example @@ -32,8 +32,12 @@ oper = admin CHANGE_THIS_PASSWORD cloak_key = CHANGE_THIS_TO_A_LONG_RANDOM_HEX_STRING # reverse-DNS clients on connect (the "*** Looking up your hostname..." notices). -# on (default) shows resolved hostnames; off keeps bare IPs. +# on (default) performs the lookup and reports the result; off skips it (bare IP). resolve_hosts = on +# whether a resolved hostname is used in the hostmask (nick!user@host). on (default) +# shows the domain; off keeps the IP in the mask even though the lookup still runs +# and reports "Found your hostname". Only matters when resolve_hosts = on. +use_resolved_host = on # antimixedutf8 — block spam that mixes look-alike scripts within words. # action = block | kill | gline | kline | zline ; target = both | channel | private diff --git a/src/config.rs b/src/config.rs index e1e864c..ef99a93 100644 --- a/src/config.rs +++ b/src/config.rs @@ -70,6 +70,7 @@ pub struct Config { pub censor: Vec<(String, String)>, // +G bad words: (find, replace); empty replace = block pub amu: AntiMixedCfg, // antimixedutf8 module config pub resolve_hosts: bool, // reverse-DNS clients on connect (default on) + pub use_resolved_host: bool, // put the resolved hostname in the hostmask (default on) } impl Default for Config { @@ -92,6 +93,7 @@ impl Default for Config { censor: Vec::new(), amu: AntiMixedCfg::default(), resolve_hosts: true, + use_resolved_host: true, } } } @@ -193,6 +195,12 @@ impl Config { "off" | "false" | "no" | "0" ) } + "use_resolved_host" | "resolved_hostmask" | "hostmask_dns" => { + c.use_resolved_host = !matches!( + v.to_ascii_lowercase().as_str(), + "off" | "false" | "no" | "0" + ) + } _ => {} } } diff --git a/src/coremods/core_oper.rs b/src/coremods/core_oper.rs index 95acbe4..202b5eb 100644 --- a/src/coremods/core_oper.rs +++ b/src/coremods/core_oper.rs @@ -229,6 +229,8 @@ impl Command for Rehash { s.cloak_key = fresh.cloak_key; s.censor = fresh.censor; s.amu = fresh.amu; + s.resolve_hosts = fresh.resolve_hosts; + s.use_resolved_host = fresh.use_resolved_host; s.numeric(uid, RPL_REHASHING, &format!("{} :Rehashing", s.conf_path)); CmdResult::Ok } diff --git a/src/server.rs b/src/server.rs index 3aeeb22..98ed71c 100644 --- a/src/server.rs +++ b/src/server.rs @@ -98,6 +98,7 @@ pub struct Server { pub censor: Vec<(String, String)>, // +G bad words: (find, replace) pub amu: crate::config::AntiMixedCfg, // antimixedutf8 module config pub resolve_hosts: bool, // reverse-DNS clients on connect + pub use_resolved_host: bool, // apply the resolved name to the hostmask pub event_tx: Sender, // self-inject events (DNS results) } @@ -133,6 +134,7 @@ impl Server { censor: cfg.censor, amu: cfg.amu, resolve_hosts: cfg.resolve_hosts, + use_resolved_host: cfg.use_resolved_host, event_tx, } } @@ -252,9 +254,14 @@ impl Server { "Couldn't look up your hostname; using your IP address instead", ), } + let apply = self.use_resolved_host; if let Some(u) = self.users.get_mut(&uid) { - if let Some(h) = host { - u.host = h; + // `use_resolved_host = off` keeps the IP in the hostmask even though we + // resolved and reported the name above. + if apply { + if let Some(h) = host { + u.host = h; + } } u.dns_pending = false; } @@ -570,6 +577,21 @@ mod tests { Server::new(Config::default(), tx) } + #[test] + fn resolved_host_applied_only_when_configured() { + let mut s = srv(); // use_resolved_host = true (default) + let _a = add_user(&mut s, 1, "ann"); // host starts "localhost" + s.on_resolved(1, Some("host.example.net".to_string())); + assert_eq!(s.users[&1].host, "host.example.net"); + assert!(!s.users[&1].dns_pending); + + s.use_resolved_host = false; // resolve + report, but keep the IP in the mask + let _b = add_user(&mut s, 2, "bob"); + s.on_resolved(2, Some("host.example.net".to_string())); + assert_eq!(s.users[&2].host, "localhost"); + assert!(!s.users[&2].dns_pending); // registration still un-held either way + } + #[test] fn join_broadcasts_and_tracks_membership() { let mut s = srv(); diff --git a/src/users.rs b/src/users.rs index a40331c..0ca5ab3 100644 --- a/src/users.rs +++ b/src/users.rs @@ -197,12 +197,12 @@ pub struct User { pub nick: String, // "" until NICK pub ident: String, // "" until USER pub realname: String, - pub host: String, // displayed host: reverse-DNS name if resolved, else IP - pub cloak: String, // masked host shown under +x ("" until computed) - pub vhost: Option, // displayed-host override (CHGHOST/SETHOST vhost) - pub secure: bool, // connected over TLS (drives WHOIS 671 / sslinfo) + pub host: String, // displayed host: reverse-DNS name if resolved, else IP + pub cloak: String, // masked host shown under +x ("" until computed) + pub vhost: Option, // displayed-host override (CHGHOST/SETHOST vhost) + pub secure: bool, // connected over TLS (drives WHOIS 671 / sslinfo) pub account: Option, // logged-in account name (set by services) - pub signon: u64, // unix secs at registration (WHOIS 317) + pub signon: u64, // unix secs at registration (WHOIS 317) pub addr: SocketAddr, pub registered: bool, pub dns_pending: bool, // holding registration for a reverse-DNS lookup