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