Friday, May 13, 2011

Reverse DNS Lookups with Python


Update 12/22/2014 -- Today I would recommend using the dnspython module instead of PyDNS.

I am neither a professional programmer nor a Python expert, but it's currently my language of choice for quick log parsing projects. I couldn't find an example of how to do reverse DNS queries from the PyDNS library, so I figured I'd post my solution here.

First, install the PyDNS library. Python has some native DNS stuff, but PyDNS just seems a lot nicer overall.

Here's my code to do a PTR query, looking up a IPv4 address to find the corresponding DNS name. This code implements a global dictionary of addresses that have been previously resolved, avoiding the need to query the server repeatedly for the same address. You could remove that part if you're feeding a set of unique addresses into the function.

import  DNS
SERVER = '8.8.8.8' # put your DNS server address here
global ptr_cache

ptr_cache = {}

def get_ptr(address):
    # check cache.    
    if ptr_cache.has_key(address):
         return ptr_cache[address]
   
    #reverse fields in IP address for use with in-addr.arpa query
    fields = address.split('.')
    fields.reverse()
    flippedaddr = '.'.join(fields)

    #query DNS
    d = DNS.DnsRequest(server=DNS_SERVER,timeout=1)
    try:
        r = d.req(flippedaddr+'.in-addr.arpa',qtype='PTR')
    except:
        return "DNS Error"
   
    name = r.answers[0]['data']
    if name:
        ptr_cache[address] = name
    return name

4 comments:

Sandip Shah said...

Hi,

Std Python lib includes socket.gethostbyaddr(ip_addr) which will do the same.

SS

Saurabh said...

Sandip - that would work but as per http://stackoverflow.com/questions/5078338/python-how-to-tell-socket-gethostbyaddr-which-dns-server-to-use you can't specify which DNS server to use. PyDNS would fill that gap.

Saurabh said...

Thanks for sharing this Jay. Minor correction - your constant is SERVER and you are using DNS_SERVER in the code.

Jay Swan said...

Saurabh,

Today I would recommend using the dnspython library instead. It's much more versatile.

I'll add an update to the post to reflect this.