Skip to content

Instantly share code, notes, and snippets.

@paulc
Created February 2, 2022 18:04
Show Gist options
  • Save paulc/2b74376ebf305e89512e013ae3444ff5 to your computer and use it in GitHub Desktop.
Save paulc/2b74376ebf305e89512e013ae3444ff5 to your computer and use it in GitHub Desktop.
resolve.py - simple recursive DNS resolver
from dnslib import DNSRecord,DNSError,QTYPE
ROOT_NS='198.41.0.4'
def find_cname(a,qtype,cname):
for r in a.rr:
if QTYPE[r.rtype] == qtype and r.rname == cname:
return str(r.rdata)
elif QTYPE[r.rtype] == 'CNAME' and r.rname == cname:
return find_cname(a,qtype,str(r.rdata))
return resolve(str(r.rdata),qtype,ROOT_NS)
def resolve(name,qtype='A',ns=ROOT_NS):
print(f"dig -r @{ns} {name} {qtype}")
q = DNSRecord.question(name,qtype)
a = DNSRecord.parse(q.send(ns))
if q.header.id != a.header.id:
raise DNSError('Response transaction id does not match query transaction id')
for r in a.rr:
if QTYPE[r.rtype] == qtype and r.rname == name:
return str(r.rdata)
elif QTYPE[r.rtype] == 'CNAME' and r.rname == name:
return find_cname(a,qtype,str(r.rdata))
for r in a.ar:
if QTYPE[r.rtype] == 'A':
return resolve(name,qtype,str(r.rdata))
for r in a.auth:
if QTYPE[r.rtype] == 'NS':
return resolve(name,qtype,resolve(str(r.rdata),'A',ROOT_NS))
raise ValueError("Cant resolve domain")
if __name__ == '__main__':
import sys
def get_arg(i,d):
try: return sys.argv[i]
except IndexError: return d
print(resolve(get_arg(1,"google.com"), get_arg(2,"A"), get_arg(3,ROOT_NS)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment