pythondnsdnspython

How can I find the authoritative DNS server for a domain using dnspython?


As part of a tool I'm writing I want to have a diagnostic that will tell the user whether they have configured their domain's DNS correctly for a particular service. I want to query the authoritative DNS server for their domain so that I can bypass any cached results.


Solution

  • Here's my attempt at this. It uses the system's standard DNS server for looking up the root server for the top-level domain and for resolving the names of the various DNS servers along the chain, which I think is appropriate because those names would presumably change very infrequently.

    import dns
    import dns.name
    import dns.query
    import dns.resolver
    
    def get_authoritative_nameserver(domain, log=lambda msg: None):
        n = dns.name.from_text(domain)
    
        depth = 2
        default = dns.resolver.get_default_resolver()
        nameserver = default.nameservers[0]
    
        last = False
        while not last:
            s = n.split(depth)
    
            last = s[0].to_unicode() == u'@'
            sub = s[1]
    
            log('Looking up %s on %s' % (sub, nameserver))
            query = dns.message.make_query(sub, dns.rdatatype.NS)
            response = dns.query.udp(query, nameserver)
    
            rcode = response.rcode()
            if rcode != dns.rcode.NOERROR:
                if rcode == dns.rcode.NXDOMAIN:
                    raise Exception('%s does not exist.' % sub)
                else:
                    raise Exception('Error %s' % dns.rcode.to_text(rcode))
    
            rrset = None
            if len(response.authority) > 0:
                rrset = response.authority[0]
            else:
                rrset = response.answer[0]
    
            rr = rrset[0]
            if rr.rdtype == dns.rdatatype.SOA:
                log('Same server is authoritative for %s' % sub)
            else:
                authority = rr.target
                log('%s is authoritative for %s' % (authority, sub))
                nameserver = default.query(authority).rrset[0].to_text()
    
            depth += 1
    
        return nameserver
    
    
    import sys
    
    def log(msg):
        print msg
    
    print get_authoritative_nameserver(sys.argv[1], log)
    

    Here's some sample output:

    Looking up com. on 192.168.255.10
    l.gtld-servers.net. is authoritative for com.
    Looking up stackoverflow.com. on 192.41.162.30
    ns1.p19.dynect.net. is authoritative for stackoverflow.com.
    Looking up meta.stackoverflow.com. on 208.78.70.19
    Same server is authoritative for meta.stackoverflow.com.
    208.78.70.19