diff --git a/src/config/mod.rs b/src/config/mod.rs index fbf7b0b6..72717763 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -147,6 +147,11 @@ pub struct Config { /// force-AAAA-SOA [yes|no] pub force_aaaa_soa: Option, + /// force HTTPS query return SOA + /// + /// force-HTTPS-SOA [yes|no] + pub force_https_soa: Option, + /// force specific qtype return soa /// /// force-qtype-SOA [qtypeid |...] diff --git a/src/config/parser/listener.rs b/src/config/parser/listener.rs index 69ab724c..fb7c7c1e 100644 --- a/src/config/parser/listener.rs +++ b/src/config/parser/listener.rs @@ -194,6 +194,7 @@ pub fn parse_server_opts<'b>(options: &Options<'b>) -> (Options<'b>, ServerOpts) "no-serve-expired" => opts.no_serve_expired = Some(true), "no-dualstack-selection" => opts.no_dualstack_selection = Some(true), "force-aaaa-soa" => opts.force_aaaa_soa = Some(true), + "force-https-soa" => opts.force_https_soa = Some(true), _ => rest_options.push((*k, *v)), } } @@ -413,6 +414,26 @@ mod tests { } ) ); + + assert_eq!( + TcpListenerConfig::parse( + "bind-tcp [::1]:5353@eth0 -qq --no-rule-addr -w123 -force-https-soa" + ) + .unwrap(), + ( + "", + TcpListenerConfig { + listen: ListenerAddress::V6("::1".parse().unwrap()), + port: 5353, + device: Some("eth0".to_string()), + opts: ServerOpts { + no_rule_addr: Some(true), + force_https_soa: Some(true), + ..Default::default() + } + } + ) + ); } #[test] diff --git a/src/config/parser/mod.rs b/src/config/parser/mod.rs index 540a6c52..572470fa 100644 --- a/src/config/parser/mod.rs +++ b/src/config/parser/mod.rs @@ -107,6 +107,7 @@ pub enum OneConfig { EdnsClientSubnet(IpNet), ExpandPtrFromAddress(bool), ForceAAAASOA(bool), + ForceHTTPSSOA(bool), ForceQtypeSoa(RecordType), ForwardRule(ForwardRule), HostsFile(glob::Pattern), @@ -201,6 +202,7 @@ pub fn parse_config(input: &str) -> IResult<&str, OneConfig> { OneConfig::ExpandPtrFromAddress, ), map(parse_item("force-AAAA-SOA"), OneConfig::ForceAAAASOA), + map(parse_item("force-HTTPS-SOA"), OneConfig::ForceHTTPSSOA), map(parse_item("force-qtype-soa"), OneConfig::ForceQtypeSoa), map(parse_item("response"), OneConfig::ResponseMode), map(parse_item("prefetch-domain"), OneConfig::PrefetchDomain), @@ -214,11 +216,11 @@ pub fn parse_config(input: &str) -> IResult<&str, OneConfig> { map(parse_item("log-file-mode"), OneConfig::LogFileMode), map(parse_item("log-file"), OneConfig::LogFile), map(parse_item("log-filter"), OneConfig::LogFilter), - map(parse_item("log-level"), OneConfig::LogLevel), - map(parse_item("log-num"), OneConfig::LogNum), )); let group3 = alt(( + map(parse_item("log-level"), OneConfig::LogLevel), + map(parse_item("log-num"), OneConfig::LogNum), map(parse_item("log-size"), OneConfig::LogSize), map(parse_item("max-reply-ip-num"), OneConfig::MaxReplyIpNum), map(parse_item("mdns-lookup"), OneConfig::MdnsLookup), diff --git a/src/config/server_opts.rs b/src/config/server_opts.rs index 5b4a8f2d..9eb85be2 100644 --- a/src/config/server_opts.rs +++ b/src/config/server_opts.rs @@ -38,6 +38,10 @@ pub struct ServerOpts { #[serde(skip_serializing_if = "Option::is_none")] pub force_aaaa_soa: Option, + /// force HTTPS query return SOA. + #[serde(skip_serializing_if = "Option::is_none")] + pub force_https_soa: Option, + /// do not serve expired #[serde(skip_serializing_if = "Option::is_none")] pub no_serve_expired: Option, @@ -101,6 +105,12 @@ impl ServerOpts { self.force_aaaa_soa.unwrap_or_default() } + /// force HTTPS query return SOA. + #[inline] + pub fn force_https_soa(&self) -> bool { + self.force_https_soa.unwrap_or_default() + } + /// do not serve expired. #[inline] pub fn no_serve_expired(&self) -> bool { @@ -118,6 +128,7 @@ impl ServerOpts { no_rule_soa, no_dualstack_selection, force_aaaa_soa, + force_https_soa, no_serve_expired, is_background: _, } = other; @@ -153,6 +164,10 @@ impl ServerOpts { self.force_aaaa_soa = force_aaaa_soa; } + if self.force_https_soa.is_none() { + self.force_https_soa = force_https_soa; + } + if self.no_serve_expired.is_none() { self.no_serve_expired = no_serve_expired; } diff --git a/src/dns_conf.rs b/src/dns_conf.rs index 08e86651..6b047548 100644 --- a/src/dns_conf.rs +++ b/src/dns_conf.rs @@ -345,6 +345,12 @@ impl RuntimeConfig { self.force_aaaa_soa.unwrap_or_default() } + /// force HTTPS query return SOA + #[inline] + pub fn force_https_soa(&self) -> bool { + self.force_https_soa.unwrap_or_default() + } + /// force specific qtype return soa #[inline] pub fn force_qtype_soa(&self) -> &HashSet { @@ -803,6 +809,7 @@ impl RuntimeConfigBuilder { ServeExpired(v) => self.cache.serve_expired = Some(v), PrefetchDomain(v) => self.cache.prefetch_domain = Some(v), ForceAAAASOA(v) => self.force_aaaa_soa = Some(v), + ForceHTTPSSOA(v) => self.force_https_soa = Some(v), DualstackIpAllowForceAAAA(v) => self.dualstack_ip_allow_force_aaaa = Some(v), DualstackIpSelection(v) => self.dualstack_ip_selection = Some(v), ServerName(v) => self.server_name = Some(v), diff --git a/src/dns_mw_addr.rs b/src/dns_mw_addr.rs index 773e824b..2455d18c 100644 --- a/src/dns_mw_addr.rs +++ b/src/dns_mw_addr.rs @@ -118,7 +118,7 @@ impl Middleware for AddressMiddle } fn handle_rule_addr(query_type: RecordType, ctx: &DnsContext) -> Option> { - use RecordType::{A, AAAA}; + use RecordType::{A, AAAA, HTTPS}; let cfg = ctx.cfg(); let server_opts = ctx.server_opts(); @@ -126,13 +126,21 @@ fn handle_rule_addr(query_type: RecordType, ctx: &DnsContext) -> Option { + return Some(vec![RData::default_soa()]); + } + // force HTTPS query return SOA + HTTPS if server_opts.force_https_soa() || cfg.force_https_soa() => { + return Some(vec![RData::default_soa()]); + } + _ => (), } - // force AAAA query return SOA + // force specific qtype return SOA if cfg.force_qtype_soa().contains(&query_type) { return Some(vec![RData::default_soa()]); }