diff --git a/conduwuit-example.toml b/conduwuit-example.toml index 1431025b..662bc01d 100644 --- a/conduwuit-example.toml +++ b/conduwuit-example.toml @@ -390,6 +390,31 @@ url_preview_check_root_domain = false +### Domain Name Resolution and Caching + +# Maximum entries stored in DNS memory-cache. The size of an entry may vary so please take care if +# raising this value excessively. Only decrease this when using an external DNS cache. Please note +# that systemd does *not* count as an external cache, even when configured to do so. +#dns_cache_entries = 12288 + +# Minimum time-to-live in seconds for entries in the DNS cache. The default may appear high to most +# administrators; this is by design. Only decrease this if you are using an external DNS cache. +#dns_min_ttl = 60 * 90 + +# Minimum time-to-live in seconds for NXDOMAIN entries in the DNS cache. This value is critical for +# the server to federate efficiently. NXDOMAIN's are assumed to not be returning to the federation +# and aggressively cached rather than constantly rechecked. +#dns_min_ttl_nxdomain = 60 * 60 * 24 * 3 + +# The number of seconds to wait for a reply to a DNS query. Please note that recursive queries can +# take up to several seconds for some domains, so this value should not be too low. +#dns_timeout = 5 + +# Number of retries after a timeout. +#dns_attempts = 5 + + + ### Request Timeouts, Connection Timeouts, and Connection Pooling ## Request Timeouts are HTTP response timeouts diff --git a/src/config/mod.rs b/src/config/mod.rs index 3f341c09..e8310b2b 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -57,6 +57,16 @@ pub struct Config { pub pdu_cache_capacity: u32, #[serde(default = "default_cleanup_second_interval")] pub cleanup_second_interval: u32, + #[serde(default = "default_dns_cache_entries")] + pub dns_cache_entries: u32, + #[serde(default = "default_dns_min_ttl")] + pub dns_min_ttl: u64, + #[serde(default = "default_dns_min_ttl_nxdomain")] + pub dns_min_ttl_nxdomain: u64, + #[serde(default = "default_dns_attempts")] + pub dns_attempts: u16, + #[serde(default = "default_dns_timeout")] + pub dns_timeout: u64, #[serde(default = "default_max_request_size")] pub max_request_size: u32, #[serde(default = "default_max_concurrent_requests")] @@ -301,6 +311,11 @@ impl fmt::Display for Config { ("Cache capacity modifier", &self.conduit_cache_capacity_modifier.to_string()), ("PDU cache capacity", &self.pdu_cache_capacity.to_string()), ("Cleanup interval in seconds", &self.cleanup_second_interval.to_string()), + ("DNS cache entry limit", &self.dns_cache_entries.to_string()), + ("DNS minimum ttl", &self.dns_min_ttl.to_string()), + ("DNS minimum nxdomain ttl", &self.dns_min_ttl_nxdomain.to_string()), + ("DNS attempts", &self.dns_attempts.to_string()), + ("DNS timeout", &self.dns_timeout.to_string()), ("Maximum request size (bytes)", &self.max_request_size.to_string()), ("Maximum concurrent requests", &self.max_concurrent_requests.to_string()), ("Request connect timeout", &self.request_conn_timeout.to_string()), @@ -528,6 +543,16 @@ fn default_cleanup_second_interval() -> u32 { 1800 // every 30 minutes } +fn default_dns_cache_entries() -> u32 { 12288 } + +fn default_dns_min_ttl() -> u64 { 60 * 90 } + +fn default_dns_min_ttl_nxdomain() -> u64 { 60 * 60 * 24 * 3 } + +fn default_dns_attempts() -> u16 { 5 } + +fn default_dns_timeout() -> u64 { 5 } + fn default_max_request_size() -> u32 { 20 * 1024 * 1024 // Default to 20 MB } diff --git a/src/service/globals/resolver.rs b/src/service/globals/resolver.rs index 1745c931..f2acc5f8 100644 --- a/src/service/globals/resolver.rs +++ b/src/service/globals/resolver.rs @@ -3,6 +3,7 @@ use std::{ future, iter, net::{IpAddr, SocketAddr}, sync::{Arc, RwLock as StdRwLock}, + time::Duration, }; use hickory_resolver::TokioAsyncResolver; @@ -30,14 +31,27 @@ pub struct Hooked { } impl Resolver { - pub(crate) fn new(_config: &Config) -> Self { - let overrides = Arc::new(StdRwLock::new(TlsNameMap::new())); - let resolver = Arc::new(TokioAsyncResolver::tokio_from_system_conf().map_err(|e| { - error!("Failed to set up trust dns resolver with system config: {}", e); - Error::bad_config("Failed to set up trust dns resolver with system config.") - }) - .unwrap()); + pub(crate) fn new(config: &Config) -> Self { + let (conf, mut opts) = hickory_resolver::system_conf::read_system_conf() + .map_err(|e| { + error!("Failed to set up hickory dns resolver with system config: {}", e); + Error::bad_config("Failed to set up hickory dns resolver with system config.") + }) + .unwrap(); + opts.cache_size = config.dns_cache_entries as usize; + opts.negative_min_ttl = Some(Duration::from_secs(config.dns_min_ttl_nxdomain)); + opts.negative_max_ttl = Some(Duration::from_secs(60 * 60 * 24 * 30)); + opts.positive_min_ttl = Some(Duration::from_secs(config.dns_min_ttl)); + opts.positive_max_ttl = Some(Duration::from_secs(60 * 60 * 24 * 7)); + opts.timeout = Duration::from_secs(config.dns_timeout); + opts.attempts = config.dns_attempts as usize; + opts.num_concurrent_reqs = 1; + opts.shuffle_dns_servers = true; + opts.rotate = true; + + let resolver = Arc::new(TokioAsyncResolver::tokio(conf, opts)); + let overrides = Arc::new(StdRwLock::new(TlsNameMap::new())); Resolver { destinations: Arc::new(RwLock::new(WellKnownMap::new())), overrides: overrides.clone(), @@ -62,8 +76,10 @@ impl Resolve for Hooked { .read() .unwrap() .get(name.as_str()) - .map(|(override_name, port)| cached_to_reqwest(override_name, *port)) - .unwrap_or_else(|| resolve_to_reqwest(self.resolver.clone(), name)) + .map_or_else( + || resolve_to_reqwest(self.resolver.clone(), name), + |(override_name, port)| cached_to_reqwest(override_name, *port) + ) } }