From 3920ce68b13e847d07d30e43f6564570ef0504e1 Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Mon, 16 Nov 2015 14:06:31 +0100 Subject: [PATCH] Add check for same SOA on all NSes --- dnssec-check | 61 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/dnssec-check b/dnssec-check index ad3d08c..e88fc5d 100755 --- a/dnssec-check +++ b/dnssec-check @@ -2,7 +2,9 @@ from __future__ import print_function import ldns -from unbound import ub_ctx, idn2dname, RR_TYPE_SOA, RR_TYPE_DNSKEY, RR_TYPE_RRSIG, ub_strerror +from unbound import ub_ctx, idn2dname, ub_strerror +from unbound import RR_TYPE_SOA, RR_TYPE_DNSKEY, RR_TYPE_RRSIG, RR_TYPE_NS +from unbound import RR_TYPE_A, RR_TYPE_AAAA from optparse import OptionParser import sys from datetime import datetime, timedelta @@ -42,7 +44,46 @@ def check_dnssec_expire(resolver, name, warn, crit): print("WARN (expires in %s) %s" % (delta, name)) return 1 return 0 + +def check_zone_synced(resolver, name): + s, result = resolver.resolve(name, RR_TYPE_NS) + if 0 != s: + ub_strerror(s) + return 3 + + nameservers = result.data.as_domain_list() + nsips = [] + for nameserver in nameservers: + for rrtype in [RR_TYPE_AAAA, RR_TYPE_A]: + s, result = resolver.resolve(nameserver, rrtype=rrtype) + if 0 != s: + ub_strerror(s) + return 3 + nsips = nsips + result.data.as_address_list() + results = dict() + for ip in nsips: + newres = ub_ctx() + newres.set_fwd(ip) + s, result = newres.resolve(name, rrtype=RR_TYPE_SOA) + if 0 != s: + ub_strerror(s) + return 3 + + s, result = ldns.ldns_wire2pkt(result.packet) + soas = list(result.rr_list_by_type(RR_TYPE_SOA, + ldns.LDNS_SECTION_ANSWER).rrs()) + + if len(soas) != 1: + return 3 + serial = str(soas[0]).split()[6] + results[serial] = results.get(serial, []) + [ip] + + if len(results) == 1: + return 0 + else: + print("CRIT (different SOAs): %s", results) + return 2 def main(): parser = OptionParser() @@ -73,15 +114,23 @@ def main(): final = 0 for name in opts.names: name = idn2dname(name.decode(encoding)) - result = check_dnssec_expire(resolver, name, + result1 = check_zone_synced(resolver, name) + if result1 == 2: + final = 2 + elif result1 == 1 and final != 2: + final = 1 + elif result1 == 3 and final not in [1, 2]: + final = 3 + + result2 = check_dnssec_expire(resolver, name, timedelta(opts.warn), timedelta(opts.crit)) - if result == 0 and opts.verbose: + if result1 + result2 == 0 and opts.verbose: print("OK %s" % name) - if result == 2: + if result2 == 2: final = 2 - elif result == 1 and final != 2: + elif result2 == 1 and final != 2: final = 1 - elif result == 3 and final not in [1, 2]: + elif result2 == 3 and final not in [1, 2]: final = 3 sys.exit(final) -- 2.39.2