CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-dnspython

DNS toolkit for Python supporting almost all record types with high-level and low-level DNS operations

85

1.37x
Overview
Eval results
Files

dns-messages.mddocs/

DNS Messages

DNS message manipulation functionality for creating, parsing, and modifying DNS protocol messages. Provides complete control over DNS message structure including headers, questions, answers, authority, and additional sections.

Capabilities

Message Creation

Create DNS query and response messages with full protocol support.

def make_query(qname, rdtype, rdclass='IN', use_edns=None, want_dnssec=False,
               ednsflags=None, payload=None, request_payload=None, options=None):
    """
    Create a DNS query message.
    
    Args:
        qname (str or dns.name.Name): Query name
        rdtype (str or int): Record type to query
        rdclass (str or int): Record class (default 'IN')
        use_edns (int): EDNS version (None to disable, 0 for EDNS0)
        want_dnssec (bool): Set DNSSEC OK bit
        ednsflags (int): EDNS flags
        payload (int): EDNS payload size
        request_payload (int): Requested payload size
        options (list): EDNS options
        
    Returns:
        dns.message.Message: DNS query message
    """

def make_response(query, recursion_available=False, our_payload=8192, fudge=300):
    """
    Create a DNS response message from a query.
    
    Args:
        query (dns.message.Message): Original query message
        recursion_available (bool): Set RA bit
        our_payload (int): Our EDNS payload size
        fudge (int): TSIG time fudge factor
        
    Returns:
        dns.message.Message: DNS response message
    """

Message Parsing

Parse DNS messages from wire format, text format, or files.

def from_wire(wire, keyring=None, request_mac=b'', xfr=False, origin=None,
              tsig_ctx=None, multi=False, first=True, question_only=False,
              one_rr_per_rrset=False, ignore_trailing=False):
    """
    Parse a DNS message from wire format.
    
    Args:
        wire (bytes): Wire format message
        keyring (dict): TSIG keyring for validation
        request_mac (bytes): TSIG MAC from request
        xfr (bool): Message is part of zone transfer
        origin (dns.name.Name): Origin for relative names
        tsig_ctx (dns.tsig.HMACTSig): TSIG context
        multi (bool): Message is part of multi-message response
        first (bool): First message in multi-message response
        question_only (bool): Parse question section only
        one_rr_per_rrset (bool): Put each RR in its own RRset
        ignore_trailing (bool): Ignore trailing junk
        
    Returns:
        dns.message.Message: Parsed DNS message
    """

def from_text(text):
    """
    Parse a DNS message from text format.
    
    Args:
        text (str): Text format message
        
    Returns:
        dns.message.Message: Parsed DNS message
    """

def from_file(f):
    """
    Read and parse a DNS message from a file.
    
    Args:
        f (file-like): File to read from
        
    Returns:
        dns.message.Message: Parsed DNS message
    """

Message Class

Complete DNS message with header and sections for questions, answers, authority, and additional records.

class Message:
    """
    A DNS message with header and sections.
    
    Attributes:
        id (int): Message ID
        flags (int): Header flags
        question (list): Question section
        answer (list): Answer section  
        authority (list): Authority section
        additional (list): Additional section
        opt (dns.edns.OPT): EDNS OPT record
        tsig (dns.rdata.Rdata): TSIG record
        request_payload (int): Requested EDNS payload size
        keyring (dict): TSIG keyring
        mac (bytes): TSIG MAC
        xfr (bool): Message is part of zone transfer
        origin (dns.name.Name): Origin for relative names
        tsig_ctx (dns.tsig.HMACTSig): TSIG context
    """
    
    def __init__(self, id=None):
        """
        Initialize DNS message.
        
        Args:
            id (int): Message ID (random if None)
        """
    
    def __repr__(self):
        """Return string representation of message."""
    
    def __str__(self):
        """Return string representation of message."""
    
    def to_wire(self, origin=None, max_size=0, **kw):
        """
        Convert message to wire format.
        
        Args:
            origin (dns.name.Name): Origin for relative names
            max_size (int): Maximum message size
            **kw: Additional options
            
        Returns:
            bytes: Wire format message
        """
    
    def to_text(self, origin=None, relativize=True, **kw):
        """
        Convert message to text format.
        
        Args:
            origin (dns.name.Name): Origin for relative names
            relativize (bool): Relativize names to origin
            **kw: Additional options
            
        Returns:
            str: Text format message
        """
    
    def is_response(self, other):
        """
        Check if this message is a response to another message.
        
        Args:
            other (dns.message.Message): Potential query message
            
        Returns:
            bool: True if this is a response to other
        """
    
    def is_valid_response(self):
        """
        Check if message is a valid response.
        
        Returns:
            bool: True if valid response
        """

