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