Skip to main content

DnsResolver

Struct DnsResolver 

Source
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

Source

pub fn new() -> Self

Creates a new DNS resolver with default settings.

Source

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.

Source

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.

Source

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.

Source

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 query
  • record_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), or https://host[:port][/path] (DNS over HTTPS) — see NameserverSpec
Source§

impl DnsResolver

Source

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

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for DnsResolver

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for DnsResolver

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more