enable caching in hickory_dns w/ configurables.

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-03-24 23:59:28 -07:00 committed by June
parent 21874f8ab7
commit 525379f8ac
3 changed files with 75 additions and 9 deletions

View file

@ -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, Connection Timeouts, and Connection Pooling
## Request Timeouts are HTTP response timeouts ## Request Timeouts are HTTP response timeouts

View file

@ -57,6 +57,16 @@ pub struct Config {
pub pdu_cache_capacity: u32, pub pdu_cache_capacity: u32,
#[serde(default = "default_cleanup_second_interval")] #[serde(default = "default_cleanup_second_interval")]
pub cleanup_second_interval: u32, 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")] #[serde(default = "default_max_request_size")]
pub max_request_size: u32, pub max_request_size: u32,
#[serde(default = "default_max_concurrent_requests")] #[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()), ("Cache capacity modifier", &self.conduit_cache_capacity_modifier.to_string()),
("PDU cache capacity", &self.pdu_cache_capacity.to_string()), ("PDU cache capacity", &self.pdu_cache_capacity.to_string()),
("Cleanup interval in seconds", &self.cleanup_second_interval.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 request size (bytes)", &self.max_request_size.to_string()),
("Maximum concurrent requests", &self.max_concurrent_requests.to_string()), ("Maximum concurrent requests", &self.max_concurrent_requests.to_string()),
("Request connect timeout", &self.request_conn_timeout.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 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 { fn default_max_request_size() -> u32 {
20 * 1024 * 1024 // Default to 20 MB 20 * 1024 * 1024 // Default to 20 MB
} }

View file

@ -3,6 +3,7 @@ use std::{
future, iter, future, iter,
net::{IpAddr, SocketAddr}, net::{IpAddr, SocketAddr},
sync::{Arc, RwLock as StdRwLock}, sync::{Arc, RwLock as StdRwLock},
time::Duration,
}; };
use hickory_resolver::TokioAsyncResolver; use hickory_resolver::TokioAsyncResolver;
@ -30,14 +31,27 @@ pub struct Hooked {
} }
impl Resolver { impl Resolver {
pub(crate) fn new(_config: &Config) -> Self { pub(crate) fn new(config: &Config) -> Self {
let overrides = Arc::new(StdRwLock::new(TlsNameMap::new())); let (conf, mut opts) = hickory_resolver::system_conf::read_system_conf()
let resolver = Arc::new(TokioAsyncResolver::tokio_from_system_conf().map_err(|e| { .map_err(|e| {
error!("Failed to set up trust dns resolver with system config: {}", e); error!("Failed to set up hickory dns resolver with system config: {}", e);
Error::bad_config("Failed to set up trust dns resolver with system config.") Error::bad_config("Failed to set up hickory dns resolver with system config.")
}) })
.unwrap()); .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 { Resolver {
destinations: Arc::new(RwLock::new(WellKnownMap::new())), destinations: Arc::new(RwLock::new(WellKnownMap::new())),
overrides: overrides.clone(), overrides: overrides.clone(),
@ -62,8 +76,10 @@ impl Resolve for Hooked {
.read() .read()
.unwrap() .unwrap()
.get(name.as_str()) .get(name.as_str())
.map(|(override_name, port)| cached_to_reqwest(override_name, *port)) .map_or_else(
.unwrap_or_else(|| resolve_to_reqwest(self.resolver.clone(), name)) || resolve_to_reqwest(self.resolver.clone(), name),
|(override_name, port)| cached_to_reqwest(override_name, *port)
)
} }
} }