What are Resolvers?¶
In asyncdns
, Resolvers are the objects that are responsible for taking
Query
objects and returning Reply
objects
corresponding to those queries.
Resolvers don’t derive from a single base class, as some of them work quite differently to others. Instead, they all implement the following two methods:
-
close
()¶ Cancel all in-progress lookups and shut down the resolver.
-
lookup
(query)¶ Parameters: query – The Query
to process.Retval: An asyncio.Future
that will complete with aReply
.
Resolvers are guaranteed to cancel lookups that are in progress when the resolver itself is destroyed. Active lookups do not keep a resolver alive.
Individual resolvers may support additional parameters for their
lookup()
method, but those parameters are generally specific to the
workings of the resolver in question.
Resolver¶
-
class
Resolver
¶ The core DNS resolver. This class holds all of the code to perform normal DNS queries, including recursive resolution, and maintains its own request cache, so that repeatedly querying for the same record won’t result in unnecessary network traffic or delay.
-
lookup(query, servers=None, should_cache=True,
-
recursive=False, prefer_ipv6=False, force_tcp=False)
Perform a DNS lookup.
Parameters: - query – The
Query
to resolve. - servers – See discussion below.
- should_cache – Setting this to False disables the
Resolver
cache. - recursive – Whether to perform recursive lookups.
- prefer_ipv6 – When doing recursive lookup, prefer servers that talk over IPv6.
- force_tcp – Prevents the resolver from using UDP for queries that are short enough to fit.
Retval: An
asyncio.Future
that will complete with aReply
.The
servers
parameter can be:- An (address, port) tuple.
- A
list
of (address, port) tuples, which will be used randomly. - An iterable of some sort that yields (address, port) tuples. Note that if the iterable raises StopIteration, any in-progress queries will fail with the StopIteration exception.
None
, in which case the resolver will be recursive (regardless of the setting of therecursive
parameter) and will start with the global root servers. We recommend not using this feature unless absolutely necessary, as it puts additional load on the root servers and it’s usually better to talk to your own nameserver or use one provided by your ISP or infrastructure platform.
asyncdns
provides two useful iterables,RandomServer
andRoundRobinServer
, both of which provide an infinite stream of tuples given a list of server addresses.- query – The
-
flush_cache
()¶ Flushes the resolver’s cache.
-
HostsResolver¶
-
class
HostsResolver
¶ Resolves names using the contents of
/etc/hosts
(or, on Windows,\Windows\System32\drivers\etc\hosts
).-
lookup
(query)¶ Parameters: query – The Query
to resolve.Retval: An asyncio.Future
that will complete with aReply
.This method only supports A, AAAA and PTR queries. In addition to names listed in
/etc/hosts
, it knows about the.in-addr.arpa
and.ip6.arpa
pseudo-zones.The
HostsResolver
will automatically re-read/etc/hosts
if it has changed, but only if the last time it was read was more than 30 seconds ago.
-
MulticastResolver¶
-
class
MulticastResolver
¶ Resolves queries using Multicast DNS (aka MDNS). You don’t need to have Apple’s mdnsResponder software installed to use this - it will work on any system that can run Python and that supports IP multicast.
-
lookup
(query, use_ipv6=False, unicast_reply=False)¶ Parameters: - query – The
Query
to resolve. - use_ipv6 – Whether to multicast using IPv6 or not. The default is to use IPv4.
- unicast_reply – Whether to request that the reply be sent via unicast. This is intended to reduce multicast traffic.
Retval: An
asyncio.Future
that will complete with aReply
.- query – The
-
SystemResolver¶
SystemResolver
is actually a “class cluster”, in that there are
separate implementations for Darwin/Mac OS X/macOS, Windows, and generic
UNIX/Linux. The idea of SystemResolver
is that it works like
Resolver
, but uses the system configured nameservers (and will
automatically update its list of nameservers should the system configuration
change).
There are some limitations here: the UNIX/Linux generic implementation works
by reading /etc/resolv.conf
, so any other configuration mechanism that
might be in use will be ignored, while the Windows version uses Windows APIs
that appear to be limited to returning IPv4 nameservers only. On Windows,
there doesn’t seem to be a mechanism to spot changes to the configuration, so
we re-read it at most once every 30 seconds; on UNIX/Linux, we watch
the timestamp on /etc/resolv.conf
, again, at most once every 30 seconds.
Some people have suggested using res_ninit()
on UNIX rather than directly
reading /etc/resolv.conf
; that’s certainly a possibility, but if
/etc/resolv.conf
isn’t being used to configure the nameservers, we’d end
up in the same situation as on Windows, where we have no way to tell if the
server settings have been updated.
-
class
SystemResolver
¶ -
lookup(query, servers=None, should_cache=True,
-
recursive=False, prefer_ipv6=False, force_tcp=False)
Perform a DNS lookup.
Parameters: - query – The
Query
to resolve. - should_cache – Setting this to False disables the
Resolver
cache. - recursive – Whether to perform recursive lookups.
- prefer_ipv6 – When doing recursive lookup, prefer servers that talk over IPv6.
- force_tcp – Prevents the resolver from using UDP for queries that are short enough to fit.
Retval: An
asyncio.Future
that will complete with aReply
.- query – The
-
SmartResolver¶
SmartResolver
is a convenience class that accepts a query and
determines which of the other resolvers to use to process it. Specifically:
- It first tries
HostsResolver
, which means the hosts file can override resolution the way people expect.- If that fails and the query is for a name ending
.local
, it usesMulticastResolver
.- Otherwise, it uses
SystemResolver
.
N.B. Pay attention to the security implications of using
MulticastResolver
here; if you are using a server platform where
multicast isn’t appropriately restricted, this could open up a security hole
that causes you to send data to an attacker’s system instead of the one you
wanted to.