diff --git a/validate-my-dns.py b/validate-my-dns.py index 906d6b3..f021b59 100644 --- a/validate-my-dns.py +++ b/validate-my-dns.py @@ -27,11 +27,15 @@ except ImportError: import dns.exception import binascii +# counter of errors that occured +errors= 0 # step1: def get_domain_by_mntner(mntner): + global errors + """get a list of domains (and reverse ipv4/6) if a nserver is specified""" # grep for the given mntner in the dns,inetnum,inet6num directory of the registry and split it into a list; replace // with / in case REGISTRY_PATH ends with / dns_files = subprocess.Popen(["grep", "-Ril", f" {mntner}", f"{REGISTRY_PATH}/data/dns/"], @@ -173,21 +177,24 @@ def get_domain_by_mntner(mntner): def get_dnskey(domain_name, nserver): """query dns server for DNSKEY""" - + global errors try: request = dns.message.make_query( domain_name, dns.rdatatype.DNSKEY, want_dnssec=False) response = dns.query.udp_with_fallback(request, nserver, timeout=2) except dns.exception.Timeout: print(f"WARN: querying {nserver} for {domain_name} timed out") + errors += 1 return False except dns.query.UnexpectedSource as e: print(f"ERROR: server replied with different different ip than requested: error: {e}") + errors += 1 return False if response[0].rcode() != 0: # HANDLE QUERY FAILED (SERVER ERROR OR NO DNSKEY RECORD) print( f"WARN: query for a DNSKEY on {domain_name} failed on {nserver}, returncode: {response[0].rcode()}") + errors += 1 return False return [dnskey.to_text().split("IN DNSKEY ")[1] for dnskey in response[0].answer] # if not nserver: @@ -299,13 +306,14 @@ def dnskey_to_ds(domain, dnskey): def check_dnssec(domain_name, domain_data): - + global errors success = False no_ds_rdata = domain_data["ds-rdata"] == [] if no_ds_rdata: print( f"NOTE: {domain_name} doesn't have ds-rdata configured, not checking it") + return True for nserver in domain_data["nserver"]: @@ -341,6 +349,7 @@ def check_dnssec(domain_name, domain_data): # HANDLE QUERY FAILED (SERVER ERROR OR NO DNSKEY RECORD) print( f"WARN: query for a DNSKEY on {domain_name} failed on {nserver} ({nsaddr}), returncode: {response[0].rcode()}") + errors += 1 continue # answer should contain two RRSET: DNSKEY and RRSIG(DNSKEY) answer = response[0].answer @@ -348,6 +357,7 @@ def check_dnssec(domain_name, domain_data): # SOMETHING WENT WRONG print( f"ERROR: query for a DNSKEY on {domain_name} failed on {nserver} ({nsaddr}), invalid answer length: {len(answer)}") + errors += 1 continue # the DNSKEY should be self signed, validate it name = dns.name.from_text(domain_name) @@ -366,8 +376,10 @@ def check_dnssec(domain_name, domain_data): # BE SUSPICIOUS print( f"WARN: DNSSEC validation failed on {domain_name} failed on {nserver} ({nsaddr}), answer: {answer}") + errors += 1 except AttributeError as e: print(f"ERROR: {e}") + errors += 1 else: # WE'RE GOOD, THERE'S A VALID DNSSEC SELF-SIGNED KEY FOR example.com print( @@ -380,7 +392,7 @@ def check_dnssec(domain_name, domain_data): # step3: end def main(mntner): - + global errors # get all domains/inet(6)nums of the mntner domains = get_domain_by_mntner(mntner=mntner) @@ -422,6 +434,7 @@ def main(mntner): else: print( f"ERROR: invalid ds-rdata specified and matching DNSKEY returned by {ip} for {domain_name}") + errors += 1 # break # print(check_dnssec(domain_name, domains[domain_name])) @@ -432,6 +445,7 @@ if __name__ == "__main__": print(f"please specify your mntner\n {sys.argv[0]} YOU-MNT") exit(1) main(sys.argv[1]) + exit(errors) # commands to run: