Skip to main content

hickory_resolver/
config.rs

1// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! Configuration for a resolver
9#![allow(clippy::use_self)]
10
11use std::collections::HashSet;
12use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
13use std::path::PathBuf;
14use std::sync::Arc;
15use std::time::Duration;
16#[cfg(all(
17    feature = "toml",
18    feature = "serde",
19    any(feature = "__tls", feature = "__quic")
20))]
21use std::{fs, io};
22
23use ipnet::IpNet;
24#[cfg(feature = "serde")]
25use serde::{Deserialize, Serialize};
26use tracing::warn;
27#[cfg(all(
28    feature = "toml",
29    feature = "serde",
30    any(feature = "__tls", feature = "__quic")
31))]
32use tracing::{debug, info};
33
34#[cfg(all(
35    feature = "toml",
36    feature = "serde",
37    any(feature = "__tls", feature = "__quic")
38))]
39use crate::name_server_pool::NameServerTransportState;
40#[cfg(any(feature = "__https", feature = "__h3"))]
41use crate::net::http::DEFAULT_DNS_QUERY_PATH;
42use crate::net::xfer::Protocol;
43use crate::proto::access_control::{AccessControlSet, AccessControlSetBuilder};
44use crate::proto::op::DEFAULT_MAX_PAYLOAD_LEN;
45use crate::proto::rr::Name;
46
47/// Configuration for the upstream nameservers to use for resolution.
48///
49/// The `Default` implementation of this struct will be removed in a future version. Use
50/// [`Self::from_name_servers()`] instead. Note that a `ResolverConfig` with no name servers will
51/// produce a nonfunctional resolver.
52#[non_exhaustive]
53#[derive(Clone, Debug, Default)]
54#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
55pub struct ResolverConfig {
56    /// Base search domain
57    #[cfg_attr(feature = "serde", serde(default))]
58    pub domain: Option<Name>,
59    /// Search domains
60    #[cfg_attr(feature = "serde", serde(default))]
61    pub search: Vec<Name>,
62    /// Name servers to use for resolution
63    pub name_servers: Vec<NameServerConfig>,
64}
65
66impl ResolverConfig {
67    /// Create a new `ResolverConfig` from [`ServerGroup`] configuration.
68    ///
69    /// Connects via UDP and TCP.
70    pub fn udp_and_tcp(config: &ServerGroup<'_>) -> Self {
71        Self {
72            // TODO: this should get the hostname and use the basename as the default
73            domain: None,
74            search: vec![],
75            name_servers: config.udp_and_tcp().collect(),
76        }
77    }
78
79    /// Create a new `ResolverConfig` from [`ServerGroup`] configuration.
80    ///
81    /// Only connects via TLS.
82    #[cfg(feature = "__tls")]
83    pub fn tls(config: &ServerGroup<'_>) -> Self {
84        Self {
85            // TODO: this should get the hostname and use the basename as the default
86            domain: None,
87            search: vec![],
88            name_servers: config.tls().collect(),
89        }
90    }
91
92    /// Create a new `ResolverConfig` from [`ServerGroup`] configuration.
93    ///
94    /// Only connects via HTTPS (HTTP/2).
95    #[cfg(feature = "__https")]
96    pub fn https(config: &ServerGroup<'_>) -> Self {
97        Self {
98            // TODO: this should get the hostname and use the basename as the default
99            domain: None,
100            search: vec![],
101            name_servers: config.https().collect(),
102        }
103    }
104
105    /// Create a new `ResolverConfig` from [`ServerGroup`] configuration.
106    ///
107    /// Only connects via QUIC.
108    #[cfg(feature = "__quic")]
109    pub fn quic(config: &ServerGroup<'_>) -> Self {
110        Self {
111            // TODO: this should get the hostname and use the basename as the default
112            domain: None,
113            search: vec![],
114            name_servers: config.quic().collect(),
115        }
116    }
117
118    /// Create a new `ResolverConfig` from [`ServerGroup`] configuration.
119    ///
120    /// Only connects via HTTP/3.
121    #[cfg(feature = "__h3")]
122    pub fn h3(config: &ServerGroup<'_>) -> Self {
123        Self {
124            // TODO: this should get the hostname and use the basename as the default
125            domain: None,
126            search: vec![],
127            name_servers: config.h3().collect(),
128        }
129    }
130
131    /// Create a ResolverConfig with all parts specified
132    ///
133    /// # Arguments
134    ///
135    /// * `domain` - domain of the entity querying results. If the `Name` being looked up is not an FQDN, then this is the first part appended to attempt a lookup. `ndots` in the `ResolverOption` does take precedence over this.
136    /// * `search` - additional search domains that are attempted if the `Name` is not found in `domain`, defaults to `vec![]`
137    /// * `name_servers` - set of name servers to use for lookups
138    pub fn from_parts(
139        domain: Option<Name>,
140        search: Vec<Name>,
141        name_servers: Vec<NameServerConfig>,
142    ) -> Self {
143        Self {
144            domain,
145            search,
146            name_servers,
147        }
148    }
149
150    /// Create a ResolverConfig from a list of name server configurations.
151    ///
152    /// No base domain for relative names will be set, and no additional search domains will be set.
153    pub fn from_name_servers(name_servers: Vec<NameServerConfig>) -> Self {
154        Self::from_parts(None, vec![], name_servers)
155    }
156
157    /// Take the `domain`, `search`, and `name_servers` from the config.
158    pub fn into_parts(self) -> (Option<Name>, Vec<Name>, Vec<NameServerConfig>) {
159        (self.domain, self.search, self.name_servers)
160    }
161
162    /// Returns the local domain
163    ///
164    /// By default any names will be appended to all non-fully-qualified-domain names, and searched for after any ndots rules
165    pub fn domain(&self) -> Option<&Name> {
166        self.domain.as_ref()
167    }
168
169    /// Set the domain of the entity querying results.
170    pub fn set_domain(&mut self, domain: Name) {
171        self.domain = Some(domain.clone());
172        self.search = vec![domain];
173    }
174
175    /// Returns the search domains
176    ///
177    /// These will be queried after any local domain and then in the order of the set of search domains
178    pub fn search(&self) -> &[Name] {
179        &self.search
180    }
181
182    /// Add a search domain
183    pub fn add_search(&mut self, search: Name) {
184        self.search.push(search)
185    }
186
187    // TODO: consider allowing options per NameServer... like different timeouts?
188    /// Add the configuration for a name server
189    pub fn add_name_server(&mut self, name_server: NameServerConfig) {
190        self.name_servers.push(name_server);
191    }
192
193    /// Returns a reference to the name servers
194    pub fn name_servers(&self) -> &[NameServerConfig] {
195        &self.name_servers
196    }
197}
198
199/// Configuration for the NameServer
200#[derive(Clone, Debug)]
201#[cfg_attr(
202    feature = "serde",
203    derive(Serialize, Deserialize),
204    serde(deny_unknown_fields)
205)]
206#[non_exhaustive]
207pub struct NameServerConfig {
208    /// The address which the DNS NameServer is registered at.
209    pub ip: IpAddr,
210    /// Whether to trust `NXDOMAIN` responses from upstream nameservers.
211    ///
212    /// When this is `true`, and an empty `NXDOMAIN` response with an empty answers set is
213    /// received, the query will not be retried against other configured name servers.
214    ///
215    /// (On a response with any other error response code, the query will still be retried
216    /// regardless of this configuration setting.)
217    ///
218    /// Defaults to `true`.
219    #[cfg_attr(feature = "serde", serde(default = "default_trust_negative_responses"))]
220    pub trust_negative_responses: bool,
221    /// Connection protocols configured for this server.
222    pub connections: Vec<ConnectionConfig>,
223}
224
225impl NameServerConfig {
226    /// Constructs a nameserver configuration with a UDP and TCP connections
227    pub fn udp_and_tcp(ip: IpAddr) -> Self {
228        Self {
229            ip,
230            trust_negative_responses: true,
231            connections: vec![ConnectionConfig::udp(), ConnectionConfig::tcp()],
232        }
233    }
234
235    /// Constructs a nameserver configuration with a single UDP connection
236    pub fn udp(ip: IpAddr) -> Self {
237        Self {
238            ip,
239            trust_negative_responses: true,
240            connections: vec![ConnectionConfig::udp()],
241        }
242    }
243
244    /// Constructs a nameserver configuration with a single TCP connection
245    pub fn tcp(ip: IpAddr) -> Self {
246        Self {
247            ip,
248            trust_negative_responses: true,
249            connections: vec![ConnectionConfig::tcp()],
250        }
251    }
252
253    /// Constructs a nameserver configuration with a single TLS connection
254    #[cfg(feature = "__tls")]
255    pub fn tls(ip: IpAddr, server_name: Arc<str>) -> Self {
256        Self {
257            ip,
258            trust_negative_responses: true,
259            connections: vec![ConnectionConfig::tls(server_name)],
260        }
261    }
262
263    /// Constructs a nameserver configuration with a single HTTP/2 connection
264    #[cfg(feature = "__https")]
265    pub fn https(ip: IpAddr, server_name: Arc<str>, path: Option<Arc<str>>) -> Self {
266        Self {
267            ip,
268            trust_negative_responses: true,
269            connections: vec![ConnectionConfig::https(server_name, path)],
270        }
271    }
272
273    /// Constructs a nameserver configuration with a single QUIC connection
274    #[cfg(feature = "__quic")]
275    pub fn quic(ip: IpAddr, server_name: Arc<str>) -> Self {
276        Self {
277            ip,
278            trust_negative_responses: true,
279            connections: vec![ConnectionConfig::quic(server_name)],
280        }
281    }
282
283    /// Constructs a nameserver configuration with a single HTTP/3 connection
284    #[cfg(feature = "__h3")]
285    pub fn h3(ip: IpAddr, server_name: Arc<str>, path: Option<Arc<str>>) -> Self {
286        Self {
287            ip,
288            trust_negative_responses: true,
289            connections: vec![ConnectionConfig::h3(server_name, path)],
290        }
291    }
292
293    /// Constructs a nameserver configuration for opportunistic encryption.
294    ///
295    /// This will include configurations for plaintext UDP/TCP as well as DNS-over-TLS and/or
296    /// DNS-over-QUIC depending on feature flag support.
297    ///
298    /// Notably, the TLS and QUIC configurations will **not** verify peer certificates, in
299    /// keeping with RFC 9539's requirement. See [RFC 9539 §4.6.3.4] for more information.
300    ///
301    /// [RFC 9539 §4.6.3.4]: https://www.rfc-editor.org/rfc/rfc9539.html#section-4.6.3.4
302    #[cfg(any(feature = "__tls", feature = "__quic"))]
303    pub fn opportunistic_encryption(ip: IpAddr) -> Self {
304        Self {
305            ip,
306            trust_negative_responses: true,
307            connections: vec![
308                ConnectionConfig::udp(),
309                ConnectionConfig::tcp(),
310                #[cfg(feature = "__tls")]
311                ConnectionConfig::tls(Arc::from(ip.to_string())),
312                #[cfg(feature = "__quic")]
313                ConnectionConfig::quic(Arc::from(ip.to_string())),
314            ],
315        }
316    }
317
318    /// Create a new [`NameServerConfig`] from its constituent parts.
319    pub fn new(
320        ip: IpAddr,
321        trust_negative_responses: bool,
322        connections: Vec<ConnectionConfig>,
323    ) -> Self {
324        Self {
325            ip,
326            trust_negative_responses,
327            connections,
328        }
329    }
330}
331
332#[cfg(feature = "serde")]
333fn default_trust_negative_responses() -> bool {
334    true
335}
336
337/// Configuration for a connection to a nameserver
338#[derive(Clone, Debug)]
339#[cfg_attr(feature = "serde", derive(Serialize))]
340#[non_exhaustive]
341pub struct ConnectionConfig {
342    /// The remote port to connect to
343    pub port: u16,
344    /// The protocol to use for the connection
345    pub protocol: ProtocolConfig,
346    /// The client address (IP and port) to use for connecting to the server
347    pub bind_addr: Option<SocketAddr>,
348}
349
350impl ConnectionConfig {
351    /// Constructs a new ConnectionConfig for UDP
352    pub fn udp() -> Self {
353        Self::new(ProtocolConfig::Udp)
354    }
355
356    /// Constructs a new ConnectionConfig for TCP
357    pub fn tcp() -> Self {
358        Self::new(ProtocolConfig::Tcp)
359    }
360
361    /// Constructs a new ConnectionConfig for TLS
362    #[cfg(feature = "__tls")]
363    pub fn tls(server_name: Arc<str>) -> Self {
364        Self::new(ProtocolConfig::Tls { server_name })
365    }
366
367    /// Constructs a new ConnectionConfig for HTTPS (HTTP/2)
368    #[cfg(feature = "__https")]
369    pub fn https(server_name: Arc<str>, path: Option<Arc<str>>) -> Self {
370        Self::new(ProtocolConfig::Https {
371            server_name,
372            path: path.unwrap_or_else(|| Arc::from(DEFAULT_DNS_QUERY_PATH)),
373        })
374    }
375
376    /// Constructs a new ConnectionConfig for QUIC
377    #[cfg(feature = "__quic")]
378    pub fn quic(server_name: Arc<str>) -> Self {
379        Self::new(ProtocolConfig::Quic { server_name })
380    }
381
382    /// Constructs a new ConnectionConfig for HTTP/3
383    #[cfg(feature = "__h3")]
384    pub fn h3(server_name: Arc<str>, path: Option<Arc<str>>) -> Self {
385        Self::new(ProtocolConfig::H3 {
386            server_name,
387            path: path.unwrap_or_else(|| Arc::from(DEFAULT_DNS_QUERY_PATH)),
388            disable_grease: false,
389        })
390    }
391
392    /// Constructs a new ConnectionConfig with the specified [`ProtocolConfig`].
393    pub fn new(protocol: ProtocolConfig) -> Self {
394        Self {
395            port: protocol.default_port(),
396            protocol,
397            bind_addr: None,
398        }
399    }
400}
401
402#[cfg(feature = "serde")]
403impl<'de> Deserialize<'de> for ConnectionConfig {
404    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
405        #[derive(Deserialize)]
406        #[serde(deny_unknown_fields)]
407        struct OptionalParts {
408            #[serde(default)]
409            port: Option<u16>,
410            protocol: ProtocolConfig,
411            #[serde(default)]
412            bind_addr: Option<SocketAddr>,
413        }
414
415        let parts = OptionalParts::deserialize(deserializer)?;
416        Ok(Self {
417            port: parts.port.unwrap_or_else(|| parts.protocol.default_port()),
418            protocol: parts.protocol,
419            bind_addr: parts.bind_addr,
420        })
421    }
422}
423
424/// Protocol configuration
425#[allow(missing_docs)]
426#[derive(Clone, Debug, Default, PartialEq)]
427#[cfg_attr(
428    feature = "serde",
429    derive(Serialize, Deserialize),
430    serde(deny_unknown_fields, rename_all = "snake_case", tag = "type")
431)]
432pub enum ProtocolConfig {
433    #[default]
434    Udp,
435    Tcp,
436    #[cfg(feature = "__tls")]
437    Tls {
438        /// The server name to use in the TLS handshake.
439        server_name: Arc<str>,
440    },
441    #[cfg(feature = "__https")]
442    Https {
443        /// The server name to use in the TLS handshake.
444        server_name: Arc<str>,
445        /// The path (or endpoint) to use for the DNS query.
446        path: Arc<str>,
447    },
448    #[cfg(feature = "__quic")]
449    Quic {
450        /// The server name to use in the TLS handshake.
451        server_name: Arc<str>,
452    },
453    #[cfg(feature = "__h3")]
454    H3 {
455        /// The server name to use in the TLS handshake.
456        server_name: Arc<str>,
457        /// The path (or endpoint) to use for the DNS query.
458        path: Arc<str>,
459        /// Whether to disable sending "grease"
460        #[cfg_attr(feature = "serde", serde(default))]
461        disable_grease: bool,
462    },
463}
464
465impl ProtocolConfig {
466    /// Get the [`Protocol`] for this [`ProtocolConfig`].
467    pub fn to_protocol(&self) -> Protocol {
468        match self {
469            ProtocolConfig::Udp => Protocol::Udp,
470            ProtocolConfig::Tcp => Protocol::Tcp,
471            #[cfg(feature = "__tls")]
472            ProtocolConfig::Tls { .. } => Protocol::Tls,
473            #[cfg(feature = "__https")]
474            ProtocolConfig::Https { .. } => Protocol::Https,
475            #[cfg(feature = "__quic")]
476            ProtocolConfig::Quic { .. } => Protocol::Quic,
477            #[cfg(feature = "__h3")]
478            ProtocolConfig::H3 { .. } => Protocol::H3,
479        }
480    }
481
482    /// Default port for the protocol.
483    pub fn default_port(&self) -> u16 {
484        match self {
485            ProtocolConfig::Udp => 53,
486            ProtocolConfig::Tcp => 53,
487            #[cfg(feature = "__tls")]
488            ProtocolConfig::Tls { .. } => 853,
489            #[cfg(feature = "__https")]
490            ProtocolConfig::Https { .. } => 443,
491            #[cfg(feature = "__quic")]
492            ProtocolConfig::Quic { .. } => 853,
493            #[cfg(feature = "__h3")]
494            ProtocolConfig::H3 { .. } => 443,
495        }
496    }
497}
498
499/// Configuration for the Resolver
500#[derive(Debug, Clone)]
501#[cfg_attr(
502    feature = "serde",
503    derive(Serialize, Deserialize),
504    serde(default, deny_unknown_fields)
505)]
506#[non_exhaustive]
507pub struct ResolverOpts {
508    /// Sets the number of dots that must appear (unless it's a final dot representing the root)
509    ///  before a query is assumed to include the TLD. The default is one, which means that `www`
510    ///  would never be assumed to be a TLD, and would always be appended to either the search
511    #[cfg_attr(feature = "serde", serde(default = "default_ndots"))]
512    pub ndots: usize,
513    /// Specify the timeout for a request. Defaults to 5 seconds
514    #[cfg_attr(
515        feature = "serde",
516        serde(default = "default_timeout", with = "duration")
517    )]
518    pub timeout: Duration,
519    /// Number of retries after lookup failure before giving up. Defaults to 2
520    #[cfg_attr(feature = "serde", serde(default = "default_attempts"))]
521    pub attempts: usize,
522    /// Enable edns, for larger records
523    pub edns0: bool,
524    /// Use DNSSEC to validate the request
525    #[cfg(feature = "__dnssec")]
526    pub validate: bool,
527    /// The strategy for the Resolver to use when looking up host IP addresses
528    pub ip_strategy: LookupIpStrategy,
529    /// Cache size is in number of responses (some responses can be large)
530    #[cfg_attr(feature = "serde", serde(default = "default_cache_size"))]
531    pub cache_size: u64,
532    /// Check /etc/hosts file before dns requery (only works for unix like OS)
533    pub use_hosts_file: ResolveHosts,
534    /// Optional minimum TTL for positive responses.
535    ///
536    /// If this is set, any positive responses with a TTL lower than this value will have a TTL of
537    /// `positive_min_ttl` instead. Otherwise, this will default to 0 seconds.
538    #[cfg_attr(feature = "serde", serde(with = "duration_opt"))]
539    pub positive_min_ttl: Option<Duration>,
540    /// Optional minimum TTL for negative (`NXDOMAIN`) responses.
541    ///
542    /// If this is set, any negative responses with a TTL lower than this value will have a TTL of
543    /// `negative_min_ttl` instead. Otherwise, this will default to 0 seconds.
544    #[cfg_attr(feature = "serde", serde(with = "duration_opt"))]
545    pub negative_min_ttl: Option<Duration>,
546    /// Optional maximum TTL for positive responses.
547    ///
548    /// If this is set, any positive responses with a TTL higher than this value will have a TTL of
549    /// `positive_max_ttl` instead. Otherwise, this will default to [`MAX_TTL`](crate::MAX_TTL) seconds.
550    #[cfg_attr(feature = "serde", serde(with = "duration_opt"))]
551    pub positive_max_ttl: Option<Duration>,
552    /// Optional maximum TTL for negative (`NXDOMAIN`) responses.
553    ///
554    /// If this is set, any negative responses with a TTL higher than this value will have a TTL of
555    /// `negative_max_ttl` instead. Otherwise, this will default to [`MAX_TTL`](crate::MAX_TTL) seconds.
556    #[cfg_attr(feature = "serde", serde(with = "duration_opt"))]
557    pub negative_max_ttl: Option<Duration>,
558    /// Number of concurrent requests per query
559    ///
560    /// Where more than one nameserver is configured, this configures the resolver to send queries
561    /// to a number of servers in parallel. Defaults to 2; 0 or 1 will execute requests serially.
562    #[cfg_attr(feature = "serde", serde(default = "default_num_concurrent_reqs"))]
563    pub num_concurrent_reqs: usize,
564    /// Maximum number of active (in-flight) requests per multiplexed connection.
565    ///
566    /// This limits how many DNS queries can be simultaneously pending on a single
567    /// connection to an upstream nameserver. When the limit is reached, new requests
568    /// will return a busy error.
569    ///
570    /// Defaults to 32. Higher values allow more parallelism but consume more memory.
571    #[cfg_attr(feature = "serde", serde(default = "default_max_active_requests"))]
572    pub max_active_requests: usize,
573    /// Preserve all intermediate records in the lookup response, such as CNAME records
574    #[cfg_attr(feature = "serde", serde(default = "default_preserve_intermediates"))]
575    pub preserve_intermediates: bool,
576    /// Try queries over TCP if they fail over UDP.
577    pub try_tcp_on_error: bool,
578    /// The server ordering strategy that the resolver should use.
579    pub server_ordering_strategy: ServerOrderingStrategy,
580    /// Request upstream recursive resolvers to not perform any recursion.
581    ///
582    /// This is true by default, disabling this is useful for requesting single records, but may prevent successful resolution.
583    #[cfg_attr(feature = "serde", serde(default = "default_recursion_desired"))]
584    pub recursion_desired: bool,
585    /// Local UDP ports to avoid when making outgoing queries
586    pub avoid_local_udp_ports: Arc<HashSet<u16>>,
587    /// Request UDP bind ephemeral ports directly from the OS
588    ///
589    /// Boolean parameter to specify whether to use the operating system's standard UDP port
590    /// selection logic instead of Hickory's logic to securely select a random source port. We do
591    /// not recommend using this option unless absolutely necessary, as the operating system may
592    /// select ephemeral ports from a smaller range than Hickory, which can make response poisoning
593    /// attacks easier to conduct. Some operating systems (notably, Windows) might display a
594    /// user-prompt to allow a Hickory-specified port to be used, and setting this option will
595    /// prevent those prompts from being displayed. If os_port_selection is true, avoid_local_udp_ports
596    /// will be ignored.
597    pub os_port_selection: bool,
598    /// Enable case randomization.
599    ///
600    /// Randomize the case of letters in query names, and require that responses preserve the case
601    /// of the query name, in order to mitigate spoofing attacks. This is only applied over UDP.
602    ///
603    /// This implements the mechanism described in
604    /// [draft-vixie-dnsext-dns0x20-00](https://datatracker.ietf.org/doc/html/draft-vixie-dnsext-dns0x20-00).
605    pub case_randomization: bool,
606    /// Path to a DNSSEC trust anchor file.
607    ///
608    /// If this is provided, `validate` will automatically be set to `true`, enabling DNSSEC validation.
609    pub trust_anchor: Option<PathBuf>,
610    /// Exceptions to `deny_answer_addresses`. Networks listed here will be allowed, even if the IP address
611    /// matches a network in `deny_answer_addresses`.
612    pub allow_answers: Vec<IpNet>,
613    /// Networks listed here will be removed from any answers returned by an upstream server.
614    pub deny_answers: Vec<IpNet>,
615    /// Configure the EDNS UDP payload size used in queries.
616    ///
617    /// See [DnsRequestOptions::edns_payload_len][crate::proto::op::DnsRequestOptions::edns_payload_len].
618    #[cfg_attr(feature = "serde", serde(default = "default_edns_payload_len"))]
619    pub edns_payload_len: u16,
620    /// Report the IP of the name server for query result metrics.
621    ///
622    /// When `false`, metrics are aggregated under a static "aggregate" address label to avoid
623    /// cardinality blowup. For this reason, you might want to leave this disabled when querying a
624    /// large or unbounded set of DNS servers.
625    #[cfg_attr(feature = "serde", serde(default))]
626    #[cfg(feature = "metrics")]
627    pub enable_per_name_server_metrics: bool,
628}
629
630impl ResolverOpts {
631    pub(crate) fn answer_address_filter(&self) -> AccessControlSet {
632        let name = "resolver_answer_filter";
633        AccessControlSetBuilder::new(name)
634            .allow(self.allow_answers.iter())
635            .deny(self.deny_answers.iter())
636            .build()
637            .inspect_err(|err| warn!("{err}"))
638            .unwrap_or_else(|_| AccessControlSet::empty(name))
639    }
640}
641
642impl Default for ResolverOpts {
643    /// Default values for the Resolver configuration.
644    ///
645    /// This follows the resolv.conf defaults as defined in the [Linux man pages](https://man7.org/linux/man-pages/man5/resolv.conf.5.html)
646    fn default() -> Self {
647        Self {
648            ndots: default_ndots(),
649            timeout: default_timeout(),
650            attempts: default_attempts(),
651            edns0: true,
652            #[cfg(feature = "__dnssec")]
653            validate: false,
654            ip_strategy: LookupIpStrategy::default(),
655            cache_size: default_cache_size(),
656            use_hosts_file: ResolveHosts::default(),
657            positive_min_ttl: None,
658            negative_min_ttl: None,
659            positive_max_ttl: None,
660            negative_max_ttl: None,
661            num_concurrent_reqs: default_num_concurrent_reqs(),
662            max_active_requests: default_max_active_requests(),
663
664            // Defaults to `true` to match the behavior of dig and nslookup.
665            preserve_intermediates: default_preserve_intermediates(),
666
667            try_tcp_on_error: false,
668            server_ordering_strategy: ServerOrderingStrategy::default(),
669            recursion_desired: default_recursion_desired(),
670            avoid_local_udp_ports: Arc::default(),
671            os_port_selection: false,
672            case_randomization: false,
673            trust_anchor: None,
674            allow_answers: vec![],
675            deny_answers: vec![],
676            edns_payload_len: default_edns_payload_len(),
677            #[cfg(feature = "metrics")]
678            enable_per_name_server_metrics: false,
679        }
680    }
681}
682
683fn default_ndots() -> usize {
684    1
685}
686
687fn default_timeout() -> Duration {
688    Duration::from_secs(5)
689}
690
691fn default_attempts() -> usize {
692    2
693}
694
695fn default_cache_size() -> u64 {
696    8_192
697}
698
699fn default_num_concurrent_reqs() -> usize {
700    2
701}
702
703fn default_max_active_requests() -> usize {
704    32
705}
706
707fn default_preserve_intermediates() -> bool {
708    true
709}
710
711fn default_recursion_desired() -> bool {
712    true
713}
714
715fn default_edns_payload_len() -> u16 {
716    DEFAULT_MAX_PAYLOAD_LEN
717}
718
719/// The lookup ip strategy
720#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
721#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
722pub enum LookupIpStrategy {
723    /// Only query for A (Ipv4) records
724    Ipv4Only,
725    /// Only query for AAAA (Ipv6) records
726    Ipv6Only,
727    /// Query for A and AAAA in parallel, ordering A before AAAA
728    Ipv4AndIpv6,
729    /// Query for AAAA and A in parallel, ordering AAAA before A
730    #[default]
731    Ipv6AndIpv4,
732    /// Query for Ipv6 if that fails, query for Ipv4
733    Ipv6thenIpv4,
734    /// Query for Ipv4 if that fails, query for Ipv6 (default)
735    Ipv4thenIpv6,
736}
737
738/// The strategy for establishing the query order of name servers in a pool.
739#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
740#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
741#[non_exhaustive]
742pub enum ServerOrderingStrategy {
743    /// Servers are ordered based on collected query statistics. The ordering
744    /// may vary over time.
745    #[default]
746    QueryStatistics,
747    /// The order provided to the resolver is used. The ordering does not vary
748    /// over time.
749    UserProvidedOrder,
750    /// The order of servers is rotated in a round-robin fashion. This is useful for
751    /// load balancing and ensuring that all servers are used evenly.
752    RoundRobin,
753}
754
755/// Whether the system hosts file should be respected by the resolver.
756#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
757#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
758pub enum ResolveHosts {
759    /// Always attempt to look up IP addresses from the system hosts file.
760    /// If the hostname cannot be found, query the DNS.
761    Always,
762    /// The DNS will always be queried.
763    Never,
764    /// Use local resolver configurations only when this resolver is not used in
765    /// a DNS forwarder. This is the default.
766    #[default]
767    Auto,
768}
769
770/// Configuration for enabling RFC 9539 opportunistic encryption.
771///
772/// Controls how a recursive resolver probes name servers to discover if they support
773/// encrypted transports.
774#[derive(Debug, Clone, Default, Eq, PartialEq)]
775#[cfg_attr(
776    feature = "serde",
777    derive(Serialize, Deserialize),
778    serde(rename_all = "snake_case")
779)]
780#[non_exhaustive]
781pub enum OpportunisticEncryption {
782    /// Opportunistic encryption will not be performed.
783    #[default]
784    Disabled,
785    /// Opportunistic encryption will be performed.
786    #[cfg(any(feature = "__tls", feature = "__quic"))]
787    Enabled {
788        /// Configuration parameters for opportunistic encryption.
789        #[cfg_attr(feature = "serde", serde(flatten))]
790        config: OpportunisticEncryptionConfig,
791    },
792}
793
794impl OpportunisticEncryption {
795    #[cfg(all(
796        feature = "toml",
797        feature = "serde",
798        any(feature = "__tls", feature = "__quic")
799    ))]
800    pub(super) fn persisted_state(&self) -> Result<Option<NameServerTransportState>, String> {
801        let OpportunisticEncryption::Enabled {
802            config:
803                OpportunisticEncryptionConfig {
804                    persistence: Some(OpportunisticEncryptionPersistence { path, .. }),
805                    ..
806                },
807        } = self
808        else {
809            return Ok(None);
810        };
811
812        let state = match fs::read_to_string(path) {
813            Ok(toml_content) => toml::from_str(&toml_content).map_err(|e| {
814                format!(
815                    "failed to parse opportunistic encryption state TOML file: {file_path}: {e}",
816                    file_path = path.display()
817                )
818            })?,
819            Err(e) if e.kind() == io::ErrorKind::NotFound => {
820                info!(
821                    state_file = %path.display(),
822                    "no pre-existing opportunistic encryption state TOML file, starting with default state",
823                );
824                NameServerTransportState::default()
825            }
826            Err(e) => {
827                return Err(format!(
828                    "failed to read opportunistic encryption state TOML file: {file_path}: {e}",
829                    file_path = path.display()
830                ));
831            }
832        };
833
834        debug!(
835            path = %path.display(),
836            nameserver_count = state.nameserver_count(),
837            "loaded opportunistic encryption state"
838        );
839
840        Ok(Some(state))
841    }
842
843    /// Returns true if opportunistic encryption is enabled.
844    pub fn is_enabled(&self) -> bool {
845        match self {
846            Self::Disabled => false,
847            #[cfg(any(feature = "__tls", feature = "__quic"))]
848            Self::Enabled { .. } => true,
849        }
850    }
851
852    /// Returns the maximum number of concurrent probes if opportunistic encrypt is enabled.
853    pub fn max_concurrent_probes(&self) -> Option<u8> {
854        match self {
855            Self::Disabled => None,
856            #[cfg(any(feature = "__tls", feature = "__quic"))]
857            Self::Enabled { config, .. } => Some(config.max_concurrent_probes),
858        }
859    }
860}
861
862/// Configuration parameters for opportunistic encryption.
863#[derive(Debug, Clone, Eq, PartialEq)]
864#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
865#[cfg_attr(feature = "serde", serde(default, deny_unknown_fields))]
866pub struct OpportunisticEncryptionConfig {
867    /// How long the recursive resolver remembers a successful encrypted transport connection.
868    #[cfg_attr(
869        feature = "serde",
870        serde(default = "default_persistence_period", with = "duration")
871    )]
872    pub persistence_period: Duration,
873
874    /// How long the recursive resolver remembers a failed encrypted transport connection.
875    #[cfg_attr(
876        feature = "serde",
877        serde(default = "default_damping_period", with = "duration")
878    )]
879    pub damping_period: Duration,
880
881    /// Maximum number of concurrent opportunistic encryption probes.
882    #[cfg_attr(feature = "serde", serde(default = "default_max_concurrent_probes"))]
883    pub max_concurrent_probes: u8,
884
885    /// Optional configuration for persistence of opportunistic encryption probe state.
886    pub persistence: Option<OpportunisticEncryptionPersistence>,
887}
888
889impl Default for OpportunisticEncryptionConfig {
890    fn default() -> Self {
891        Self {
892            persistence_period: default_persistence_period(),
893            damping_period: default_damping_period(),
894            max_concurrent_probes: default_max_concurrent_probes(),
895            persistence: None,
896        }
897    }
898}
899
900/// The RFC 9539 suggested default for the resolver persistence period.
901fn default_persistence_period() -> Duration {
902    Duration::from_secs(60 * 60 * 24 * 3) // 3 days
903}
904
905/// The RFC 9539 suggested default for the resolver damping period.
906fn default_damping_period() -> Duration {
907    Duration::from_secs(24 * 60 * 60) // 1 day
908}
909
910/// A conservative default for the maximum number of in-flight opportunistic probe requests.
911fn default_max_concurrent_probes() -> u8 {
912    10
913}
914
915#[derive(Debug, Clone, Eq, PartialEq)]
916#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
917#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
918/// Configuration for persistence of opportunistic encryption probe state.
919pub struct OpportunisticEncryptionPersistence {
920    /// Path to a TOML state file that may be used for saving/loading opportunistic encryption state.
921    pub path: PathBuf,
922
923    /// Interval after which opportunistic encryption state is periodically saved to `path`.
924    #[cfg_attr(
925        feature = "serde",
926        serde(default = "default_save_interval", with = "duration")
927    )]
928    pub save_interval: Duration,
929}
930
931#[cfg(feature = "serde")]
932fn default_save_interval() -> Duration {
933    Duration::from_secs(60 * 10) // 10 minutes
934}
935
936/// Google Public DNS configuration.
937///
938/// Please see Google's [privacy statement](https://developers.google.com/speed/public-dns/privacy)
939/// for important information about what they track, many ISP's track similar information in DNS.
940/// To use the system configuration see: `Resolver::from_system_conf`.
941pub const GOOGLE: ServerGroup<'static> = ServerGroup {
942    ips: &[
943        IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)),
944        IpAddr::V4(Ipv4Addr::new(8, 8, 4, 4)),
945        IpAddr::V6(Ipv6Addr::new(0x2001, 0x4860, 0x4860, 0, 0, 0, 0, 0x8888)),
946        IpAddr::V6(Ipv6Addr::new(0x2001, 0x4860, 0x4860, 0, 0, 0, 0, 0x8844)),
947    ],
948    server_name: "dns.google",
949    path: "/dns-query",
950};
951
952/// Cloudflare's 1.1.1.1 DNS service configuration.
953///
954/// See <https://www.cloudflare.com/dns/> for more information.
955pub const CLOUDFLARE: ServerGroup<'static> = ServerGroup {
956    ips: &[
957        IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)),
958        IpAddr::V4(Ipv4Addr::new(1, 0, 0, 1)),
959        IpAddr::V6(Ipv6Addr::new(0x2606, 0x4700, 0x4700, 0, 0, 0, 0, 0x1111)),
960        IpAddr::V6(Ipv6Addr::new(0x2606, 0x4700, 0x4700, 0, 0, 0, 0, 0x1001)),
961    ],
962    server_name: "cloudflare-dns.com",
963    path: "/dns-query",
964};
965
966/// The Quad9 DNS service configuration.
967///
968/// See <https://www.quad9.net/faq/> for more information.
969pub const QUAD9: ServerGroup<'static> = ServerGroup {
970    ips: &[
971        IpAddr::V4(Ipv4Addr::new(9, 9, 9, 9)),
972        IpAddr::V4(Ipv4Addr::new(149, 112, 112, 112)),
973        IpAddr::V6(Ipv6Addr::new(0x2620, 0x00fe, 0, 0, 0, 0, 0, 0x00fe)),
974        IpAddr::V6(Ipv6Addr::new(0x2620, 0x00fe, 0, 0, 0, 0, 0, 0x0009)),
975    ],
976    server_name: "dns.quad9.net",
977    path: "/dns-query",
978};
979
980/// A group of DNS servers.
981#[derive(Clone, Copy, Debug)]
982pub struct ServerGroup<'a> {
983    /// IP addresses of the DNS servers in this group.
984    pub ips: &'a [IpAddr],
985    /// The TLS server name to use for servers.
986    pub server_name: &'a str,
987    /// The query path to use for HTTP queries.
988    pub path: &'a str,
989}
990
991impl<'a> ServerGroup<'a> {
992    /// Create an iterator with `NameServerConfig` for each IP address in the group.
993    pub fn udp_and_tcp(&self) -> impl Iterator<Item = NameServerConfig> + 'a {
994        self.ips.iter().map(|&ip| {
995            NameServerConfig::new(
996                ip,
997                true,
998                vec![ConnectionConfig::udp(), ConnectionConfig::tcp()],
999            )
1000        })
1001    }
1002
1003    /// Create an iterator with `NameServerConfig` for each IP address in the group.
1004    pub fn udp(&self) -> impl Iterator<Item = NameServerConfig> + 'a {
1005        self.ips
1006            .iter()
1007            .map(|&ip| NameServerConfig::new(ip, true, vec![ConnectionConfig::udp()]))
1008    }
1009
1010    /// Create an iterator with `NameServerConfig` for each IP address in the group.
1011    pub fn tcp(&self) -> impl Iterator<Item = NameServerConfig> + 'a {
1012        self.ips
1013            .iter()
1014            .map(|&ip| NameServerConfig::new(ip, true, vec![ConnectionConfig::tcp()]))
1015    }
1016
1017    /// Create an iterator with `NameServerConfig` for each IP address in the group.
1018    #[cfg(feature = "__tls")]
1019    pub fn tls(&self) -> impl Iterator<Item = NameServerConfig> + 'a {
1020        let this = *self;
1021        self.ips.iter().map(move |&ip| {
1022            NameServerConfig::new(
1023                ip,
1024                true,
1025                vec![ConnectionConfig::tls(Arc::from(this.server_name))],
1026            )
1027        })
1028    }
1029
1030    /// Create an iterator with `NameServerConfig` for each IP address in the group.
1031    #[cfg(feature = "__https")]
1032    pub fn https(&self) -> impl Iterator<Item = NameServerConfig> + 'a {
1033        let this = *self;
1034        self.ips.iter().map(move |&ip| {
1035            NameServerConfig::new(
1036                ip,
1037                true,
1038                vec![ConnectionConfig::https(
1039                    Arc::from(this.server_name),
1040                    Some(Arc::from(this.path)),
1041                )],
1042            )
1043        })
1044    }
1045
1046    /// Create an iterator with `NameServerConfig` for each IP address in the group.
1047    #[cfg(feature = "__quic")]
1048    pub fn quic(&self) -> impl Iterator<Item = NameServerConfig> + 'a {
1049        let this = *self;
1050        self.ips.iter().map(move |&ip| {
1051            NameServerConfig::new(
1052                ip,
1053                true,
1054                vec![ConnectionConfig::quic(Arc::from(this.server_name))],
1055            )
1056        })
1057    }
1058
1059    /// Create an iterator with `NameServerConfig` for each IP address in the group.
1060    #[cfg(feature = "__h3")]
1061    pub fn h3(&self) -> impl Iterator<Item = NameServerConfig> + 'a {
1062        let this = *self;
1063        self.ips.iter().map(move |&ip| {
1064            NameServerConfig::new(
1065                ip,
1066                true,
1067                vec![ConnectionConfig::h3(
1068                    Arc::from(this.server_name),
1069                    Some(Arc::from(this.path)),
1070                )],
1071            )
1072        })
1073    }
1074}
1075
1076#[cfg(feature = "serde")]
1077pub(crate) mod duration {
1078    use std::time::Duration;
1079
1080    use serde::{Deserialize, Deserializer, Serialize, Serializer};
1081
1082    /// This is an alternate serialization function for a [`Duration`] that emits a single number,
1083    /// representing the number of seconds, instead of a struct with `secs` and `nanos` fields.
1084    pub(super) fn serialize<S: Serializer>(
1085        duration: &Duration,
1086        serializer: S,
1087    ) -> Result<S::Ok, S::Error> {
1088        duration.as_secs().serialize(serializer)
1089    }
1090
1091    /// This is an alternate deserialization function for a [`Duration`] that expects a single number,
1092    /// representing the number of seconds, instead of a struct with `secs` and `nanos` fields.
1093    pub(crate) fn deserialize<'de, D: Deserializer<'de>>(
1094        deserializer: D,
1095    ) -> Result<Duration, D::Error> {
1096        Ok(Duration::from_secs(u64::deserialize(deserializer)?))
1097    }
1098}
1099
1100#[cfg(feature = "serde")]
1101pub(crate) mod duration_opt {
1102    use std::time::Duration;
1103
1104    use serde::{Deserialize, Deserializer, Serialize, Serializer};
1105
1106    /// This is an alternate serialization function for an optional [`Duration`] that emits a single
1107    /// number, representing the number of seconds, instead of a struct with `secs` and `nanos` fields.
1108    pub(super) fn serialize<S: Serializer>(
1109        duration: &Option<Duration>,
1110        serializer: S,
1111    ) -> Result<S::Ok, S::Error> {
1112        struct Wrapper<'a>(&'a Duration);
1113
1114        impl Serialize for Wrapper<'_> {
1115            fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1116                super::duration::serialize(self.0, serializer)
1117            }
1118        }
1119
1120        match duration {
1121            Some(duration) => serializer.serialize_some(&Wrapper(duration)),
1122            None => serializer.serialize_none(),
1123        }
1124    }
1125
1126    /// This is an alternate deserialization function for an optional [`Duration`] that expects a single
1127    /// number, representing the number of seconds, instead of a struct with `secs` and `nanos` fields.
1128    pub(crate) fn deserialize<'de, D: Deserializer<'de>>(
1129        deserializer: D,
1130    ) -> Result<Option<Duration>, D::Error> {
1131        Ok(Option::<u64>::deserialize(deserializer)?.map(Duration::from_secs))
1132    }
1133}
1134
1135#[cfg(all(test, feature = "serde"))]
1136mod tests {
1137    use super::*;
1138
1139    #[cfg(feature = "serde")]
1140    #[test]
1141    fn default_opts() {
1142        let code = ResolverOpts::default();
1143        let json = serde_json::from_str::<ResolverOpts>("{}").unwrap();
1144        assert_eq!(code.ndots, json.ndots);
1145        assert_eq!(code.timeout, json.timeout);
1146        assert_eq!(code.attempts, json.attempts);
1147        assert_eq!(code.edns0, json.edns0);
1148        #[cfg(feature = "__dnssec")]
1149        assert_eq!(code.validate, json.validate);
1150        assert_eq!(code.ip_strategy, json.ip_strategy);
1151        assert_eq!(code.cache_size, json.cache_size);
1152        assert_eq!(code.use_hosts_file, json.use_hosts_file);
1153        assert_eq!(code.positive_min_ttl, json.positive_min_ttl);
1154        assert_eq!(code.negative_min_ttl, json.negative_min_ttl);
1155        assert_eq!(code.positive_max_ttl, json.positive_max_ttl);
1156        assert_eq!(code.negative_max_ttl, json.negative_max_ttl);
1157        assert_eq!(code.num_concurrent_reqs, json.num_concurrent_reqs);
1158        assert_eq!(code.preserve_intermediates, json.preserve_intermediates);
1159        assert_eq!(code.try_tcp_on_error, json.try_tcp_on_error);
1160        assert_eq!(code.recursion_desired, json.recursion_desired);
1161        assert_eq!(code.server_ordering_strategy, json.server_ordering_strategy);
1162        assert_eq!(code.avoid_local_udp_ports, json.avoid_local_udp_ports);
1163        assert_eq!(code.os_port_selection, json.os_port_selection);
1164        assert_eq!(code.case_randomization, json.case_randomization);
1165        assert_eq!(code.trust_anchor, json.trust_anchor);
1166        #[cfg(feature = "metrics")]
1167        assert_eq!(
1168            code.enable_per_name_server_metrics,
1169            json.enable_per_name_server_metrics
1170        );
1171    }
1172}