diff options
Diffstat (limited to 'dnscheck_nsd.py')
-rw-r--r-- | dnscheck_nsd.py | 82 |
1 files changed, 47 insertions, 35 deletions
diff --git a/dnscheck_nsd.py b/dnscheck_nsd.py index 329fa45..ea923c5 100644 --- a/dnscheck_nsd.py +++ b/dnscheck_nsd.py @@ -4,7 +4,7 @@ __author__ = 'lundberg' import sys import argparse import logging -from socket import gethostbyname, gethostbyaddr, gaierror +from socket import gethostbyname, gethostbyaddr, gaierror, herror import dns.resolver logger = logging.getLogger('dnscheck_nsd') @@ -17,6 +17,7 @@ logger.addHandler(ch) VERBOSE = False + def get_resolver(nameserver=None, lifetime=30): resolver = dns.resolver.Resolver() resolver.lifetime = lifetime @@ -25,13 +26,14 @@ def get_resolver(nameserver=None, lifetime=30): resolver.nameservers=[gethostbyname(nameserver)] except gaierror: try: - resolver.nameservers=[nameserver] # It is an IP address + resolver.nameservers = [nameserver] # It is an IP address except gaierror: logger.error('Could not find nameserver: %s' % nameserver) sys.exit(1) logger.debug('Resolver instance with nameserver %s.' % resolver.nameservers[0]) return resolver + def compare_soa(zone, resolvers): answers = [] for resolver in resolvers: @@ -41,7 +43,10 @@ def compare_soa(zone, resolvers): if resolver.nameservers[0] == '127.0.0.1' or resolver.nameservers[0] == '::1': logger.info('NS %s: %s' % (resolver.nameservers[0], answer)) else: - logger.info('NS %s: %s' % (gethostbyaddr(resolver.nameservers[0])[0], answer)) + try: + logger.info('NS %s: %s' % (gethostbyaddr(resolver.nameservers[0])[0], answer)) + except herror: + logger.info('NS %s: %s' % (resolver.nameservers[0], answer)) except dns.exception.Timeout: logger.error('%s timed out. SOA request for %s failed.' % (gethostbyaddr(resolver.nameservers[0])[0], zone)) return 'timeout' @@ -60,6 +65,7 @@ def compare_soa(zone, resolvers): return 'match' return 'no match' + def print_soa(zone, resolvers): for resolver in resolvers: try: @@ -77,13 +83,14 @@ def print_soa(zone, resolvers): except dns.resolver.NoNameservers: logger.error('No non-broken nameservers are available to answer the query for %s.' % zone) + def check_auth(zone, resolver): try: nameserver = gethostbyaddr(resolver.nameservers[0])[0] answer = resolver.query(zone, 'NS') if VERBOSE: logger.info('Checking if NS %s authoritative for %s...' % (nameserver, zone)) - ns_match = '%s.' % nameserver # hostname. + ns_match = '%s.' % nameserver # hostname. for auth in answer: if ns_match == auth.to_text(): if VERBOSE: @@ -108,9 +115,10 @@ def check_auth(zone, resolver): logger.info('NS %s is not authoritative for %s...' % (nameserver, zone)) return False + def parse_file(f): result = [] - in_zone,domain,ns_address = False,'','' + in_zone, domain, ns_address = False, '', '' for line in f: if not line.startswith('#'): if line.startswith('zone'): @@ -119,20 +127,21 @@ def parse_file(f): domain = line.split()[1] if in_zone and line.find('request-xfr') != -1: ns_address = line.split()[1] - if not line.strip(): # Blank line + if not line.strip(): # Blank line if domain: logger.error('Misconfigured zone: %s in %s.' % (domain, f.name)) if ns_address: logger.error('Misconfigured zone with NS address: %s in %s.' % (ns_address, f.name)) - in_zone,domain,ns_address = False,'','' + in_zone, domain, ns_address = False, '', '' if in_zone and domain and ns_address: result.append({ 'domain': domain.strip('"'), 'ns_address': ns_address - }) - in_zone,domain,ns_address = False,'','' + }) + in_zone, domain, ns_address = False, '', '' return result + def main(): # User friendly usage output parser = argparse.ArgumentParser() @@ -168,32 +177,35 @@ def main(): else: exclude_list = [] ref_resolver = get_resolver(nameserver=args.nameserver, lifetime=args.timeout) - for item in parse_file(args.file): - if not item['domain'] in exclude_list: - if not args.nochecksoa: - resolver = get_resolver(nameserver=item['ns_address'], lifetime=args.timeout) - soa_result = compare_soa(item['domain'], [ref_resolver, resolver]) - if soa_result == 'match' and VERBOSE: - print 'SOA check complete for zone %s.\n' % item['domain'] - elif not soa_result: - print 'SOA check for zone %s failed.\n' % item['domain'] - elif soa_result == 'timeout': - print 'SOA check for zone %s timed out.\n' % item['domain'] - elif soa_result == 'no match': - print 'SOA did not match:' - print_soa(item['domain'], [ref_resolver, resolver]) - print '' - if not args.nocheckauth: - auth_result = check_auth(item['domain'], ref_resolver) - if auth_result and VERBOSE: - print 'Authority check complete for %s.\n' % item['domain'] - elif auth_result is None: - print 'Authoritative check failed for %s.\n' % item['domain'] - elif not auth_result: - print 'Reference NS is not authoritative for %s.\n' % item['domain'] - else: - if VERBOSE: - logger.info('Zone %s found in exclude list, skipping...' % item['domain']) + try: + for item in parse_file(args.file): + if not item['domain'] in exclude_list: + if not args.nochecksoa: + resolver = get_resolver(nameserver=item['ns_address'], lifetime=args.timeout) + soa_result = compare_soa(item['domain'], [ref_resolver, resolver]) + if soa_result == 'match' and VERBOSE: + print 'SOA check complete for zone %s.\n' % item['domain'] + elif not soa_result: + print 'SOA check for zone %s failed.\n' % item['domain'] + elif soa_result == 'timeout': + print 'SOA check for zone %s timed out.\n' % item['domain'] + elif soa_result == 'no match': + print 'SOA did not match:' + print_soa(item['domain'], [ref_resolver, resolver]) + print '' + if not args.nocheckauth: + auth_result = check_auth(item['domain'], ref_resolver) + if auth_result and VERBOSE: + print 'Authority check complete for %s.\n' % item['domain'] + elif auth_result is None: + print 'Authoritative check failed for %s.\n' % item['domain'] + elif not auth_result: + print 'Reference NS is not authoritative for %s.\n' % item['domain'] + else: + if VERBOSE: + logger.info('Zone %s found in exclude list, skipping...' % item['domain']) + except KeyboardInterrupt: + sys.exit(0) return 0 if __name__ == '__main__': |