#!/usr/bin/python import base64 import re import struct import sys from scapy.all import DNS def Count(d, value): if value in d: d[value] += 1 else: d[value] = 1 results = {} # Results, by type. answered = {} # Number of answered queries, by resolver. filtering = {} # Number of filtered queries, by resolver. unfiltered = {} # Number of filtered queries, by probe filtered = {} # Number of filtered queries, by probe. ERROR_RE = re.compile('"error": {"([^"]+)": ') ABUF_RE = re.compile('"abuf": "([0-9A-Za-z+/=]+)"') SERVER_RE = re.compile('"from": "([^"]*)"') PROBE_RE = re.compile('"prb_id":([^"]*),') NOANSWER_RE = re.compile('"ANCOUNT": 0,') for line in sys.stdin.readlines(): # If the probe detected an error, report it. error = ERROR_RE.search(line) if error: msg = "ERR_" + error.groups(1)[0] Count(results, msg) continue # Get the server's IP address. server = SERVER_RE.search(line).groups(1)[0] probe = PROBE_RE.search(line).groups(1)[0] # Got an answer? Assume it's OK. if not NOANSWER_RE.search(line): Count(results, "successful") Count(answered, server) Count(unfiltered, probe) continue # Otherwise, parse the answer packet. answer = ABUF_RE.search(line).groups(1)[0] try: dns = DNS(base64.b64decode(answer)) except struct.error: Count(results, "parseerror") continue # Probes configured to use resolvers that aren't willing to recurse for them. if dns.nscount > 0 and dns.arcount != 1: Count(results, "norecurse") continue if dns.rcode == 0: # This should never happen unless the resolver is filtering AAAA records. Count(filtering, server) Count(filtered, probe) Count(results, "filtering") else: rcodestr = dns.get_field('rcode').i2s[dns.rcode] Count(results, rcodestr) def PrintFilteringPercentage(filtered, unfiltered, key): total = filtered[key] + unfiltered.get(key, 0) num_filtered = filtered[key] rate = 100.0 * num_filtered / total print " %s: %d/%d (%.1f%%)" % (key, num_filtered, total, rate) print "Results:", results if filtering: print "Filtering DNS servers:" for server in filtering: PrintFilteringPercentage(filtering, answered, server) if filtered: print "Filtered probes:" for probe in filtered: PrintFilteringPercentage(filtered, unfiltered, probe)