Add config option for dns passthru for appservices. (#158)

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk
2025-09-10 01:01:00 +00:00
parent a9f1926654
commit bf8aa57d03
4 changed files with 41 additions and 5 deletions

View File

@@ -378,6 +378,13 @@ pub struct Config {
#[serde(default, with = "serde_regex")] #[serde(default, with = "serde_regex")]
pub dns_passthru_domains: RegexSet, pub dns_passthru_domains: RegexSet,
/// Whether to resolve appservices via the alternative path; setting this is
/// superior to providing domains in `dns_passthru_domains` if all
/// appservices intend to be matched anyway. The overhead of matching regex
/// and maintaining the list of domains can be avoided.
#[serde(default)]
pub dns_passthru_appservices: bool,
/// Max request size for file uploads in bytes. Defaults to 20MB. /// Max request size for file uploads in bytes. Defaults to 20MB.
/// ///
/// default: 20971520 /// default: 20971520

View File

@@ -5,7 +5,7 @@ use std::{
use either::Either; use either::Either;
use ipaddress::IPAddress; use ipaddress::IPAddress;
use reqwest::redirect; use reqwest::{dns::Resolve, redirect};
use tuwunel_core::{Config, Result, err, implement, trace}; use tuwunel_core::{Config, Result, err, implement, trace};
use crate::{service, services::OnceServices}; use crate::{service, services::OnceServices};
@@ -98,7 +98,7 @@ impl crate::Service for Service {
.redirect(redirect::Policy::limited(2))), .redirect(redirect::Policy::limited(2))),
appservice: create_client!(config, services; base(config)? appservice: create_client!(config, services; base(config)?
.dns_resolver2(Arc::clone(&services.resolver.resolver)) .dns_resolver2(appservice_resolver(&services))
.connect_timeout(Duration::from_secs(5)) .connect_timeout(Duration::from_secs(5))
.read_timeout(Duration::from_secs(config.appservice_timeout)) .read_timeout(Duration::from_secs(config.appservice_timeout))
.timeout(Duration::from_secs(config.appservice_timeout)) .timeout(Duration::from_secs(config.appservice_timeout))
@@ -220,6 +220,14 @@ fn builder_interface(
} }
} }
fn appservice_resolver(services: &Arc<OnceServices>) -> Arc<dyn Resolve> {
if services.server.config.dns_passthru_appservices {
services.resolver.resolver.passthru.clone()
} else {
services.resolver.resolver.clone()
}
}
#[inline] #[inline]
#[must_use] #[must_use]
#[implement(Service)] #[implement(Service)]

View File

@@ -13,7 +13,7 @@ use super::cache::{Cache, CachedOverride};
pub struct Resolver { pub struct Resolver {
pub(crate) resolver: Arc<TokioResolver>, pub(crate) resolver: Arc<TokioResolver>,
pub(crate) passthru: Arc<TokioResolver>, pub(crate) passthru: Arc<Passthru>,
pub(crate) hooked: Arc<Hooked>, pub(crate) hooked: Arc<Hooked>,
server: Arc<Server>, server: Arc<Server>,
} }
@@ -24,6 +24,11 @@ pub(crate) struct Hooked {
server: Arc<Server>, server: Arc<Server>,
} }
pub(crate) struct Passthru {
resolver: Arc<TokioResolver>,
server: Arc<Server>,
}
type ResolvingResult = Result<Addrs, Box<dyn std::error::Error + Send + Sync>>; type ResolvingResult = Result<Addrs, Box<dyn std::error::Error + Send + Sync>>;
impl Resolver { impl Resolver {
@@ -47,9 +52,12 @@ impl Resolver {
resolver: resolver.clone(), resolver: resolver.clone(),
cache, cache,
}), }),
passthru: Arc::new(Passthru {
server: server.clone(),
resolver: passthru,
}),
server: server.clone(), server: server.clone(),
resolver, resolver,
passthru,
})) }))
} }
@@ -137,7 +145,7 @@ impl Resolve for Resolver {
.dns_passthru_domains .dns_passthru_domains
.is_match(name.as_str()) .is_match(name.as_str())
{ {
&self.passthru &self.passthru.resolver
} else { } else {
&self.resolver &self.resolver
}; };
@@ -146,6 +154,12 @@ impl Resolve for Resolver {
} }
} }
impl Resolve for Passthru {
fn resolve(&self, name: Name) -> Resolving {
resolve_to_reqwest(self.server.clone(), self.resolver.clone(), name).boxed()
}
}
impl Resolve for Hooked { impl Resolve for Hooked {
fn resolve(&self, name: Name) -> Resolving { fn resolve(&self, name: Name) -> Resolving {
hooked_resolve(self.cache.clone(), self.server.clone(), self.resolver.clone(), name) hooked_resolve(self.cache.clone(), self.server.clone(), self.resolver.clone(), name)

View File

@@ -295,6 +295,13 @@
# #
#dns_passthru_domains = [] #dns_passthru_domains = []
# Whether to resolve appservices via the alternative path; setting this is
# superior to providing domains in `dns_passthru_domains` if all
# appservices intend to be matched anyway. The overhead of matching regex
# and maintaining the list of domains can be avoided.
#
#dns_passthru_appservices = false
# Max request size for file uploads in bytes. Defaults to 20MB. # Max request size for file uploads in bytes. Defaults to 20MB.
# #
#max_request_size = 20971520 #max_request_size = 20971520