From 248d778290c64fbd0f9b483d949e391e9dc2037f Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Tue, 9 Sep 2025 23:53:51 +0000 Subject: [PATCH] Add alternative resolver path with passthru cache-characteristics. (resolves #158) Signed-off-by: Jason Volk --- src/core/config/mod.rs | 12 ++++++++++ src/service/resolver/dns.rs | 44 ++++++++++++++++++++++++++++++++----- tuwunel-example.toml | 10 +++++++++ 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index b565d786..ca44e2b9 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -366,6 +366,18 @@ pub struct Config { #[serde(default = "default_ip_lookup_strategy")] pub ip_lookup_strategy: u8, + /// List of domain patterns resolved via the alternative path without any + /// persistent cache, very small memory cache, and no enforced TTL. This + /// is intended for internal network and application services which require + /// these specific properties. This path does not support federation or + /// general purposes. + /// + /// example: ["*\.dns\.podman$"] + /// + /// default: [] + #[serde(default, with = "serde_regex")] + pub dns_passthru_domains: RegexSet, + /// Max request size for file uploads in bytes. Defaults to 20MB. /// /// default: 20971520 diff --git a/src/service/resolver/dns.rs b/src/service/resolver/dns.rs index bb89ce3e..29f034d6 100644 --- a/src/service/resolver/dns.rs +++ b/src/service/resolver/dns.rs @@ -13,6 +13,7 @@ use super::cache::{Cache, CachedOverride}; pub struct Resolver { pub(crate) resolver: Arc, + pub(crate) passthru: Arc, pub(crate) hooked: Arc, server: Arc, } @@ -27,12 +28,18 @@ type ResolvingResult = Result>; impl Resolver { pub(super) fn build(server: &Arc, cache: Arc) -> Result> { + // Create the primary resolver. let (conf, opts) = Self::configure(server)?; - let rt_prov = hickory_resolver::proto::runtime::TokioRuntimeProvider::new(); - let conn_prov = hickory_resolver::name_server::TokioConnectionProvider::new(rt_prov); - let mut builder = TokioResolver::builder_with_config(conf, conn_prov); - *builder.options_mut() = Self::configure_opts(server, opts); - let resolver = Arc::new(builder.build()); + let resolver = Self::create(server, conf.clone(), opts.clone())?; + + // Create the passthru resolver with modified options. + let (conf, mut opts) = (conf, opts); + opts.negative_min_ttl = None; + opts.negative_max_ttl = None; + opts.positive_min_ttl = None; + opts.positive_max_ttl = None; + opts.cache_size = ResolverOpts::default().cache_size; + let passthru = Self::create(server, conf, opts)?; Ok(Arc::new(Self { hooked: Arc::new(Hooked { @@ -42,9 +49,23 @@ impl Resolver { }), server: server.clone(), resolver, + passthru, })) } + fn create( + server: &Arc, + conf: ResolverConfig, + opts: ResolverOpts, + ) -> Result> { + let rt_prov = hickory_resolver::proto::runtime::TokioRuntimeProvider::new(); + let conn_prov = hickory_resolver::name_server::TokioConnectionProvider::new(rt_prov); + let mut builder = TokioResolver::builder_with_config(conf, conn_prov); + *builder.options_mut() = Self::configure_opts(server, opts); + + Ok(Arc::new(builder.build())) + } + fn configure(server: &Arc) -> Result<(ResolverConfig, ResolverOpts)> { let config = &server.config; let (sys_conf, opts) = hickory_resolver::system_conf::read_system_conf() @@ -110,7 +131,18 @@ impl Resolver { impl Resolve for Resolver { fn resolve(&self, name: Name) -> Resolving { - resolve_to_reqwest(self.server.clone(), self.resolver.clone(), name).boxed() + let resolver = if self + .server + .config + .dns_passthru_domains + .is_match(name.as_str()) + { + &self.passthru + } else { + &self.resolver + }; + + resolve_to_reqwest(self.server.clone(), resolver.clone(), name).boxed() } } diff --git a/tuwunel-example.toml b/tuwunel-example.toml index 56129211..029123af 100644 --- a/tuwunel-example.toml +++ b/tuwunel-example.toml @@ -285,6 +285,16 @@ # #ip_lookup_strategy = 5 +# List of domain patterns resolved via the alternative path without any +# persistent cache, very small memory cache, and no enforced TTL. This +# is intended for internal network and application services which require +# these specific properties. This path does not support federation or +# general purposes. +# +# example: ["*\.dns\.podman$"] +# +#dns_passthru_domains = [] + # Max request size for file uploads in bytes. Defaults to 20MB. # #max_request_size = 20971520