[ldns-users] Writing a DNS AXFR proxy in Python with ldns

Jason Fogel (BLOOMBERG/ 120 PARK) jfogel2 at bloomberg.net
Tue Sep 19 20:45:42 UTC 2017


My scenario is that I'm writing a DNS AXFR proxy in Python, using ldns. Basically, we want to insert a proxy between our DNS server and various unreliable hidden master backends. So instead of our server directly performing AXFR against those hidden masters, it will perform them against the proxy, which will in turn perform the AXFR against the hidden master, validate the results in various ways, and send the data back to our DNS server.

I was able to start a server listening for DNS requests and parse client AXFR requests. It's easy enough to then perform an AXFR with ldns, which gives me nice RR objects I can easily validate. However, I'm struggling to figure out how to then turn those RRs back into something I can send to the client on the wire via python's socket interface. I'm sure it has something to do with converting it to wire format and using struct to pack it, but I can't quite figure it out. Here's approximately what I have so far:

connection, address = socket.accept()
data = connection.recv(self.buffer_size)
# I use dnslib here to parse out the zone_name of the AXFR query
# [...]
resolver = ldns.ldns_resolver.new_frm_file('resolv.test')
start_status = resolver.axfr_start(zone_name, ldns.LDNS_RR_CLASS_IN)
if start_status != ldns.LDNS_STATUS_OK:
    raise Exception("Can't start AXFR. Error: %s" % ldns.ldns_get_errorstr_by_id(start_status))
# Loop through the RRs as we get them
while True:
    rr = resolv.axfr_next()
    if not rr:
        # End of AXFR
        break
    # Do various checks to validate the RR
    # [...]
    # Extract the wire data from the rr
    buff = ldns.ldns_buffer(self.buffer_size)
    char_list = []
    rr._ldns_rr.write_to_buffer(buff, 1)
    while buff.remaining() > 0:
        char_list.append(buff.getc())


Using getc() seems to let me pull out the RR in wire format one character at a time as ASCII code INTs. I can use chr() to convert these to characters, but after that I'm pretty lost for how to use struct to convert that to binary data and send it back over the socket. Preferably I'd like to do this as a I receive the data, because some of the zones are very large (250k+ records) and I don't want to wait until the transfer has completed to start proxying it back.

Thank you!

- Jason Fogel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.nlnetlabs.nl/pipermail/ldns-users/attachments/20170919/75f69596/attachment.htm>


More information about the ldns-users mailing list