No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

dnshelper.py 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import dns.name
  2. import dns.message
  3. import dns.query
  4. import dns.resolver
  5. #from collections import defaultdict
  6. # FIXME: DNS timeouts
  7. def compareRecords(rrset, expected):
  8. result = {
  9. "nameMissing": [],
  10. "rrMissing": [],
  11. "rrExtra": [],
  12. }
  13. for domain, rrtype, content in expected:
  14. for rrrec in rrset:
  15. if domain == rrrec.name.to_text() and dns.rdatatype.from_text(rrtype) == rrrec.rdtype:
  16. for name in content:
  17. if name not in map(lambda _x: _x.to_text(), rrrec.items):
  18. # record missing
  19. result["rrMissing"].append((domain, rrtype, name))
  20. for item in rrrec.items:
  21. if item.to_text() not in content:
  22. # superfluous record
  23. result["rrExtra"].append((domain, rrtype, item.to_text()))
  24. break
  25. else:
  26. # domain + rr nicht in nameserver
  27. result["nameMissing"].append((domain, rrtype))
  28. success = not any(len(_x) > 0 for _x in result.values())
  29. print("NARF", success, result)
  30. return success, result
  31. def dnsQuery(domain, rrType, nameserverIp):
  32. dname = dns.name.from_text(domain)
  33. req = dns.message.make_query(dname, dns.rdatatype.from_text(rrType))
  34. resp = dns.query.udp(req, nameserverIp, timeout=2.0)
  35. if resp.rcode() != dns.rcode.NXDOMAIN:
  36. rrset = resp.answer + resp.authority + resp.additional
  37. return True, rrset
  38. else:
  39. return False, []
  40. def checkDomain(domain, tldNameserver, nameservers):
  41. print(domain, tldNameserver, nameservers)
  42. result = []
  43. # build record set
  44. nsRecords = [(domain, "NS", list(ns.name for ns in nameservers))]
  45. glueRecords = []
  46. for ns in nameservers:
  47. if ns.name.endswith("." + domain):
  48. if ns.glueIPv4 or ns.glueIPv6:
  49. if ns.glueIPv4:
  50. glueRecords.append((ns.name, "A", [ns.glueIPv4]))
  51. if ns.glueIPv6:
  52. glueRecords.append((ns.name, "AAAA", [ns.glueIPv6]))
  53. else:
  54. result.append(("err", "Nameserver %s is under domain %s, but has no glue entries." % (ns.name, domain)))
  55. print(nsRecords, glueRecords)
  56. # 1. TLD nameserver
  57. try:
  58. found, rrset = dnsQuery(domain, "ANY", tldNameserver)
  59. if found:
  60. #print(rrset, nsRecords, glueRecords)
  61. success, errors = compareRecords(rrset, nsRecords + glueRecords)
  62. if success:
  63. result.append(("succ", "All records present in TLD nameserver"))
  64. else:
  65. result.append(("err", "Record mismatch between TLD nameserver and WHOIS database", errors))
  66. else:
  67. result.append(("err", "Domain %s not found in TLD nameserver" % (domain,)))
  68. except (dns.exception.Timeout, OSError):
  69. result.append(("err", "TLD nameserver is currently not reachable"))
  70. # find other records...
  71. # 2. your nameservers
  72. for ns in nameservers:
  73. addr = None
  74. if ns.glueIPv4:
  75. addr = ns.glueIPv4
  76. elif ns.glueIPv6:
  77. addr = ns.glueIPv6
  78. else:
  79. for rrType in ("A", "AAAA"):
  80. try:
  81. r = dns.resolver.Resolver()
  82. r.timeout = 2.0
  83. q = r.query(ns.name, rdtype=dns.rdatatype.from_text(rrType))
  84. addr = q.response.answer[0].items[0].address
  85. except (dns.exception.DNSException, OSError):
  86. pass
  87. if addr:
  88. err = False
  89. errDict = {"nameMissing": [], "rrMissing": [], "rrExtra": []}
  90. try:
  91. for rec in (nsRecords + glueRecords):
  92. found, rrset = dnsQuery(rec[0], rec[1], addr)
  93. success, errors = compareRecords(rrset, nsRecords + glueRecords)
  94. if not success:
  95. err = True
  96. for k in errors.keys():
  97. errDict[k].extend(errors[k])
  98. if not err:
  99. result.append(("succ", "Nameserver %s is configured correctly" % ns.name))
  100. else:
  101. print(" ==> ", errDict, addr)
  102. result.append(("err", "Nameserver %s recordset does not match the database" % (ns.name,), errDict))
  103. except (dns.exception.DNSException, OSError):
  104. result.append(("err", "Nameserver %s is not reachable (via %s)" % (ns.name, addr)))
  105. else:
  106. result.append(("err", "Can't resolv an ip address for nameserver %s" % ns.name))
  107. return result