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];