Coverage Report

Created: 2025-10-29 07:05

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