dnslib
dnslib is a simple Python library designed to encode and decode DNS wire-format packets. It provides comprehensive support for converting DNS packets between wire format, Python objects, and human-readable Zone/DiG textual representations. Additionally, it offers a server framework that facilitates the creation of custom DNS resolvers. The library is currently at version 0.9.26 and is in maintenance mode, with no further active development planned.
Warnings
- deprecated The dnslib library is in maintenance mode and no longer undergoes active development. While minor bug fixes may be applied, significant new features or major architectural changes are not expected. Users should factor this into long-term project planning.
- breaking Python 2.7 support has been officially dropped. Version 0.9.24 was the last release to support Python 2.7 and Python <3.7. Later versions require Python 3.7+ (though the 0.9.25 release notes refer to 'Python2 support' in the context of maintenance mode for users reliant on the old API).
- breaking Significant API changes occurred around version 0.9.0 and were further referenced in 0.9.25. Specifically, the 'Bimap' interface for lookups changed, and hostnames are now returned with a trailing dot by default (RFC compliant). Updating from older `dnslib` versions might require code adjustments for these interface changes.
- gotcha There's a reported issue (Issue #76) where RFC2136 delete UPDATEs are parsed differently between versions. Version 0.9.24 would parse them with `rdata=''`, while 0.9.25+ rejects them, raising an error. This can affect specific DNS update operations.
Install
-
pip install dnslib
Imports
- DNSRecord
from dnslib import DNSRecord, DNSHeader, DNSQuestion, QTYPE, RR, A, CNAME, MX, NS, SOA
- *
from dnslib import *
Quickstart
from dnslib import DNSRecord, DNSHeader, DNSQuestion, QTYPE, RR, A, CNAME
import binascii
# --- Example 1: Creating a simple DNS A query ---
q = DNSRecord(q=DNSQuestion('example.com', QTYPE.A))
print('--- DNS Query (example.com A) ---\n', q)
# Pack the query to wire format
query_packet = q.pack()
# print(f'Wire format: {binascii.hexlify(query_packet).decode()}')
# --- Example 2: Parsing a DNS response (simulated) ---
# Example DNS response packet (e.g., for google.com A record)
# In a real scenario, this would come from a network socket.
# d5ad818000010005000000000377777706676f6f676c6503636f6d0000010001c00c0005000100000005000803777777016cc010c02c0001000100000005000442f95b68c02c0001000100000005000442f95b63c02c0001000100000005000442f95b67c02c0001000100000005000442f95b93
# A simplified, small response for 'test.com' to 1.2.3.4
# Real packets are more complex, this is just for demonstration.
response_hex = b'\x01\x00\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00\x04test\x03com\x00\x00\x01\x00\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04\x01\x02\x03\x04'
response_packet = response_hex
# Parse the response packet
try:
r = DNSRecord.parse(response_packet)
print('\n--- Parsed DNS Response (test.com A to 1.2.3.4) ---\n', r)
except Exception as e:
print(f"Error parsing response: {e}")
# --- Example 3: Creating a reply from a query (simplified) ---
q_example = DNSRecord(q=DNSQuestion('host.example.com'))
reply = q_example.reply()
reply.add_answer(RR('host.example.com', QTYPE.A, rdata=A('192.168.1.1')))
print('\n--- Simple DNS Reply ---\n', reply)