DNS toolkit for Python supporting almost all record types with high-level and low-level DNS operations
85
High-level DNS resolution functionality that provides the simplest interface for common DNS operations. The resolver module handles automatic retry logic, caching, and provides convenient access to all DNS record types.
Perform DNS queries using the default resolver with automatic error handling and retry logic.
def query(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, tcp=False, source=None,
raise_on_no_answer=True, source_port=0, lifetime=None):
"""
Query using the default resolver.
Args:
qname (str or dns.name.Name): Domain name to query
rdtype (str or int): Record type (default 'A')
rdclass (str or int): Record class (default 'IN')
tcp (bool): Use TCP instead of UDP
source (str): Source IP address
raise_on_no_answer (bool): Raise exception if no answer
source_port (int): Source port number
lifetime (float): Total query lifetime in seconds
Returns:
dns.resolver.Answer: Query result with sequence-like access
"""
def zone_for_name(name, rdclass='IN', tcp=False, resolver=None):
"""
Find the zone containing the specified name.
Args:
name (str or dns.name.Name): Domain name
rdclass (str or int): Record class (default 'IN')
tcp (bool): Use TCP instead of UDP
resolver (dns.resolver.Resolver): Custom resolver
Returns:
dns.name.Name: Zone name containing the specified name
"""
def get_default_resolver():
"""
Get the default resolver instance.
Returns:
dns.resolver.Resolver: Default resolver
"""
def reset_default_resolver():
"""Re-initialize the default resolver from system configuration."""
def override_system_resolver(resolver=None):
"""
Override system DNS resolution functions.
Args:
resolver (dns.resolver.Resolver): Custom resolver or None for default
"""
def restore_system_resolver():
"""Restore original system DNS resolution functions."""Configurable DNS resolver with support for custom nameservers, timeouts, and query options.
class Resolver:
"""
A DNS resolver with configurable options.
Attributes:
nameservers (list): List of nameserver IP addresses
port (int): Default port for queries (default 53)
timeout (float): Timeout for individual queries
lifetime (float): Total timeout for all queries
search (list): Search domains for relative names
domain (dns.name.Name): Local domain name
ndots (int): Minimum dots for absolute name treatment
rotate (bool): Rotate through nameservers
cache (dns.resolver.Cache): Answer cache
flags (int): Query flags
edns (int): EDNS version (-1 to disable)
ednsflags (int): EDNS flags
payload (int): EDNS payload size
keyring (dict): TSIG keyring
keyname (dns.name.Name): TSIG key name
keyalgorithm (dns.name.Name): TSIG algorithm
"""
def __init__(self, filename='/etc/resolv.conf', configure=True):
"""
Initialize resolver.
Args:
filename (str): Configuration file path
configure (bool): Configure from system settings
"""
def query(self, qname, rdtype='A', rdclass='IN', tcp=False, source=None,
raise_on_no_answer=True, source_port=0):
"""
Query using this resolver instance.
Returns:
dns.resolver.Answer: Query result
"""
def read_resolv_conf(self, f):
"""
Read configuration from resolv.conf format file.
Args:
f (file-like): File to read from
"""
def use_tsig(self, keyring, keyname=None, algorithm=dns.tsig.default_algorithm):
"""
Configure TSIG authentication for queries.
Args:
keyring (dict): TSIG keyring mapping key names to key values
keyname (dns.name.Name): TSIG key name (optional, uses first key if None)
algorithm (dns.name.Name): TSIG algorithm (default: HMAC-MD5)
"""Result wrapper that provides sequence-like access to resource records with metadata.
class Answer:
"""
DNS query answer with sequence-like access to resource records.
Attributes:
qname (dns.name.Name): Query name
rdtype (int): Record type queried
rdclass (int): Record class queried
response (dns.message.Message): Full DNS response
rrset (dns.rrset.RRset): Answer resource record set
canonical_name (dns.name.Name): Canonical name after CNAME following
expiration (float): Answer expiration time
"""
def __iter__(self):
"""Iterate over resource records in the answer."""
def __len__(self):
"""Return number of resource records."""
def __getitem__(self, index):
"""Get resource record by index."""DNS answer caching with configurable size and TTL handling.
class Cache:
"""
Simple thread-safe DNS answer cache.
Args:
cleaning_interval (float): Cache cleaning interval in seconds
"""
def get(self, key):
"""Get cached answer for key."""
def put(self, key, value):
"""Store answer in cache."""
def flush(self, key=None):
"""Remove items from cache."""
class LRUCache(Cache):
"""
Bounded least-recently-used DNS answer cache.
Args:
max_size (int): Maximum cache entries (default 100000)
"""import dns.resolver
# Simple A record lookup
result = dns.resolver.query('example.com', 'A')
for rdata in result:
print(f"IP: {rdata.address}")
# MX record lookup
mx_result = dns.resolver.query('example.com', 'MX')
for rdata in mx_result:
print(f"Mail server: {rdata.exchange}, priority: {rdata.preference}")
# TXT record lookup
txt_result = dns.resolver.query('example.com', 'TXT')
for rdata in txt_result:
print(f"TXT: {rdata.strings}")import dns.resolver
# Create custom resolver
resolver = dns.resolver.Resolver()
resolver.nameservers = ['8.8.8.8', '8.8.4.4'] # Google DNS
resolver.timeout = 10
resolver.lifetime = 30
# Query using custom resolver
result = resolver.query('example.com', 'AAAA')
for rdata in result:
print(f"IPv6: {rdata.address}")
# Configure search domains
resolver.search = [dns.name.from_text('example.com')]
resolver.domain = dns.name.from_text('example.com')import dns.resolver
import dns.exception
try:
result = dns.resolver.query('nonexistent.example.com', 'A')
except dns.resolver.NXDOMAIN as e:
print(f"Domain does not exist: {e}")
except dns.resolver.NoAnswer as e:
print(f"No answer for query: {e}")
except dns.resolver.Timeout as e:
print(f"Query timed out: {e}")
except dns.exception.DNSException as e:
print(f"DNS error occurred: {e}")class NXDOMAIN(DNSException):
"""The query name does not exist."""
class YXDOMAIN(DNSException):
"""The query name is too long after DNAME substitution."""
class NoAnswer(DNSException):
"""The DNS response does not contain an answer to the question."""
class NoNameservers(DNSException):
"""All nameservers failed to answer the query."""
class NotAbsolute(DNSException):
"""An absolute domain name is required but was not provided."""
class NoRootSOA(DNSException):
"""There is no SOA RR at the DNS root name."""
class NoMetaqueries(DNSException):
"""DNS metaqueries are not allowed."""Install with Tessl CLI
npx tessl i tessl/pypi-dnspythondocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10