pub struct DnsResolver { /* private fields */ }Expand description
DNS resolver for querying various record types.
Uses Google DNS (8.8.8.8) by default, but supports custom nameservers
over plain UDP, DNS over TLS (tls://), and DNS over HTTPS (https://)
— see NameserverSpec for the accepted forms.
The default resolver is cached and reused across queries to avoid
repeated initialization overhead.
Implementations§
Source§impl DnsResolver
impl DnsResolver
Sourcepub fn from_config(config: &SeerConfig) -> Self
pub fn from_config(config: &SeerConfig) -> Self
Builds a resolver honoring ~/.seer/config.toml settings.
Reads timeouts.dns_secs (already clamped to 1–60s by
crate::config::SeerConfig::load) — the same resolver as
DnsResolver::new().with_timeout(config.dns_timeout()), built once.
The nameserver config key is deliberately NOT applied here: the
resolver takes the nameserver per-query (see DnsResolver::resolve),
so callers thread config.nameserver at the call site where it can be
overridden per-invocation.
Sourcepub fn with_timeout(self, timeout: Duration) -> Self
pub fn with_timeout(self, timeout: Duration) -> Self
Sets the timeout for DNS queries.
The default is 5 seconds, which is sufficient for most DNS queries.
Sourcepub async fn query(
&self,
domain: &str,
record_type: RecordType,
nameserver: Option<&str>,
) -> Result<DnsQueryResult>
pub async fn query( &self, domain: &str, record_type: RecordType, nameserver: Option<&str>, ) -> Result<DnsQueryResult>
Queries one name the way dig does and reports the whole response:
status, header flags, the CNAME chain and answers under their real
owner names, the AUTHORITY section, and a wildcard probe.
Takes the same input as resolve — normalization,
the dig-style _service._proto.name SRV form, a raw IP literal for
PTR, and a custom nameserver spec (SSRF-vetted) or None for the
default upstream — but where resolve folds every negative answer
into an empty list, query reports it: NXDOMAIN, NODATA, SERVFAIL
and REFUSED are Ok results with that DnsQueryResult::status.
An Err means there is no response to report: invalid input (a
malformed name, a bare-domain SRV query), a nameserver that was
refused (a private or reserved address) or did not resolve, or a
transport failure (timeout, no connection) at every server.
Like dig, it sends one query (with RD set) and reports the response the server sent — header, ANSWER and AUTHORITY sections as they came — rather than a resolver lookup, which would chase a CNAME itself and fold a negative answer into an error: a chain that ends at a name that does not exist is reported with the chain and NXDOMAIN, as the recursive server returns it. The servers are the nameserver’s (or the default upstream’s), asked in order, IPv4 first; UDP, repeated over TCP when the reply is truncated; and a server that does not respond passes the query to the next, all under two DNS timeouts.
ANY fans out concurrently to A, AAAA, CNAME, MX, NS, TXT, SOA, CAA,
HTTPS, DS and DNSKEY and merges the answers (see
DnsQueryResult::answers); a sub-query that failed is listed in
DnsQueryResult::failed_types, and the query errors only when
every sub-query failed.
For a name strictly below its registrable domain (www.example.com,
not example.com), a random sibling (seer-probe-….example.com) is
queried for the same type concurrently with the main query, and its
outcome attached as DnsQueryResult::wildcard when the main answer
has records. The probe never fails the query, a positive answer waits
for it at most a fifth of the DNS timeout, and
DnsQueryResult::query_time_ms times the main query alone.
A special-use name (RFC 6761: localhost, 127.in-addr.arpa,
invalid, onion, …) is never sent to a server — RFC 7686 forbids
leaking .onion names into the DNS — but answered by hickory’s
resolver itself; the result says so
(DnsQueryResult::answered_locally) and runs no probe. A
nameserver given with it is parsed and, when an IP literal, vetted,
but a hostname is not resolved: nothing is sent to it.
Sourcepub async fn resolve(
&self,
domain: &str,
record_type: RecordType,
nameserver: Option<&str>,
) -> Result<Vec<DnsRecord>>
pub async fn resolve( &self, domain: &str, record_type: RecordType, nameserver: Option<&str>, ) -> Result<Vec<DnsRecord>>
Resolves DNS records for a domain: the records of record_type only,
each named by the queried name, with NXDOMAIN and NODATA folded into
an empty list. For the response itself — status, CNAME chain, the SOA
of a negative answer — use query.
§Arguments
domain- The domain name to queryrecord_type- The type of DNS record to look up (A, AAAA, MX, etc.)nameserver- Optional custom nameserver spec; uses Google DNS if None. Accepts a bare IP/hostname with optional port (UDP),tls://host[:port](DNS over TLS), orhttps://host[:port][/path](DNS over HTTPS) — seeNameserverSpec
Source§impl DnsResolver
impl DnsResolver
Sourcepub async fn presence(&self, domain: &str) -> DnsPresence
pub async fn presence(&self, domain: &str) -> DnsPresence
Probes whether a domain has any DNS presence by querying its apex NS records. A registered, delegated domain returns NS records; an unregistered domain returns NXDOMAIN (an empty record set).
This is a heuristic, not proof: a registered-but-undelegated domain
also has no NS records, so callers should treat
DnsPresence::Absent as “likely available” (medium confidence).
Trait Implementations§
Source§impl Clone for DnsResolver
impl Clone for DnsResolver
Source§impl Debug for DnsResolver
impl Debug for DnsResolver
Auto Trait Implementations§
impl !RefUnwindSafe for DnsResolver
impl !UnwindSafe for DnsResolver
impl Freeze for DnsResolver
impl Send for DnsResolver
impl Sync for DnsResolver
impl Unpin for DnsResolver
impl UnsafeUnpin for DnsResolver
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more