Message Section Operations

Find, get, and manipulate RRsets within message sections.

def find_rrset(section, name, rdclass, rdtype, covers='NONE', deleting=None,
               create=False, force_unique=False):
    """
    Find an RRset in the specified message section.
    
    Args:
        section (int): Message section (QUESTION, ANSWER, AUTHORITY, ADDITIONAL)
        name (dns.name.Name): Record name
        rdclass (int): Record class
        rdtype (int): Record type
        covers (int): Covered type for RRSIG records
        deleting (int): Deletion indicator for dynamic updates
        create (bool): Create RRset if not found
        force_unique (bool): Force unique names
        
    Returns:
        dns.rrset.RRset: Found or created RRset
    """

def get_rrset(section, name, rdclass, rdtype, covers='NONE', deleting=None,
              create=False, force_unique=False):
    """
    Get an RRset from the specified message section.
    
    Args:
        section (int): Message section
        name (dns.name.Name): Record name  
        rdclass (int): Record class
        rdtype (int): Record type
        covers (int): Covered type for RRSIG records
        deleting (int): Deletion indicator
        create (bool): Create RRset if not found
        force_unique (bool): Force unique names
        
    Returns:
        dns.rrset.RRset or None: Found RRset or None
    """

EDNS and TSIG Configuration

Configure extended DNS (EDNS) and transaction signatures (TSIG) for messages.

def use_edns(edns=0, ednsflags=0, payload=1280, request_payload=None, options=None):
    """
    Configure EDNS for this message.
    
    Args:
        edns (int): EDNS version (0 for EDNS0, -1 to disable)
        ednsflags (int): EDNS flags
        payload (int): Payload size
        request_payload (int): Requested payload size
        options (list): EDNS options
    """

def use_tsig(keyring, keyname=None, fudge=300, original_id=None, tsig_error=0,
             other_data=b'', algorithm='HMAC-MD5.SIG-ALG.REG.INT'):
    """
    Configure TSIG for this message.
    
    Args:
        keyring (dict): TSIG keyring
        keyname (dns.name.Name): Key name
        fudge (int): Time fudge factor
        original_id (int): Original message ID
        tsig_error (int): TSIG error code
        other_data (bytes): Additional TSIG data
        algorithm (str): TSIG algorithm name
    """

def want_dnssec(wanted=True):
    """
    Enable or disable DNSSEC DO bit.
    
    Args:
        wanted (bool): Enable DNSSEC
    """

Message Properties

Access message header fields and computed properties.

def id():
    """Get message ID."""

def flags():
    """Get header flags."""

def rcode():
    """Get response code."""

def opcode():
    """Get operation code."""

def question_for_answer():
    """Get question corresponding to first answer."""

def had_tsig():
    """Check if message had TSIG."""

def tsig_error():
    """Get TSIG error code."""

def mac():
    """Get TSIG MAC."""

Usage Examples

Creating Query Messages

import dns.message
import dns.name
import dns.rdatatype

# Basic query
qname = dns.name.from_text('example.com')
query = dns.message.make_query(qname, dns.rdatatype.A)

