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