trust_dns_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// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://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::fmt;
12use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
13use std::ops::{Deref, DerefMut};
14use std::time::Duration;
15
16#[cfg(feature = "dns-over-rustls")]
17use std::sync::Arc;
18
19use proto::rr::Name;
20#[cfg(feature = "dns-over-rustls")]
21use rustls::ClientConfig;
22
23#[cfg(all(feature = "serde-config", feature = "dns-over-rustls"))]
24use serde::{
25    de::{Deserialize as DeserializeT, Deserializer},
26    ser::{Serialize as SerializeT, Serializer},
27};
28
29/// Configuration for the upstream nameservers to use for resolution
30#[derive(Clone, Debug, PartialEq, Eq)]
31#[cfg_attr(feature = "serde-config", derive(Serialize, Deserialize))]
32pub struct ResolverConfig {
33    // base search domain
34    #[cfg_attr(feature = "serde-config", serde(default))]
35    domain: Option<Name>,
36    // search domains
37    #[cfg_attr(feature = "serde-config", serde(default))]
38    search: Vec<Name>,
39    // nameservers to use for resolution.
40    name_servers: NameServerConfigGroup,
41}
42
43impl ResolverConfig {
44    /// Creates a new empty configuration
45    pub fn new() -> Self {
46        Self {
47            // TODO: this should get the hostname and use the basename as the default
48            domain: None,
49            search: vec![],
50            name_servers: NameServerConfigGroup::new(),
51        }
52    }
53
54    /// Creates a default configuration, using `8.8.8.8`, `8.8.4.4` and `2001:4860:4860::8888`, `2001:4860:4860::8844` (thank you, Google).
55    ///
56    /// Please see Google's [privacy statement](https://developers.google.com/speed/public-dns/privacy) for important information about what they track, many ISP's track similar information in DNS. To use the system configuration see: `Resolver::from_system_conf` and `AsyncResolver::from_system_conf`
57    ///
58    /// NameServerConfigGroups can be combined to use a set of different providers, see `NameServerConfigGroup` and `ResolverConfig::from_parts`
59    pub fn google() -> Self {
60        Self {
61            // TODO: this should get the hostname and use the basename as the default
62            domain: None,
63            search: vec![],
64            name_servers: NameServerConfigGroup::google(),
65        }
66    }
67
68    /// Creates a default configuration, using `1.1.1.1`, `1.0.0.1` and `2606:4700:4700::1111`, `2606:4700:4700::1001` (thank you, Cloudflare).
69    ///
70    /// Please see: <https://www.cloudflare.com/dns/>
71    ///
72    /// NameServerConfigGroups can be combined to use a set of different providers, see `NameServerConfigGroup` and `ResolverConfig::from_parts`
73    pub fn cloudflare() -> Self {
74        Self {
75            // TODO: this should get the hostname and use the basename as the default
76            domain: None,
77            search: vec![],
78            name_servers: NameServerConfigGroup::cloudflare(),
79        }
80    }
81
82    /// Creates a configuration, using `1.1.1.1`, `1.0.0.1` and `2606:4700:4700::1111`, `2606:4700:4700::1001` (thank you, Cloudflare). This limits the registered connections to just TLS lookups
83    ///
84    /// Please see: <https://www.cloudflare.com/dns/>
85    ///
86    /// NameServerConfigGroups can be combined to use a set of different providers, see `NameServerConfigGroup` and `ResolverConfig::from_parts`
87    #[cfg(feature = "dns-over-tls")]
88    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-tls")))]
89    pub fn cloudflare_tls() -> Self {
90        Self {
91            // TODO: this should get the hostname and use the basename as the default
92            domain: None,
93            search: vec![],
94            name_servers: NameServerConfigGroup::cloudflare_tls(),
95        }
96    }
97
98    /// Creates a configuration, using `1.1.1.1`, `1.0.0.1` and `2606:4700:4700::1111`, `2606:4700:4700::1001` (thank you, Cloudflare). This limits the registered connections to just HTTPS lookups
99    ///
100    /// Please see: <https://www.cloudflare.com/dns/>
101    ///
102    /// NameServerConfigGroups can be combined to use a set of different providers, see `NameServerConfigGroup` and `ResolverConfig::from_parts`
103    #[cfg(feature = "dns-over-https")]
104    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-https")))]
105    pub fn cloudflare_https() -> Self {
106        Self {
107            // TODO: this should get the hostname and use the basename as the default
108            domain: None,
109            search: vec![],
110            name_servers: NameServerConfigGroup::cloudflare_https(),
111        }
112    }
113
114    /// Creates a configuration, using `9.9.9.9`, `149.112.112.112` and `2620:fe::fe`, `2620:fe::fe:9`, the "secure" variants of the quad9 settings (thank you, Quad9).
115    ///
116    /// Please see: <https://www.quad9.net/faq/>
117    ///
118    /// NameServerConfigGroups can be combined to use a set of different providers, see `NameServerConfigGroup` and `ResolverConfig::from_parts`
119    pub fn quad9() -> Self {
120        Self {
121            // TODO: this should get the hostname and use the basename as the default
122            domain: None,
123            search: vec![],
124            name_servers: NameServerConfigGroup::quad9(),
125        }
126    }
127
128    /// Creates a configuration, using `9.9.9.9`, `149.112.112.112` and `2620:fe::fe`, `2620:fe::fe:9`, the "secure" variants of the quad9 settings. This limits the registered connections to just TLS lookups
129    ///
130    /// Please see: <https://www.quad9.net/faq/>
131    ///
132    /// NameServerConfigGroups can be combined to use a set of different providers, see `NameServerConfigGroup` and `ResolverConfig::from_parts`
133    #[cfg(feature = "dns-over-tls")]
134    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-tls")))]
135    pub fn quad9_tls() -> Self {
136        Self {
137            // TODO: this should get the hostname and use the basename as the default
138            domain: None,
139            search: vec![],
140            name_servers: NameServerConfigGroup::quad9_tls(),
141        }
142    }
143
144    /// Creates a configuration, using `9.9.9.9`, `149.112.112.112` and `2620:fe::fe`, `2620:fe::fe:9`, the "secure" variants of the quad9 settings. This limits the registered connections to just HTTPS lookups
145    ///
146    /// Please see: <https://www.quad9.net/faq/>
147    ///
148    /// NameServerConfigGroups can be combined to use a set of different providers, see `NameServerConfigGroup` and `ResolverConfig::from_parts`
149    #[cfg(feature = "dns-over-https")]
150    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-https")))]
151    pub fn quad9_https() -> Self {
152        Self {
153            // TODO: this should get the hostname and use the basename as the default
154            domain: None,
155            search: vec![],
156            name_servers: NameServerConfigGroup::quad9_https(),
157        }
158    }
159
160    /// Create a ResolverConfig with all parts specified
161    ///
162    /// # Arguments
163    ///
164    /// * `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.
165    /// * `search` - additional search domains that are attempted if the `Name` is not found in `domain`, defaults to `vec![]`
166    /// * `name_servers` - set of name servers to use for lookups, defaults are Google: `8.8.8.8`, `8.8.4.4` and `2001:4860:4860::8888`, `2001:4860:4860::8844`
167    pub fn from_parts<G: Into<NameServerConfigGroup>>(
168        domain: Option<Name>,
169        search: Vec<Name>,
170        name_servers: G,
171    ) -> Self {
172        Self {
173            domain,
174            search,
175            name_servers: name_servers.into(),
176        }
177    }
178
179    /// Returns the local domain
180    ///
181    /// By default any names will be appended to all non-fully-qualified-domain names, and searched for after any ndots rules
182    pub fn domain(&self) -> Option<&Name> {
183        self.domain.as_ref()
184    }
185
186    /// Set the domain of the entity querying results.
187    pub fn set_domain(&mut self, domain: Name) {
188        self.domain = Some(domain.clone());
189        self.search = vec![domain];
190    }
191
192    /// Returns the search domains
193    ///
194    /// These will be queried after any local domain and then in the order of the set of search domains
195    pub fn search(&self) -> &[Name] {
196        &self.search
197    }
198
199    /// Add a search domain
200    pub fn add_search(&mut self, search: Name) {
201        self.search.push(search)
202    }
203
204    // TODO: consider allowing options per NameServer... like different timeouts?
205    /// Add the configuration for a name server
206    pub fn add_name_server(&mut self, name_server: NameServerConfig) {
207        self.name_servers.push(name_server);
208    }
209
210    /// Returns a reference to the name servers
211    pub fn name_servers(&self) -> &[NameServerConfig] {
212        &self.name_servers
213    }
214
215    /// return the associated TlsClientConfig
216    #[cfg(feature = "dns-over-rustls")]
217    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-rustls")))]
218    pub fn client_config(&self) -> &Option<TlsClientConfig> {
219        &self.name_servers.1
220    }
221
222    /// adds the `rustls::ClientConf` for every configured NameServer
223    /// of the Resolver.
224    ///
225    /// ```
226    /// use std::sync::Arc;
227    ///
228    /// use rustls::{ClientConfig, ProtocolVersion, RootCertStore, OwnedTrustAnchor};
229    /// use trust_dns_resolver::config::ResolverConfig;
230    /// use webpki_roots;
231    ///
232    /// let mut root_store = RootCertStore::empty();
233    /// root_store.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| {
234    ///     OwnedTrustAnchor::from_subject_spki_name_constraints(
235    ///         ta.subject,
236    ///         ta.spki,
237    ///         ta.name_constraints,
238    ///     )
239    /// }));
240    ///
241    /// let mut client_config = ClientConfig::builder()
242    ///     .with_safe_default_cipher_suites()
243    ///     .with_safe_default_kx_groups()
244    ///     .with_protocol_versions(&[&rustls::version::TLS12])
245    ///     .unwrap()
246    ///     .with_root_certificates(root_store)
247    ///     .with_no_client_auth();
248    ///
249    /// let mut resolver_config = ResolverConfig::quad9_tls();
250    /// resolver_config.set_tls_client_config(Arc::new(client_config));
251    /// ```
252    #[cfg(feature = "dns-over-rustls")]
253    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-rustls")))]
254    pub fn set_tls_client_config(&mut self, client_config: Arc<ClientConfig>) {
255        self.name_servers = self.name_servers.clone().with_client_config(client_config);
256    }
257}
258
259impl Default for ResolverConfig {
260    /// Creates a default configuration, using `8.8.8.8`, `8.8.4.4` and `2001:4860:4860::8888`, `2001:4860:4860::8844` (thank you, Google).
261    ///
262    /// Please see Google's [privacy statement](https://developers.google.com/speed/public-dns/privacy) for important information about what they track, many ISP's track similar information in DNS. To use the system configuration see: `Resolver::from_system_conf` and `AsyncResolver::from_system_conf`
263    fn default() -> Self {
264        Self::google()
265    }
266}
267
268/// The protocol on which a NameServer should be communicated with
269#[derive(Clone, Copy, Debug, Eq, PartialEq)]
270#[cfg_attr(
271    feature = "serde-config",
272    derive(Serialize, Deserialize),
273    serde(rename_all = "lowercase")
274)]
275#[non_exhaustive]
276pub enum Protocol {
277    /// UDP is the traditional DNS port, this is generally the correct choice
278    Udp,
279    /// TCP can be used for large queries, but not all NameServers support it
280    Tcp,
281    /// Tls for DNS over TLS
282    #[cfg(feature = "dns-over-tls")]
283    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-tls")))]
284    Tls,
285    /// Https for DNS over HTTPS
286    #[cfg(feature = "dns-over-https")]
287    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-https")))]
288    Https,
289    /// QUIC for DNS over QUIC
290    #[cfg(feature = "dns-over-quic")]
291    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-quic")))]
292    Quic,
293    /// mDNS protocol for performing multicast lookups
294    #[cfg(feature = "mdns")]
295    #[cfg_attr(docsrs, doc(cfg(feature = "mdns")))]
296    Mdns,
297}
298
299impl fmt::Display for Protocol {
300    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
301        let protocol = match self {
302            Self::Udp => "udp",
303            Self::Tcp => "tcp",
304            #[cfg(feature = "dns-over-tls")]
305            Self::Tls => "tls",
306            #[cfg(feature = "dns-over-https")]
307            Self::Https => "https",
308            #[cfg(feature = "dns-over-quic")]
309            Self::Quic => "quic",
310            #[cfg(feature = "mdns")]
311            Self::Mdns => "mdns",
312        };
313
314        f.write_str(protocol)
315    }
316}
317
318impl Protocol {
319    /// Returns true if this is a datagram oriented protocol, e.g. UDP
320    pub fn is_datagram(self) -> bool {
321        match self {
322            Self::Udp => true,
323            Self::Tcp => false,
324            #[cfg(feature = "dns-over-tls")]
325            Self::Tls => false,
326            #[cfg(feature = "dns-over-https")]
327            Self::Https => false,
328            // TODO: if you squint, this is true...
329            #[cfg(feature = "dns-over-quic")]
330            Self::Quic => true,
331            #[cfg(feature = "mdns")]
332            Self::Mdns => true,
333        }
334    }
335
336    /// Returns true if this is a stream oriented protocol, e.g. TCP
337    pub fn is_stream(self) -> bool {
338        !self.is_datagram()
339    }
340
341    /// Is this an encrypted protocol, i.e. TLS or HTTPS
342    pub fn is_encrypted(self) -> bool {
343        match self {
344            Self::Udp => false,
345            Self::Tcp => false,
346            #[cfg(feature = "dns-over-tls")]
347            Self::Tls => true,
348            #[cfg(feature = "dns-over-https")]
349            Self::Https => true,
350            #[cfg(feature = "dns-over-quic")]
351            Self::Quic => true,
352            #[cfg(feature = "mdns")]
353            Self::Mdns => false,
354        }
355    }
356}
357
358impl Default for Protocol {
359    /// Default protocol should be UDP, which is supported by all DNS servers
360    fn default() -> Self {
361        Self::Udp
362    }
363}
364
365/// a compatibility wrapper around rustls
366/// ClientConfig
367#[cfg(feature = "dns-over-rustls")]
368#[cfg_attr(docsrs, doc(cfg(feature = "dns-over-rustls")))]
369#[derive(Clone)]
370pub struct TlsClientConfig(pub Arc<ClientConfig>);
371
372#[cfg(feature = "dns-over-rustls")]
373impl std::cmp::PartialEq for TlsClientConfig {
374    fn eq(&self, other: &Self) -> bool {
375        Arc::ptr_eq(&self.0, &other.0)
376    }
377}
378
379#[cfg(feature = "dns-over-rustls")]
380impl std::cmp::Eq for TlsClientConfig {}
381
382#[cfg(feature = "dns-over-rustls")]
383impl std::fmt::Debug for TlsClientConfig {
384    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
385        write!(f, "rustls client config")
386    }
387}
388
389/// Configuration for the NameServer
390#[derive(Clone, Debug, Eq, PartialEq)]
391#[cfg_attr(feature = "serde-config", derive(Serialize, Deserialize))]
392pub struct NameServerConfig {
393    /// The address which the DNS NameServer is registered at.
394    pub socket_addr: SocketAddr,
395    /// The protocol to use when communicating with the NameServer.
396    #[cfg_attr(feature = "serde-config", serde(default))]
397    pub protocol: Protocol,
398    /// SPKI name, only relevant for TLS connections
399    #[cfg_attr(feature = "serde-config", serde(default))]
400    pub tls_dns_name: Option<String>,
401    /// Whether to trust `NXDOMAIN` responses from upstream nameservers.
402    ///
403    /// When this is `true`, and an empty `NXDOMAIN` response is received, the
404    /// query will not be retried against other configured name servers.
405    ///
406    /// (On an empty `NoError` response, or a response with any other error
407    /// response code, the query will still be retried regardless of this
408    /// configuration setting.)
409    ///
410    /// Defaults to false.
411    #[cfg_attr(feature = "serde-config", serde(default))]
412    pub trust_nx_responses: bool,
413    #[cfg(feature = "dns-over-rustls")]
414    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-rustls")))]
415    #[cfg_attr(feature = "serde-config", serde(skip))]
416    /// optional configuration for the tls client
417    pub tls_config: Option<TlsClientConfig>,
418    /// The client address (IP and port) to use for connecting to the server.
419    pub bind_addr: Option<SocketAddr>,
420}
421
422impl NameServerConfig {
423    /// Constructs a Nameserver configuration with some basic defaults
424    pub fn new(socket_addr: SocketAddr, protocol: Protocol) -> Self {
425        Self {
426            socket_addr,
427            protocol,
428            trust_nx_responses: true,
429            tls_dns_name: None,
430            #[cfg(feature = "dns-over-rustls")]
431            tls_config: None,
432            bind_addr: None,
433        }
434    }
435}
436
437impl fmt::Display for NameServerConfig {
438    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
439        write!(f, "{}:", self.protocol)?;
440
441        if let Some(ref tls_dns_name) = self.tls_dns_name {
442            write!(f, "{}@", tls_dns_name)?;
443        }
444
445        write!(f, "{}", self.socket_addr)
446    }
447}
448
449/// A set of name_servers to associate with a [`ResolverConfig`].
450#[derive(Clone, Debug, Eq, PartialEq)]
451#[cfg_attr(
452    all(feature = "serde-config", not(feature = "dns-over-rustls")),
453    derive(Serialize, Deserialize)
454)]
455pub struct NameServerConfigGroup(
456    Vec<NameServerConfig>,
457    #[cfg(feature = "dns-over-rustls")] Option<TlsClientConfig>,
458);
459
460#[cfg(all(feature = "serde-config", feature = "dns-over-rustls"))]
461impl SerializeT for NameServerConfigGroup {
462    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
463    where
464        S: Serializer,
465    {
466        self.0.serialize(serializer)
467    }
468}
469
470#[cfg(all(feature = "serde-config", feature = "dns-over-rustls"))]
471impl<'de> DeserializeT<'de> for NameServerConfigGroup {
472    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
473    where
474        D: Deserializer<'de>,
475    {
476        Vec::deserialize(deserializer).map(|nameservers| Self(nameservers, None))
477    }
478}
479
480impl NameServerConfigGroup {
481    /// Creates a new `NameServerConfigGroup` with a default size of 2
482    pub fn new() -> Self {
483        // this might be a nice opportunity for SmallVec
484        //   most name_server configs will be 2.
485        Self::with_capacity(2)
486    }
487
488    /// Creates a new `NameServiceConfigGroup` with the specified capacity
489    pub fn with_capacity(capacity: usize) -> Self {
490        Self(
491            Vec::with_capacity(capacity),
492            #[cfg(feature = "dns-over-rustls")]
493            None,
494        )
495    }
496
497    /// Returns the inner vec of configs
498    pub fn into_inner(self) -> Vec<NameServerConfig> {
499        self.0
500    }
501
502    /// Configure a NameServer address and port
503    ///
504    /// This will create UDP and TCP connections, using the same port.
505    pub fn from_ips_clear(ips: &[IpAddr], port: u16, trust_nx_responses: bool) -> Self {
506        let mut name_servers = Self::with_capacity(ips.len());
507
508        for ip in ips {
509            let udp = NameServerConfig {
510                socket_addr: SocketAddr::new(*ip, port),
511                protocol: Protocol::Udp,
512                tls_dns_name: None,
513                trust_nx_responses,
514                #[cfg(feature = "dns-over-rustls")]
515                tls_config: None,
516                bind_addr: None,
517            };
518            let tcp = NameServerConfig {
519                socket_addr: SocketAddr::new(*ip, port),
520                protocol: Protocol::Tcp,
521                tls_dns_name: None,
522                trust_nx_responses,
523                #[cfg(feature = "dns-over-rustls")]
524                tls_config: None,
525                bind_addr: None,
526            };
527
528            name_servers.push(udp);
529            name_servers.push(tcp);
530        }
531
532        name_servers
533    }
534
535    #[cfg(any(feature = "dns-over-tls", feature = "dns-over-https"))]
536    fn from_ips_encrypted(
537        ips: &[IpAddr],
538        port: u16,
539        tls_dns_name: String,
540        protocol: Protocol,
541        trust_nx_responses: bool,
542    ) -> Self {
543        assert!(protocol.is_encrypted());
544
545        let mut name_servers = Self::with_capacity(ips.len());
546
547        for ip in ips {
548            let config = NameServerConfig {
549                socket_addr: SocketAddr::new(*ip, port),
550                protocol,
551                tls_dns_name: Some(tls_dns_name.clone()),
552                trust_nx_responses,
553                #[cfg(feature = "dns-over-rustls")]
554                tls_config: None,
555                bind_addr: None,
556            };
557
558            name_servers.push(config);
559        }
560
561        name_servers
562    }
563
564    /// Configure a NameServer address and port for DNS-over-TLS
565    ///
566    /// This will create a TLS connections.
567    #[cfg(feature = "dns-over-tls")]
568    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-tls")))]
569    pub fn from_ips_tls(
570        ips: &[IpAddr],
571        port: u16,
572        tls_dns_name: String,
573        trust_nx_responses: bool,
574    ) -> Self {
575        Self::from_ips_encrypted(ips, port, tls_dns_name, Protocol::Tls, trust_nx_responses)
576    }
577
578    /// Configure a NameServer address and port for DNS-over-HTTPS
579    ///
580    /// This will create a HTTPS connections.
581    #[cfg(feature = "dns-over-https")]
582    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-https")))]
583    pub fn from_ips_https(
584        ips: &[IpAddr],
585        port: u16,
586        tls_dns_name: String,
587        trust_nx_responses: bool,
588    ) -> Self {
589        Self::from_ips_encrypted(ips, port, tls_dns_name, Protocol::Https, trust_nx_responses)
590    }
591
592    /// Creates a default configuration, using `8.8.8.8`, `8.8.4.4` and `2001:4860:4860::8888`, `2001:4860:4860::8844` (thank you, Google).
593    ///
594    /// Please see Google's [privacy statement](https://developers.google.com/speed/public-dns/privacy) for important information about what they track, many ISP's track similar information in DNS. To use the system configuration see: `Resolver::from_system_conf` and `AsyncResolver::from_system_conf`
595    pub fn google() -> Self {
596        Self::from_ips_clear(GOOGLE_IPS, 53, true)
597    }
598
599    /// Creates a default configuration, using `8.8.8.8`, `8.8.4.4` and `2001:4860:4860::8888`, `2001:4860:4860::8844` (thank you, Google). This limits the registered connections to just HTTPS lookups
600    ///
601    /// Please see Google's [privacy statement](https://developers.google.com/speed/public-dns/privacy) for important information about what they track, many ISP's track similar information in DNS. To use the system configuration see: `Resolver::from_system_conf` and `AsyncResolver::from_system_conf`
602    #[cfg(feature = "dns-over-https")]
603    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-https")))]
604    pub fn google_https() -> Self {
605        Self::from_ips_https(GOOGLE_IPS, 443, "dns.google".to_string(), true)
606    }
607
608    /// Creates a default configuration, using `1.1.1.1`, `1.0.0.1` and `2606:4700:4700::1111`, `2606:4700:4700::1001` (thank you, Cloudflare).
609    ///
610    /// Please see: <https://www.cloudflare.com/dns/>
611    pub fn cloudflare() -> Self {
612        Self::from_ips_clear(CLOUDFLARE_IPS, 53, true)
613    }
614
615    /// Creates a configuration, using `1.1.1.1`, `1.0.0.1` and `2606:4700:4700::1111`, `2606:4700:4700::1001` (thank you, Cloudflare). This limits the registered connections to just TLS lookups
616    ///
617    /// Please see: <https://www.cloudflare.com/dns/>
618    #[cfg(feature = "dns-over-tls")]
619    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-tls")))]
620    pub fn cloudflare_tls() -> Self {
621        Self::from_ips_tls(CLOUDFLARE_IPS, 853, "cloudflare-dns.com".to_string(), true)
622    }
623
624    /// Creates a configuration, using `1.1.1.1`, `1.0.0.1` and `2606:4700:4700::1111`, `2606:4700:4700::1001` (thank you, Cloudflare). This limits the registered connections to just HTTPS lookups
625    ///
626    /// Please see: <https://www.cloudflare.com/dns/>
627    #[cfg(feature = "dns-over-https")]
628    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-https")))]
629    pub fn cloudflare_https() -> Self {
630        Self::from_ips_https(CLOUDFLARE_IPS, 443, "cloudflare-dns.com".to_string(), true)
631    }
632
633    /// Creates a configuration, using `9.9.9.9`, `149.112.112.112` and `2620:fe::fe`, `2620:fe::fe:9`, the "secure" variants of the quad9 settings (thank you, Quad9).
634    ///
635    /// Please see: <https://www.quad9.net/faq/>
636    pub fn quad9() -> Self {
637        Self::from_ips_clear(QUAD9_IPS, 53, true)
638    }
639
640    /// Creates a configuration, using `9.9.9.9`, `149.112.112.112` and `2620:fe::fe`, `2620:fe::fe:9`, the "secure" variants of the quad9 settings. This limits the registered connections to just TLS lookups
641    ///
642    /// Please see: <https://www.quad9.net/faq/>
643    #[cfg(feature = "dns-over-tls")]
644    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-tls")))]
645    pub fn quad9_tls() -> Self {
646        Self::from_ips_tls(QUAD9_IPS, 853, "dns.quad9.net".to_string(), true)
647    }
648
649    /// Creates a configuration, using `9.9.9.9`, `149.112.112.112` and `2620:fe::fe`, `2620:fe::fe:9`, the "secure" variants of the quad9 settings. This limits the registered connections to just HTTPS lookups
650    ///
651    /// Please see: <https://www.quad9.net/faq/>
652    #[cfg(feature = "dns-over-https")]
653    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-https")))]
654    pub fn quad9_https() -> Self {
655        Self::from_ips_https(QUAD9_IPS, 443, "dns.quad9.net".to_string(), true)
656    }
657
658    /// Merges this set of [`NameServerConfig`]s with the other
659    ///
660    /// ```
661    /// use std::net::{SocketAddr, Ipv4Addr};
662    /// use trust_dns_resolver::config::NameServerConfigGroup;
663    ///
664    /// let mut group = NameServerConfigGroup::google();
665    /// group.merge(NameServerConfigGroup::cloudflare());
666    /// group.merge(NameServerConfigGroup::quad9());
667    ///
668    /// assert!(group.iter().any(|c| c.socket_addr == SocketAddr::new(Ipv4Addr::new(8, 8, 8, 8).into(), 53)));
669    /// assert!(group.iter().any(|c| c.socket_addr == SocketAddr::new(Ipv4Addr::new(1, 1, 1, 1).into(), 53)));
670    /// assert!(group.iter().any(|c| c.socket_addr == SocketAddr::new(Ipv4Addr::new(9, 9, 9, 9).into(), 53)));
671    /// ```
672    pub fn merge(&mut self, mut other: Self) {
673        #[cfg(not(feature = "dns-over-rustls"))]
674        {
675            self.append(&mut other);
676        }
677        #[cfg(feature = "dns-over-rustls")]
678        {
679            self.0.append(&mut other);
680        }
681    }
682
683    /// add a [`rustls::ClientConfig`]
684    #[cfg(feature = "dns-over-rustls")]
685    #[cfg_attr(docsrs, doc(cfg(feature = "dns-over-rustls")))]
686    pub fn with_client_config(self, client_config: Arc<ClientConfig>) -> Self {
687        Self(self.0, Some(TlsClientConfig(client_config)))
688    }
689
690    /// Sets the client address (IP and port) to connect from on all name servers.
691    pub fn with_bind_addr(mut self, bind_addr: Option<SocketAddr>) -> Self {
692        for server in &mut self.0 {
693            server.bind_addr = bind_addr;
694        }
695        self
696    }
697}
698
699impl Default for NameServerConfigGroup {
700    fn default() -> Self {
701        Self::new()
702    }
703}
704
705impl Deref for NameServerConfigGroup {
706    type Target = Vec<NameServerConfig>;
707    fn deref(&self) -> &Self::Target {
708        &self.0
709    }
710}
711
712impl DerefMut for NameServerConfigGroup {
713    fn deref_mut(&mut self) -> &mut Self::Target {
714        &mut self.0
715    }
716}
717
718impl From<Vec<NameServerConfig>> for NameServerConfigGroup {
719    fn from(configs: Vec<NameServerConfig>) -> Self {
720        #[cfg(not(feature = "dns-over-rustls"))]
721        {
722            Self(configs)
723        }
724        #[cfg(feature = "dns-over-rustls")]
725        {
726            Self(configs, None)
727        }
728    }
729}
730
731/// The lookup ip strategy
732#[derive(Debug, Clone, Copy, PartialEq, Eq)]
733#[cfg_attr(feature = "serde-config", derive(Serialize, Deserialize))]
734pub enum LookupIpStrategy {
735    /// Only query for A (Ipv4) records
736    Ipv4Only,
737    /// Only query for AAAA (Ipv6) records
738    Ipv6Only,
739    /// Query for A and AAAA in parallel
740    Ipv4AndIpv6,
741    /// Query for Ipv6 if that fails, query for Ipv4
742    Ipv6thenIpv4,
743    /// Query for Ipv4 if that fails, query for Ipv6 (default)
744    Ipv4thenIpv6,
745}
746
747impl Default for LookupIpStrategy {
748    /// Returns [`LookupIpStrategy::Ipv4thenIpv6`] as the default.
749    fn default() -> Self {
750        Self::Ipv4thenIpv6
751    }
752}
753
754/// The strategy for establishing the query order of name servers in a pool.
755#[derive(Debug, Clone, Copy, PartialEq, Eq)]
756#[cfg_attr(feature = "serde-config", derive(Serialize, Deserialize))]
757pub enum ServerOrderingStrategy {
758    /// Servers are ordered based on collected query statistics. The ordering
759    /// may vary over time.
760    QueryStatistics,
761    /// The order provided to the resolver is used. The ordering does not vary
762    /// over time.
763    UserProvidedOrder,
764}
765
766impl Default for ServerOrderingStrategy {
767    /// Returns [`ServerOrderingStrategy::QueryStatistics`] as the default.
768    fn default() -> Self {
769        Self::QueryStatistics
770    }
771}
772
773/// Configuration for the Resolver
774#[derive(Debug, Clone, Copy, Eq, PartialEq)]
775#[cfg_attr(
776    feature = "serde-config",
777    derive(Serialize, Deserialize),
778    serde(default)
779)]
780#[allow(dead_code)] // TODO: remove after all params are supported
781#[non_exhaustive]
782pub struct ResolverOpts {
783    /// Sets the number of dots that must appear (unless it's a final dot representing the root)
784    ///  before a query is assumed to include the TLD. The default is one, which means that `www`
785    ///  would never be assumed to be a TLD, and would always be appended to either the search
786    pub ndots: usize,
787    /// Specify the timeout for a request. Defaults to 5 seconds
788    pub timeout: Duration,
789    /// Number of retries after lookup failure before giving up. Defaults to 2
790    pub attempts: usize,
791    /// Rotate through the resource records in the response (if there is more than one for a given name)
792    pub rotate: bool,
793    /// Validate the names in the response, not implemented don't really see the point unless you need to support
794    ///  badly configured DNS
795    pub check_names: bool,
796    /// Enable edns, for larger records
797    pub edns0: bool,
798    /// Use DNSSec to validate the request
799    pub validate: bool,
800    /// The ip_strategy for the Resolver to use when lookup Ipv4 or Ipv6 addresses
801    pub ip_strategy: LookupIpStrategy,
802    /// Cache size is in number of records (some records can be large)
803    pub cache_size: usize,
804    /// Check /ect/hosts file before dns requery (only works for unix like OS)
805    pub use_hosts_file: bool,
806    /// Optional minimum TTL for positive responses.
807    ///
808    /// If this is set, any positive responses with a TTL lower than this value will have a TTL of
809    /// `positive_min_ttl` instead. Otherwise, this will default to 0 seconds.
810    pub positive_min_ttl: Option<Duration>,
811    /// Optional minimum TTL for negative (`NXDOMAIN`) responses.
812    ///
813    /// If this is set, any negative responses with a TTL lower than this value will have a TTL of
814    /// `negative_min_ttl` instead. Otherwise, this will default to 0 seconds.
815    pub negative_min_ttl: Option<Duration>,
816    /// Optional maximum TTL for positive responses.
817    ///
818    /// If this is set, any positive responses with a TTL higher than this value will have a TTL of
819    /// `positive_max_ttl` instead. Otherwise, this will default to [`MAX_TTL`] seconds.
820    ///
821    /// [`MAX_TTL`]: ../dns_lru/const.MAX_TTL.html
822    pub positive_max_ttl: Option<Duration>,
823    /// Optional maximum TTL for negative (`NXDOMAIN`) responses.
824    ///
825    /// If this is set, any negative responses with a TTL higher than this value will have a TTL of
826    /// `negative_max_ttl` instead. Otherwise, this will default to [`MAX_TTL`] seconds.
827    ///
828    /// [`MAX_TTL`]: ../dns_lru/const.MAX_TTL.html
829    pub negative_max_ttl: Option<Duration>,
830    /// Number of concurrent requests per query
831    ///
832    /// Where more than one nameserver is configured, this configures the resolver to send queries
833    /// to a number of servers in parallel. Defaults to 2; 0 or 1 will execute requests serially.
834    pub num_concurrent_reqs: usize,
835    /// Preserve all intermediate records in the lookup response, suchas CNAME records
836    pub preserve_intermediates: bool,
837    /// Try queries over TCP if they fail over UDP.
838    pub try_tcp_on_error: bool,
839    /// The server ordering strategy that the resolver should use.
840    pub server_ordering_strategy: ServerOrderingStrategy,
841    /// Request upstream recursive resolvers to not perform any recursion.
842    ///
843    /// This is true by default, disabling this is useful for requesting single records, but may prevent successful resolution.
844    pub recursion_desired: bool,
845    /// This is true by default, disabling this is useful for requesting single records, but may prevent successful resolution.
846    pub authentic_data: bool,
847}
848
849impl Default for ResolverOpts {
850    /// Default values for the Resolver configuration.
851    ///
852    /// This follows the resolv.conf defaults as defined in the [Linux man pages](http://man7.org/linux/man-pages/man5/resolv.conf.5.html)
853    fn default() -> Self {
854        Self {
855            ndots: 1,
856            timeout: Duration::from_secs(5),
857            attempts: 2,
858            rotate: false,
859            check_names: true,
860            edns0: false,
861            validate: false,
862            ip_strategy: LookupIpStrategy::default(),
863            cache_size: 32,
864            use_hosts_file: true,
865            positive_min_ttl: None,
866            negative_min_ttl: None,
867            positive_max_ttl: None,
868            negative_max_ttl: None,
869            num_concurrent_reqs: 2,
870
871            // Defaults to `true` to match the behavior of dig and nslookup.
872            preserve_intermediates: true,
873
874            try_tcp_on_error: false,
875            server_ordering_strategy: ServerOrderingStrategy::default(),
876            recursion_desired: true,
877            authentic_data: false,
878        }
879    }
880}
881
882/// IP addresses for Google Public DNS
883pub const GOOGLE_IPS: &[IpAddr] = &[
884    IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)),
885    IpAddr::V4(Ipv4Addr::new(8, 8, 4, 4)),
886    IpAddr::V6(Ipv6Addr::new(0x2001, 0x4860, 0x4860, 0, 0, 0, 0, 0x8888)),
887    IpAddr::V6(Ipv6Addr::new(0x2001, 0x4860, 0x4860, 0, 0, 0, 0, 0x8844)),
888];
889
890/// IP addresses for Cloudflare's 1.1.1.1 DNS service
891pub const CLOUDFLARE_IPS: &[IpAddr] = &[
892    IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)),
893    IpAddr::V4(Ipv4Addr::new(1, 0, 0, 1)),
894    IpAddr::V6(Ipv6Addr::new(0x2606, 0x4700, 0x4700, 0, 0, 0, 0, 0x1111)),
895    IpAddr::V6(Ipv6Addr::new(0x2606, 0x4700, 0x4700, 0, 0, 0, 0, 0x1001)),
896];
897
898/// IP address for the Quad9 DNS service
899pub const QUAD9_IPS: &[IpAddr] = &[
900    IpAddr::V4(Ipv4Addr::new(9, 9, 9, 9)),
901    IpAddr::V4(Ipv4Addr::new(149, 112, 112, 112)),
902    IpAddr::V6(Ipv6Addr::new(0x2620, 0x00fe, 0, 0, 0, 0, 0, 0x00fe)),
903    IpAddr::V6(Ipv6Addr::new(0x2620, 0x00fe, 0, 0, 0, 0, 0x00fe, 0x0009)),
904];