DNS toolkit for Python supporting almost all record types with high-level and low-level DNS operations
85
DNS name parsing, manipulation, and formatting functionality with full internationalization support. Handles absolute and relative names, wildcards, IDNA encoding, and all DNS name operations including comparison, concatenation, and canonicalization.
Parse DNS names from various formats including text, Unicode, and wire format.
def from_text(text, origin=None, idna_codec=None):
"""
Parse a DNS name from text format.
Args:
text (str): Text representation of DNS name
origin (dns.name.Name): Origin for relative names
idna_codec (dns.name.IDNACodec): IDNA codec for internationalization
Returns:
dns.name.Name: Parsed DNS name
"""
def from_unicode(text, origin=None, idna_codec=None):
"""
Parse a DNS name from Unicode text.
Args:
text (str): Unicode representation of DNS name
origin (dns.name.Name): Origin for relative names
idna_codec (dns.name.IDNACodec): IDNA codec
Returns:
dns.name.Name: Parsed DNS name
"""
def from_wire(message, current):
"""
Parse a DNS name from wire format.
Args:
message (bytes): Wire format message
current (int): Current position in message
Returns:
tuple: (dns.name.Name, int) - name and new position
"""Immutable DNS name represented as a tuple of labels with comprehensive manipulation methods.
class Name:
"""
An immutable DNS name as a tuple of labels.
A Name is an ordered sequence of labels. Names can be absolute
(ending with the root label) or relative.
"""
def __init__(self, labels):
"""
Initialize a Name from a sequence of labels.
Args:
labels (iterable): Sequence of label strings
"""
def __str__(self):
"""Return text representation of name."""
def __repr__(self):
"""Return detailed string representation."""
def __hash__(self):
"""Return hash of name."""
def __len__(self):
"""Return number of labels in name."""
def __getitem__(self, index):
"""Get label by index."""
def __add__(self, other):
"""Concatenate names."""
def __eq__(self, other):
"""Test name equality."""
def __ne__(self, other):
"""Test name inequality."""
def __lt__(self, other):
"""Compare names for sorting."""
def __le__(self, other):
"""Compare names for sorting."""
def __gt__(self, other):
"""Compare names for sorting."""
def __ge__(self, other):
"""Compare names for sorting."""Convert names to various output formats including text, Unicode, and wire format.
def to_text(omit_final_dot=False):
"""
Convert name to text format.
Args:
omit_final_dot (bool): Omit trailing dot for absolute names
Returns:
str: Text representation of name
"""
def to_unicode(omit_final_dot=False, idna_codec=None):
"""
Convert name to Unicode text format.
Args:
omit_final_dot (bool): Omit trailing dot for absolute names
idna_codec (dns.name.IDNACodec): IDNA codec for decoding
Returns:
str: Unicode representation of name
"""
def to_wire(file=None, compress=None, origin=None):
"""
Convert name to wire format.
Args:
file (file-like): File to write to (None returns bytes)
compress (dict): Compression map for name compression
origin (dns.name.Name): Origin for relative names
Returns:
bytes or None: Wire format bytes or None if file specified
"""
def to_digestable(origin=None):
"""
Convert name to format suitable for cryptographic hashing.
Args:
origin (dns.name.Name): Origin for relative names
Returns:
bytes: Canonical wire format for hashing
"""Test name properties and relationships.
def is_absolute():
"""
Check if name is absolute (ends with root label).
Returns:
bool: True if name is absolute
"""
def is_wild():
"""
Check if name is a wildcard (starts with '*' label).
Returns:
bool: True if name is wildcard
"""
def is_subdomain(other):
"""
Check if this name is a subdomain of another name.
Args:
other (dns.name.Name): Potential parent domain
Returns:
bool: True if this name is subdomain of other
"""
def is_superdomain(other):
"""
Check if this name is a superdomain of another name.
Args:
other (dns.name.Name): Potential subdomain
Returns:
bool: True if this name is superdomain of other
"""Manipulate names through concatenation, relativization, and hierarchy operations.
def concatenate(other):
"""
Concatenate this name with another name.
Args:
other (dns.name.Name): Name to append
Returns:
dns.name.Name: Concatenated name
"""
def relativize(origin):
"""
Make this name relative to the specified origin.
Args:
origin (dns.name.Name): Origin name
Returns:
dns.name.Name: Relativized name
"""
def derelativize(origin):
"""
Make this name absolute using the specified origin.
Args:
origin (dns.name.Name): Origin name
Returns:
dns.name.Name: Absolute name
"""
def parent():
"""
Get the parent domain of this name.
Returns:
dns.name.Name: Parent domain
Raises:
dns.name.NoParent: If name has no parent (root or empty)
"""
def split(depth):
"""
Split name into prefix and suffix at specified depth.
Args:
depth (int): Split depth from right
Returns:
tuple: (prefix, suffix) as Name objects
"""Advanced name comparison and DNSSEC canonical form operations.
def canonicalize():
"""
Convert name to DNSSEC canonical form (lowercase).
Returns:
dns.name.Name: Canonicalized name
"""
def fullcompare(other):
"""
Perform full comparison with relationship information.
Args:
other (dns.name.Name): Name to compare with
Returns:
tuple: (order, labels_in_common, relationship)
order: -1, 0, or 1 for less than, equal, greater than
labels_in_common: number of common labels from right
relationship: NAMERELN_* constant
"""import dns.name
# Create names from text
name1 = dns.name.from_text('www.example.com.') # Absolute
name2 = dns.name.from_text('www.example.com') # Relative
name3 = dns.name.from_text('sub', dns.name.from_text('example.com.'))
print(f"Name 1: {name1}")
print(f"Is absolute: {name1.is_absolute()}")
print(f"Labels: {list(name1.labels)}")
# Name comparison
print(f"Equal: {name1 == name2.derelativize(dns.name.root)}")
print(f"Is subdomain: {name1.is_subdomain(dns.name.from_text('example.com.'))}")import dns.name
# Work with name hierarchy
fqdn = dns.name.from_text('mail.server.example.com.')
parent = fqdn.parent()
grandparent = parent.parent()
print(f"FQDN: {fqdn}")
print(f"Parent: {parent}")
print(f"Grandparent: {grandparent}")
# Split names
prefix, suffix = fqdn.split(2)
print(f"Prefix: {prefix}") # mail.server
print(f"Suffix: {suffix}") # example.com.
# Name concatenation
host = dns.name.from_text('www')
domain = dns.name.from_text('example.com.')
full_name = host.concatenate(domain)
print(f"Full name: {full_name}")import dns.name
# Handle Unicode domain names
unicode_name = 'тест.example.com'
name = dns.name.from_unicode(unicode_name)
print(f"Unicode input: {unicode_name}")
print(f"ASCII representation: {name.to_text()}")
print(f"Back to Unicode: {name.to_unicode()}")
# Specify IDNA codec
name_2008 = dns.name.from_unicode(unicode_name, idna_codec=dns.name.IDNA_2008)
name_2003 = dns.name.from_unicode(unicode_name, idna_codec=dns.name.IDNA_2003)import dns.name
# Wildcard names
wildcard = dns.name.from_text('*.example.com.')
print(f"Is wildcard: {wildcard.is_wild()}")
# Special names
root_name = dns.name.root
empty_name = dns.name.empty
print(f"Root name: '{root_name}'")
print(f"Empty name: '{empty_name}'")
print(f"Root is absolute: {root_name.is_absolute()}")import dns.name
name = dns.name.from_text('Example.COM.')
# Convert to wire format
wire_data = name.to_wire()
print(f"Wire format length: {len(wire_data)} bytes")
# Parse from wire format
parsed_name, pos = dns.name.from_wire(wire_data, 0)
print(f"Parsed name: {parsed_name}")
# Canonicalization for DNSSEC
canonical = name.canonicalize()
print(f"Original: {name}")
print(f"Canonical: {canonical}")
# Digestable format for hashing
digest_format = name.to_digestable()
print(f"Digest length: {len(digest_format)} bytes")# Special name instances
root = Name(()) # The root name '.'
empty = Name(()) # The empty name
# Name relationship constants
NAMERELN_NONE = 0 # No relationship
NAMERELN_SUPERDOMAIN = 1 # First is superdomain of second
NAMERELN_SUBDOMAIN = 2 # First is subdomain of second
NAMERELN_EQUAL = 3 # Names are equal
NAMERELN_COMMONANCESTOR = 4 # Names have common ancestor
# IDNA codecs
IDNA_2003 = ... # IDNA 2003 codec
IDNA_2008 = ... # IDNA 2008 codecclass EmptyLabel(DNSException):
"""A DNS label is empty."""
class BadEscape(DNSException):
"""An invalid escape sequence was encountered."""
class BadPointer(DNSException):
"""A compression pointer points forward instead of backward."""
class BadLabelType(DNSException):
"""An unknown label type was encountered."""
class NeedAbsoluteNameOrOrigin(DNSException):
"""An absolute name or origin is required."""
class NameTooLong(DNSException):
"""A DNS name is longer than 255 octets."""
class LabelTooLong(DNSException):
"""A DNS label is longer than 63 octets."""
class AbsoluteConcatenation(DNSException):
"""An attempt was made to append to an absolute name."""
class NoParent(DNSException):
"""An attempt was made to get the parent of the root or empty name."""
class NoIDNA2008(DNSException):
"""IDNA 2008 processing is not available."""
class IDNAException(DNSException):
"""IDNA processing raised an exception."""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