trust_dns_resolver/lib.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//! **NOTICE** This project has been rebranded to Hickory DNS and has been moved to the https://github.com/hickory-dns/hickory-dns organization and repo, this crate/binary has been moved to [hickory-resolver](https://docs.rs/hickory-resolver/latest/hickory_resolver/), from `0.24` and onward.
9//!
10//! The Resolver is responsible for performing recursive queries to lookup domain names.
11//!
12//! This is a 100% in process DNS resolver. It *does not* use the Host OS' resolver. If what is
13//! desired is to use the Host OS' resolver, generally in the system's libc, then the
14//! `std::net::ToSocketAddrs` variant over `&str` should be used.
15//!
16//! Unlike the `trust-dns-client`, this tries to provide a simpler interface to perform DNS
17//! queries. For update options, i.e. Dynamic DNS, the `trust-dns-client` crate must be used
18//! instead. The Resolver library is capable of searching multiple domains (this can be disabled by
19//! using an FQDN during lookup), dual-stack IPv4/IPv6 lookups, performing chained CNAME lookups,
20//! and features connection metric tracking for attempting to pick the best upstream DNS resolver.
21//!
22//! There are two types for performing DNS queries, [`Resolver`] and [`AsyncResolver`]. `Resolver`
23//! is the easiest to work with, it is a wrapper around [`AsyncResolver`]. `AsyncResolver` is a
24//! `Tokio` based async resolver, and can be used inside any `Tokio` based system.
25//!
26//! This as best as possible attempts to abide by the DNS RFCs, please file issues at
27//! <https://github.com/bluejekyll/trust-dns>.
28//!
29//! # Usage
30//!
31//! ## Declare dependency
32//!
33//! ```toml
34//! [dependency]
35//! trust-dns-resolver = "*"
36//! ```
37//!
38//! ## Using the Synchronous Resolver
39//!
40//! This uses the default configuration, which sets the [Google Public
41//! DNS](https://developers.google.com/speed/public-dns/) as the upstream resolvers. Please see
42//! their [privacy statement](https://developers.google.com/speed/public-dns/privacy) for important
43//! information about what they track, many ISP's track similar information in DNS.
44//!
45//! ```rust
46//! # fn main() {
47//! # #[cfg(feature = "tokio-runtime")]
48//! # {
49//! use std::net::*;
50//! use trust_dns_resolver::Resolver;
51//! use trust_dns_resolver::config::*;
52//!
53//! // Construct a new Resolver with default configuration options
54//! let resolver = Resolver::new(ResolverConfig::default(), ResolverOpts::default()).unwrap();
55//!
56//! // Lookup the IP addresses associated with a name.
57//! // The final dot forces this to be an FQDN, otherwise the search rules as specified
58//! // in `ResolverOpts` will take effect. FQDN's are generally cheaper queries.
59//! let response = resolver.lookup_ip("www.example.com.").unwrap();
60//!
61//! // There can be many addresses associated with the name,
62//! // this can return IPv4 and/or IPv6 addresses
63//! let address = response.iter().next().expect("no addresses returned!");
64//! if address.is_ipv4() {
65//! assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
66//! } else {
67//! assert_eq!(address, IpAddr::V6(Ipv6Addr::new(0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946)));
68//! }
69//! # }
70//! # }
71//! ```
72//!
73//! ## Using the host system config
74//!
75//! On Unix systems, the `/etc/resolv.conf` can be used for configuration. Not all options
76//! specified in the host systems `resolv.conf` are applicable or compatible with this software. In
77//! addition there may be additional options supported which the host system does not. Example:
78//!
79//! ```rust,no_run
80//! # fn main() {
81//! # #[cfg(feature = "tokio-runtime")]
82//! # {
83//! # use std::net::*;
84//! # use trust_dns_resolver::Resolver;
85//! // Use the host OS'es `/etc/resolv.conf`
86//! # #[cfg(unix)]
87//! let resolver = Resolver::from_system_conf().unwrap();
88//! # #[cfg(unix)]
89//! let response = resolver.lookup_ip("www.example.com.").unwrap();
90//! # }
91//! # }
92//! ```
93//!
94//! ## Using the Tokio/Async Resolver
95//!
96//! For more advanced asynchronous usage, the `AsyncResolver`] is integrated with Tokio. In fact,
97//! the [`AsyncResolver`] is used by the synchronous Resolver for all lookups.
98//!
99//! ```rust
100//! # fn main() {
101//! # #[cfg(feature = "tokio-runtime")]
102//! # {
103//! use std::net::*;
104//! use tokio::runtime::Runtime;
105//! use trust_dns_resolver::TokioAsyncResolver;
106//! use trust_dns_resolver::config::*;
107//!
108//! // We need a Tokio Runtime to run the resolver
109//! // this is responsible for running all Future tasks and registering interest in IO channels
110//! let mut io_loop = Runtime::new().unwrap();
111//!
112//! // Construct a new Resolver with default configuration options
113//! let resolver = io_loop.block_on(async {
114//! TokioAsyncResolver::tokio(
115//! ResolverConfig::default(),
116//! ResolverOpts::default())
117//! });
118//!
119//! // Lookup the IP addresses associated with a name.
120//! // This returns a future that will lookup the IP addresses, it must be run in the Core to
121//! // to get the actual result.
122//! let lookup_future = resolver.lookup_ip("www.example.com.");
123//!
124//! // Run the lookup until it resolves or errors
125//! let mut response = io_loop.block_on(lookup_future).unwrap();
126//!
127//! // There can be many addresses associated with the name,
128//! // this can return IPv4 and/or IPv6 addresses
129//! let address = response.iter().next().expect("no addresses returned!");
130//! if address.is_ipv4() {
131//! assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
132//! } else {
133//! assert_eq!(address, IpAddr::V6(Ipv6Addr::new(0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946)));
134//! }
135//! # }
136//! # }
137//! ```
138//!
139//! Generally after a lookup in an asynchronous context, there would probably be a connection made
140//! to a server, for example:
141//!
142//! ```rust,no_run
143//! # fn main() {
144//! # #[cfg(feature = "tokio-runtime")]
145//! # {
146//! # use std::net::*;
147//! # use tokio::runtime::Runtime;
148//! # use trust_dns_resolver::TokioAsyncResolver;
149//! # use trust_dns_resolver::config::*;
150//! # use futures_util::TryFutureExt;
151//! #
152//! # let mut io_loop = Runtime::new().unwrap();
153//! #
154//! # let resolver = io_loop.block_on(async {
155//! # TokioAsyncResolver::tokio(
156//! # ResolverConfig::default(),
157//! # ResolverOpts::default())
158//! # });
159//! #
160//! let ips = io_loop.block_on(resolver.lookup_ip("www.example.com.")).unwrap();
161//!
162//! let result = io_loop.block_on(async {
163//! let ip = ips.iter().next().unwrap();
164//! TcpStream::connect((ip, 443))
165//! })
166//! .and_then(|conn| Ok(conn) /* do something with the connection... */)
167//! .unwrap();
168//! # }
169//! # }
170//! ```
171//!
172//! It's beyond the scope of these examples to show how to deal with connection failures and
173//! looping etc. But if you wanted to say try a different address from the result set after a
174//! connection failure, it will be necessary to create a type that implements the `Future` trait.
175//! Inside the `Future::poll` method would be the place to implement a loop over the different IP
176//! addresses.
177//!
178//! ## DNS-over-TLS and DNS-over-HTTPS
179//!
180//! DNS-over-TLS and DNS-over-HTTPS are supported in the Trust-DNS Resolver library. The underlying
181//! implementations are available as addon libraries. *WARNING* The trust-dns developers make no
182//! claims on the security and/or privacy guarantees of this implementation.
183//!
184//! To use DNS-over-TLS one of the `dns-over-tls` features must be enabled at compile time. There
185//! are three: `dns-over-openssl`, `dns-over-native-tls`, and `dns-over-rustls`. For DNS-over-HTTPS
186//! only rustls is supported with the `dns-over-https-rustls`, this implicitly enables support for
187//! DNS-over-TLS as well. The reason for each is to make the Trust-DNS libraries flexible for
188//! different deployments, and/or security concerns. The easiest to use will generally be
189//! `dns-over-rustls` which utilizes the `*ring*` Rust cryptography library (a rework of the
190//! `boringssl` project), this should compile and be usable on most ARM and x86 platforms.
191//! `dns-over-native-tls` will utilize the hosts TLS implementation where available or fallback to
192//! `openssl` where not supported. `dns-over-openssl` will specify that `openssl` should be used
193//! (which is a perfectly fine option if required). If more than one is specified, the precedence
194//! will be in this order (i.e. only one can be used at a time) `dns-over-rustls`,
195//! `dns-over-native-tls`, and then `dns-over-openssl`. *NOTICE* the trust-dns developers are not
196//! responsible for any choice of library that does not meet required security requirements.
197//!
198//! ### Example
199//!
200//! Enable the TLS library through the dependency on `trust-dns-resolver`:
201//!
202//! ```toml
203//! trust-dns-resolver = { version = "*", features = ["dns-over-rustls"] }
204//! ```
205//!
206//! A default TLS configuration is available for Cloudflare's `1.1.1.1` DNS service (Quad9 as
207//! well):
208//!
209//! ```rust,no_run
210//! # fn main() {
211//! # #[cfg(feature = "tokio-runtime")]
212//! # {
213//! use trust_dns_resolver::Resolver;
214//! use trust_dns_resolver::config::*;
215//!
216//! // Construct a new Resolver with default configuration options
217//! # #[cfg(feature = "dns-over-tls")]
218//! let mut resolver = Resolver::new(ResolverConfig::cloudflare_tls(), ResolverOpts::default()).unwrap();
219//!
220//! // see example above...
221//! # }
222//! # }
223//! ```
224//!
225//! ## mDNS (multicast DNS)
226//!
227//! Multicast DNS is an experimental feature in Trust-DNS at the moment. Its support on different
228//! platforms is not yet ideal. Initial support is only for IPv4 mDNS, as there are some
229//! complexities to figure out with IPv6. Once enabled, an mDNS `NameServer` will automatically be
230//! added to the `Resolver` and used for any lookups performed in the `.local.` zone.
231
232// LIBRARY WARNINGS
233#![warn(
234 clippy::default_trait_access,
235 clippy::dbg_macro,
236 clippy::print_stdout,
237 clippy::unimplemented,
238 clippy::use_self,
239 missing_copy_implementations,
240 missing_docs,
241 non_snake_case,
242 non_upper_case_globals,
243 rust_2018_idioms,
244 unreachable_pub
245)]
246#![recursion_limit = "128"]
247#![allow(clippy::needless_doctest_main, clippy::single_component_path_imports)]
248#![cfg_attr(docsrs, feature(doc_cfg))]
249
250#[cfg(feature = "dns-over-tls")]
251#[macro_use]
252extern crate cfg_if;
253#[cfg(feature = "serde-config")]
254#[macro_use]
255extern crate serde;
256pub extern crate trust_dns_proto as proto;
257
258mod async_resolver;
259pub mod caching_client;
260pub mod config;
261pub mod dns_lru;
262pub mod dns_sd;
263pub mod error;
264mod hosts;
265#[cfg(feature = "dns-over-https")]
266mod https;
267pub mod lookup;
268pub mod lookup_ip;
269// TODO: consider #[doc(hidden)]
270pub mod name_server;
271#[cfg(feature = "dns-over-quic")]
272mod quic;
273#[cfg(feature = "tokio-runtime")]
274mod resolver;
275pub mod system_conf;
276#[cfg(feature = "dns-over-tls")]
277mod tls;
278
279// reexports from proto
280pub use self::proto::rr::{IntoName, Name, TryParseIp};
281
282#[cfg(feature = "testing")]
283#[cfg_attr(docsrs, doc(cfg(feature = "testing")))]
284pub use async_resolver::testing;
285pub use async_resolver::AsyncResolver;
286#[cfg(feature = "tokio-runtime")]
287#[cfg_attr(docsrs, doc(cfg(feature = "tokio-runtime")))]
288pub use async_resolver::TokioAsyncResolver;
289pub use hosts::Hosts;
290#[cfg(feature = "tokio-runtime")]
291#[cfg_attr(docsrs, doc(cfg(feature = "tokio-runtime")))]
292pub use name_server::TokioHandle;
293#[cfg(feature = "tokio-runtime")]
294#[cfg_attr(docsrs, doc(cfg(feature = "tokio-runtime")))]
295pub use resolver::Resolver;
296
297/// This is an alias for [`AsyncResolver`], which replaced the type previously
298/// called `ResolverFuture`.
299///
300/// # Note
301///
302/// For users of `ResolverFuture`, the return type for `ResolverFuture::new`
303/// has changed since version 0.9 of `trust-dns-resolver`. It now returns
304/// a tuple of an [`AsyncResolver`] _and_ a background future, which must
305/// be spawned on a reactor before any lookup futures will run.
306///
307/// See the [`AsyncResolver`] documentation for more information on how to
308/// use the background future.
309#[deprecated(note = "use [`trust_dns_resolver::AsyncResolver`] instead")]
310#[cfg(feature = "tokio-runtime")]
311#[cfg_attr(docsrs, doc(cfg(feature = "tokio-runtime")))]
312pub type ResolverFuture = TokioAsyncResolver;
313
314/// returns a version as specified in Cargo.toml
315pub fn version() -> &'static str {
316 env!("CARGO_PKG_VERSION")
317}