Frode F.
Frode F.

Reputation: 54821

Parsing DNS RDATA using python

I'm trying to use Python to parse hex-formated DNS RDATA-values (should be RFC1035-compliant) that's generated in audit logs from Windows DNS Server when a record is created or deleted. I've tried a couple of Python dns-modules and think I'm getting close with dnslib, however all the documentation I find is for parsing a complete DNS-packet captured from the network including question and answer header ++.

The audit log only provides the class type and the RDATA it stores in AD (Active Directory-integrated zone), so I figured I might be able to use the parse(buffer,length) method of the individual record type-classes to parse it, but so far all my attempts are failing.

Sample data:

Type = MX

RDATA = 0A0011737276312E636F6E746F736F2E636F6D2E

Which should be parsed to:

preference = 10

mx = srv1.contoso.com.

Latest attempt:

import dnslib
import binascii

mxrdata = binascii.unhexlify(b'0A0011737276312E636F6E746F736F2E636F6D2E')
b = dnslib.DNSBuffer(mxrdata)
mx = dnslib.MX.parse(b,len(b))

this fails with:

Traceback (most recent call last):
  File "C:\Python37-32\lib\site-packages\dnslib\dns.py", line 1250, in parse
    mx = buffer.decode_name()
  File "C:\Python37-32\lib\site-packages\dnslib\label.py", line 235, in decode_name
    (length,) = self.unpack("!B")
  File "C:\Python37-32\lib\site-packages\dnslib\buffer.py", line 103, in unpack
    data = self.get(struct.calcsize(fmt))
  File "C:\Python37-32\lib\site-packages\dnslib\buffer.py", line 64, in get
    (self.offset,self.remaining(),length))
dnslib.buffer.BufferError: Not enough bytes [offset=20,remaining=0,requested=1]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python37-32\lib\site-packages\dnslib\dns.py", line 1254, in parse
    (buffer.offset,e))
dnslib.dns.DNSError: Error unpacking MX [offset=20]: Not enough bytes [offset=20,remaining=0,requested=1]

Can anyone help me? Is it even possible using this module?

Upvotes: 3

Views: 2213

Answers (1)

Ctx
Ctx

Reputation: 18410

You are encoding the RDATA wrongly a bit:

First, you specify the preference:

0A00

However, this is not 10 (because integer are encoded MSB first, not LSB first), but 2560. So this should be

000A

Then, you try to encode the hostname here:

11737276312E636F6E746F736F2E636F6D2E

0x11 should be the length byte and the rest is the domain name srv1.contoso.com.. But this is not how encoding a hostname works. You have to encode each label separately with a length byte and terminate the hostname with a 0-length label. So this should be:

04 73727631 07 636F6E746F736F 03 636F6D 00
   s r v 1  .  c o n t o s o  .  c o m  .

This adds up to:

mxrdata = binascii.unhexlify(b'000A047372763107636F6E746F736F03636F6D00')

Them the parser should succeed. So if you really get the RDATA in such an invalid format, you have to convert it first in to make it rfc1035-compliant.

Upvotes: 2

Related Questions