make Recursor configurable via a "builder"
and make security-awareness opt-in
This commit is contained in:
parent
f3a012cc36
commit
36258a8a03
@ -34,7 +34,7 @@ pub use error::{Error, ErrorKind};
|
|||||||
pub use hickory_proto as proto;
|
pub use hickory_proto as proto;
|
||||||
pub use hickory_resolver as resolver;
|
pub use hickory_resolver as resolver;
|
||||||
pub use hickory_resolver::config::NameServerConfig;
|
pub use hickory_resolver::config::NameServerConfig;
|
||||||
pub use recursor::Recursor;
|
pub use recursor::{Recursor, RecursorBuilder};
|
||||||
|
|
||||||
fn is_security_aware() -> bool {
|
fn is_security_aware() -> bool {
|
||||||
cfg!(feature = "dnssec")
|
cfg!(feature = "dnssec")
|
||||||
|
@ -37,6 +37,66 @@ use crate::{
|
|||||||
/// Set of nameservers by the zone name
|
/// Set of nameservers by the zone name
|
||||||
type NameServerCache<P> = LruCache<Name, RecursorPool<P>>;
|
type NameServerCache<P> = LruCache<Name, RecursorPool<P>>;
|
||||||
|
|
||||||
|
/// A `Recursor` builder
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct RecursorBuilder {
|
||||||
|
ns_cache_size: usize,
|
||||||
|
record_cache_size: usize,
|
||||||
|
#[cfg(feature = "dnssec")]
|
||||||
|
security_aware: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RecursorBuilder {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
ns_cache_size: 1024,
|
||||||
|
record_cache_size: 1048576,
|
||||||
|
#[cfg(feature = "dnssec")]
|
||||||
|
security_aware: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RecursorBuilder {
|
||||||
|
/// Sets the size of the list of cached name servers
|
||||||
|
pub fn ns_cache_size(&mut self, size: usize) -> &mut Self {
|
||||||
|
self.ns_cache_size = size;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the size of the list of cached records
|
||||||
|
pub fn record_cache_size(&mut self, size: usize) -> &mut Self {
|
||||||
|
self.record_cache_size = size;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enables or disables (DNSSEC) security awareness
|
||||||
|
#[cfg(feature = "dnssec")]
|
||||||
|
pub fn security_aware(&mut self, security_aware: bool) -> &mut Self {
|
||||||
|
self.security_aware = security_aware;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a new recursor using the list of NameServerConfigs for the root node list
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This will panic if the roots are empty.
|
||||||
|
pub fn build(&self, roots: impl Into<NameServerConfigGroup>) -> Result<Recursor, ResolveError> {
|
||||||
|
#[cfg(not(feature = "dnssec"))]
|
||||||
|
let security_aware = false;
|
||||||
|
#[cfg(feature = "dnssec")]
|
||||||
|
let security_aware = self.security_aware;
|
||||||
|
|
||||||
|
Recursor::build(
|
||||||
|
roots,
|
||||||
|
self.ns_cache_size,
|
||||||
|
self.record_cache_size,
|
||||||
|
security_aware,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A top down recursive resolver which operates off a list of roots for initial recursive requests.
|
/// A top down recursive resolver which operates off a list of roots for initial recursive requests.
|
||||||
///
|
///
|
||||||
/// This is the well known root nodes, referred to as hints in RFCs. See the IANA [Root Servers](https://www.iana.org/domains/root/servers) list.
|
/// This is the well known root nodes, referred to as hints in RFCs. See the IANA [Root Servers](https://www.iana.org/domains/root/servers) list.
|
||||||
@ -44,18 +104,21 @@ pub struct Recursor {
|
|||||||
roots: RecursorPool<TokioRuntimeProvider>,
|
roots: RecursorPool<TokioRuntimeProvider>,
|
||||||
name_server_cache: Mutex<NameServerCache<TokioRuntimeProvider>>,
|
name_server_cache: Mutex<NameServerCache<TokioRuntimeProvider>>,
|
||||||
record_cache: DnsLru,
|
record_cache: DnsLru,
|
||||||
|
security_aware: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Recursor {
|
impl Recursor {
|
||||||
/// Construct a new recursor using the list of NameServerConfigs for the root node list
|
/// Short-hand for `RecursorBuilder::default`
|
||||||
///
|
#[allow(clippy::new_ret_no_self)]
|
||||||
/// # Panics
|
pub fn new() -> RecursorBuilder {
|
||||||
///
|
RecursorBuilder::default()
|
||||||
/// This will panic if the roots are empty.
|
}
|
||||||
pub fn new(
|
|
||||||
|
fn build(
|
||||||
roots: impl Into<NameServerConfigGroup>,
|
roots: impl Into<NameServerConfigGroup>,
|
||||||
ns_cache_size: usize,
|
ns_cache_size: usize,
|
||||||
record_cache_size: usize,
|
record_cache_size: usize,
|
||||||
|
security_aware: bool,
|
||||||
) -> Result<Self, ResolveError> {
|
) -> Result<Self, ResolveError> {
|
||||||
// configure the hickory-resolver
|
// configure the hickory-resolver
|
||||||
let roots: NameServerConfigGroup = roots.into();
|
let roots: NameServerConfigGroup = roots.into();
|
||||||
@ -74,6 +137,7 @@ impl Recursor {
|
|||||||
roots,
|
roots,
|
||||||
name_server_cache,
|
name_server_cache,
|
||||||
record_cache,
|
record_cache,
|
||||||
|
security_aware,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +308,7 @@ impl Recursor {
|
|||||||
request_time: Instant,
|
request_time: Instant,
|
||||||
query_has_dnssec_ok: bool,
|
query_has_dnssec_ok: bool,
|
||||||
) -> Result<Lookup, Error> {
|
) -> Result<Lookup, Error> {
|
||||||
if crate::is_security_aware() {
|
if self.security_aware {
|
||||||
// TODO RFC4035 section 4.5 recommends caching "each response as a single atomic entry
|
// TODO RFC4035 section 4.5 recommends caching "each response as a single atomic entry
|
||||||
// containing the entire answer, including the named RRset and any associated DNSSEC
|
// containing the entire answer, including the named RRset and any associated DNSSEC
|
||||||
// RRs"
|
// RRs"
|
||||||
@ -289,7 +353,7 @@ impl Recursor {
|
|||||||
let ns = ns.ok_or_else(|| Error::from(format!("no nameserver found for {zone}")))?;
|
let ns = ns.ok_or_else(|| Error::from(format!("no nameserver found for {zone}")))?;
|
||||||
debug!("found zone {} for {}", ns.zone(), query);
|
debug!("found zone {} for {}", ns.zone(), query);
|
||||||
|
|
||||||
let dnssec = if crate::is_security_aware() {
|
let dnssec = if self.security_aware {
|
||||||
Dnssec::Aware {
|
Dnssec::Aware {
|
||||||
query_has_dnssec_ok,
|
query_has_dnssec_ok,
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,10 @@ impl RecursiveAuthority {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let recursor = Recursor::new(roots, config.ns_cache_size, config.record_cache_size)
|
let recursor = Recursor::new()
|
||||||
|
.ns_cache_size(config.ns_cache_size)
|
||||||
|
.record_cache_size(config.record_cache_size)
|
||||||
|
.build(roots)
|
||||||
.map_err(|e| format!("failed to initialize recursor: {e}"))?;
|
.map_err(|e| format!("failed to initialize recursor: {e}"))?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -157,7 +157,7 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let name = opts.domainname;
|
let name = opts.domainname;
|
||||||
let ty = opts.ty;
|
let ty = opts.ty;
|
||||||
|
|
||||||
let recursor = Recursor::new(roots, 1024, 1048576)?;
|
let recursor = Recursor::new().build(roots)?;
|
||||||
|
|
||||||
// execute query
|
// execute query
|
||||||
println!(
|
println!(
|
||||||
|
Loading…
Reference in New Issue
Block a user