Skip to content

Instantly share code, notes, and snippets.

@lucab
Created December 29, 2015 15:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lucab/47e2214b962234a924b0 to your computer and use it in GitHub Desktop.
Save lucab/47e2214b962234a924b0 to your computer and use it in GitHub Desktop.
Scan authoritative NS trying to AXFR zones
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Scan authoritative NS trying to AXFR zones.
Result dictionary is as follows:
{
'domain': 'example.com',
'axfr_answers': {'ns1.example.com': [],
'ns2.example.com': [],
'ns3.example.com': [],
'ns4.example.com': [{'name': '@',
'pretty_name': 'example.com',
'pretty_rdclass': 'IN',
'pretty_rdtype': 'A',
'rdata': '',
'rdclass': 1,
'rdtype': 1,
'ttl': 86400}]},
'nameservers': ['ns1.example.com',
'ns2.example.com',
'ns3.example.com',
'ns4.example.com']}
}
"""
__author__ = "Luca Bruno"
__email__ = "lucab@debian.org"
# this module requires dnspython
import bisect
import dns.name
import dns.query
import dns.rdataclass
import dns.rdatatype
import dns.resolver
import dns.zone
def scan_dns_axfr(domain):
"""
Scan authoritative NS trying to AXFR a zone
@param domain: the domain we try to AXFR
@type domain: string
@rtype: dict
@return: dictionary with zone info
"""
AXFR_TIMEOUT = float(10) # AXFR timeout, in seconds
zone_data = {'domain': domain}
zone_data['nameservers'] = []
zone_data['axfr_answers'] = {}
try:
ns_query = dns.resolver.query(domain, 'NS').rrset
except Exception:
ns_query = []
for n in ns_query:
zone_content = []
ns = str(n).rstrip('.')
if not ns:
continue
bisect.insort(zone_data['nameservers'], ns)
zone_data['axfr_answers'][ns] = zone_content
try:
axfr_rr = dns.query.xfr(ns, domain, lifetime=AXFR_TIMEOUT)
axfr_zone = dns.zone.from_xfr(axfr_rr)
except Exception:
axfr_zone = None
if not axfr_zone:
continue
for name, ttl, rdata in axfr_zone.iterate_rdatas():
entry = {'name': name.to_text(),
'ttl': ttl,
'rdclass': rdata.rdclass,
'rdtype': rdata.rdtype,
'rdata': rdata.to_text()}
try:
entry['pretty_rdclass'] = dns.rdataclass.to_text(rdata.rdclass)
entry['pretty_rdtype'] = dns.rdatatype.to_text(rdata.rdtype)
parent = dns.name.Name(domain.split('.'))
if name == dns.name.empty:
entry['pretty_name'] = parent.to_text()
else:
entry['pretty_name'] = name.concatenate(parent).to_text()
except Exception:
pass
zone_content.append(entry)
zone_data['axfr_answers'][ns] = zone_content
return zone_data
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment