Simple library to encode/decode DNS wire-format packets
npx @tessl/cli install tessl/pypi-dnslib@0.9.0A comprehensive Python library for DNS wire-format packet encoding and decoding. Provides support for converting DNS packets between wire format, Python objects, and Zone/DiG textual representations, along with a server framework for creating custom DNS resolvers and utility modules for testing and development.
pip install dnslibimport dnslibMost common usage imports all DNS functionality:
from dnslib import *Module-specific imports:
from dnslib.server import DNSServer, BaseResolver
from dnslib.client import DiG
from dnslib.proxy import ProxyResolverimport binascii
from dnslib import *
# Parse a DNS packet from wire format
packet = binascii.unhexlify(b'd5ad818000010005000000000377777706676f6f676c6503636f6d0000010001c00c0005000100000005000803777777016cc010c02c0001000100000005000442f95b68c02c0001000100000005000442f95b63c02c0001000100000005000442f95b67c02c0001000100000005000442f95b93')
d = DNSRecord.parse(packet)
print(d) # Zone file format output
# Create a DNS query
q = DNSRecord.question("google.com")
print(q)
# Create a DNS query with specific record type
q = DNSRecord.question("google.com", "MX")
print(q)
# Create a DNS response
response = DNSRecord(
DNSHeader(qr=1, aa=1, ra=1),
q=DNSQuestion("example.com"),
a=RR("example.com", rdata=A("1.2.3.4"))
)
print(response)
# Create records from zone file format
rr = RR.fromZone("example.com IN A 1.2.3.4")
print(rr[0])
# Create a reply to a query
q = DNSRecord.question("example.com")
a = q.reply()
a.add_answer(*RR.fromZone("example.com 60 A 1.2.3.4"))
print(a)dnslib follows the standard DNS packet structure with these key components:
The library provides three main representations:
Core DNS packet encoding, decoding, and manipulation functionality supporting all standard DNS record types and DNSSEC extensions.
class DNSRecord:
def __init__(self, header=None, q=None, a=None, auth=None, ar=None): ...
@classmethod
def parse(cls, packet): ...
@classmethod
def question(cls, qname, qtype="A", qclass="IN"): ...
def pack(self): ...
def reply(self, ra=1, aa=1): ...
def replyZone(self, zone): ...
def add_question(self, q): ...
def add_answer(self, *rr): ...
def add_auth(self, *rr): ...
def add_ar(self, *rr): ...
class DNSHeader:
def __init__(self, id=None, **kwargs): ...
def pack(self): ...
@classmethod
def parse(cls, buffer): ...
class DNSQuestion:
def __init__(self, qname, qtype="A", qclass="IN"): ...
def pack(self): ...
@classmethod
def parse(cls, buffer): ...
class RR:
def __init__(self, rname, rtype="A", rclass="IN", ttl=0, rdata=None): ...
def pack(self): ...
@classmethod
def parse(cls, buffer): ...
@classmethod
def fromZone(cls, zone): ...Comprehensive support for DNS resource record types including address records, mail exchange, name servers, text records, and DNSSEC extensions.
class A:
def __init__(self, data): ...
class AAAA:
def __init__(self, data): ...
class MX:
def __init__(self, preference, mx): ...
class CNAME:
def __init__(self, label): ...
class TXT:
def __init__(self, data): ...
class SOA:
def __init__(self, mname, rname, times): ...Framework for creating custom DNS resolvers with UDP/TCP server support, request handling, and logging capabilities.
class DNSServer:
def __init__(self, resolver, port=53, address="", logger=None, **kwargs): ...
def start(self): ...
def start_thread(self): ...
class BaseResolver:
def resolve(self, request, handler): ...
class DNSLogger:
def __init__(self, log="request,reply,truncated,error", prefix=True, logf=None): ...
def log_recv(self, handler, data): ...
def log_send(self, handler, data): ...DiG-like DNS client functionality for querying DNS servers, comparing responses, and debugging DNS configurations.
class DiG:
def __init__(self, **kwargs): ...
def query(self, name, qtype="A", qclass="IN", **kwargs): ...
def compare(self, response1, response2): ...Ready-to-use resolver implementations including proxy resolvers, fixed response resolvers, zone file resolvers, and shell script resolvers.
class ProxyResolver(BaseResolver):
def __init__(self, address, port, timeout=0): ...
def resolve(self, request, handler): ...
class FixedResolver(BaseResolver):
def __init__(self, zone): ...
def resolve(self, request, handler): ...
class ZoneResolver(BaseResolver):
def __init__(self, zone, glob=False): ...
def resolve(self, request, handler): ...# DNS record type mappings
QTYPE = Bimap(A=1, NS=2, CNAME=5, SOA=6, MX=15, TXT=16, AAAA=28, ...)
# DNS class mappings
CLASS = Bimap(IN=1, CS=2, CH=3, HS=4)
# Response code mappings
RCODE = Bimap(NOERROR=0, FORMERR=1, SERVFAIL=2, NXDOMAIN=3, ...)
# Operation code mappings
OPCODE = Bimap(QUERY=0, IQUERY=1, STATUS=2, NOTIFY=4, UPDATE=5)
# Query/Response flag
QR = Bimap(QUERY=0, RESPONSE=1)class DNSError(Exception): ...
class DNSLabelError(Exception): ...
class BufferError(Exception): ...
class BimapError(Exception): ...dnslib provides several command-line utilities accessible via Python module execution:
python -m dnslib.client --helppython -m dnslib.proxy --helppython -m dnslib.intercept --helppython -m dnslib.fixedresolver --helppython -m dnslib.zoneresolver --helppython -m dnslib.shellresolver --help