# Query with EDNS and DNSSEC
query_edns = dns.message.make_query(
    qname, dns.rdatatype.DNSKEY, 
    use_edns=0, 
    want_dnssec=True, 
    payload=4096
)

# Multiple questions (not common but supported)
query = dns.message.Message()
query.id = dns.entropy.random_16()
query.flags = dns.flags.RD  # Recursion desired
query.find_rrset(dns.message.QUESTION, qname, dns.rdataclass.IN, 
                dns.rdatatype.A, create=True)

Parsing Wire Format

import dns.message

# Parse raw DNS packet
wire_data = b'\x12\x34\x01\x00...'  # Raw DNS packet bytes
message = dns.message.from_wire(wire_data)

print(f"Message ID: {message.id}")
print(f"Response code: {message.rcode()}")
print(f"Question count: {len(message.question)}")
print(f"Answer count: {len(message.answer)}")

# Process answers
for rrset in message.answer:
    print(f"Name: {rrset.name}")
    print(f"Type: {rrset.rdtype}")
    for rdata in rrset:
        print(f"  Data: {rdata}")

Creating Response Messages

import dns.message
import dns.rrset
import dns.rdata
import dns.rdataclass
import dns.rdatatype

# Create response from query
query = dns.message.make_query('example.com', dns.rdatatype.A)  
response = dns.message.make_response(query, recursion_available=True)

# Add answer records
answer_rrset = dns.rrset.from_text('example.com', 300, 'IN', 'A', '192.0.2.1')
response.answer.append(answer_rrset)

# Set response code
response.set_rcode(dns.rcode.NOERROR)

# Convert to wire format for transmission
wire_response = response.to_wire()

Working with Message Sections

import dns.message
import dns.name
import dns.rdatatype
import dns.rdataclass

message = dns.message.from_wire(wire_data)

# Find specific RRset
name = dns.name.from_text('example.com')
rrset = message.find_rrset(dns.message.ANSWER, name, 
                          dns.rdataclass.IN, dns.rdatatype.A)

if rrset:
    print(f"Found {len(rrset)} A records for {name}")
    for rdata in rrset:
        print(f"  {rdata.address}")

# Check all sections
sections = [
    (dns.message.QUESTION, message.question, "Question"),
    (dns.message.ANSWER, message.answer, "Answer"),
    (dns.message.AUTHORITY, message.authority, "Authority"),
    (dns.message.ADDITIONAL, message.additional, "Additional")
]

for section_id, section_list, section_name in sections:
    print(f"{section_name} section: {len(section_list)} RRsets")

Constants

# Message sections
QUESTION = 0
ANSWER = 1  
AUTHORITY = 2
ADDITIONAL = 3

# Header flags
QR = 0x8000    # Query/Response
AA = 0x0400    # Authoritative Answer
TC = 0x0200    # Truncated
RD = 0x0100    # Recursion Desired
RA = 0x0080    # Recursion Available
AD = 0x0020    # Authentic Data
CD = 0x0010    # Checking Disabled

Exceptions

class ShortHeader(DNSException):
    """A DNS packet is too short to contain a complete header."""

class TrailingJunk(DNSException):
    """There is trailing junk after the end of the DNS message."""

class UnknownHeaderField(DNSException):
    """An unknown header field name was specified."""

class BadEDNS(DNSException):
    """An OPT record was found somewhere other than the additional section."""

class BadTSIG(DNSException):
    """A TSIG record was found somewhere other than the end of the additional section."""

class UnknownTSIGKey(DNSException):
    """A TSIG record was received with an unknown key."""

Install with Tessl CLI

npx tessl i tessl/pypi-dnspython

docs

dns-constants.md

dns-exceptions.md

dns-messages.md

dns-names.md

dns-queries.md

dns-records.md

dns-resolution.md

dns-updates.md

dns-utilities.md

dns-zones.md

dnssec.md

index.md

tsig.md

tile.json