Commit 2adcdd26 authored by Petr Špaček's avatar Petr Špaček

WIP: prototype of TCP zone scanner

parent ed6c0c20
Pipeline #48038 failed with stage
in 1 minute and 36 seconds
......@@ -10,9 +10,11 @@ import dns.name
import domain2ipset
import ednsevalzone
import ednscomp2pickle
import tcpcomp2pickle
import genednscomp
import nsname2ipset
import testedns
import testtcp
import zone2pickle
def main():
......@@ -20,7 +22,7 @@ def main():
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')
argparser = argparse.ArgumentParser(description='test delegations in given zone file')
argparser.add_argument('scan_type', choices=['edns2019'], help='criteria to use for scanner')
argparser.add_argument('scan_type', choices=['edns2019', 'tcp'], help='criteria to use for scanner')
argparser.add_argument('zone_file', type=open, help='zone file in RFC 1035 format')
argparser.add_argument('zone_origin', type=dns.name.from_text, help='zone name, SOA RR must be present')
args = argparser.parse_args()
......@@ -83,8 +85,13 @@ def main():
remaining,
remaining/total * 100)
domain2ipset.save(domain_nsset, netstats, domain_ipset)
if args.scan_type == 'edns2019':
summary = scan_edns2019(domain_nsset, nsname_ipsets, domain_ipset)
elif args.scan_type == 'tcp':
summary = scan_tcp(domain_nsset, nsname_ipsets, domain_ipset)
print(summary.text)
def scan_edns2019(domain_nsset, nsname_ipsets, domain_ipset):
logging.info('generating input data for genreport tool')
with open('ednscomp.input', 'w') as ednscomp_input:
ednscomp_input.writelines(genednscomp.generate(nsname_ipsets, domain_ipset))
......@@ -108,7 +115,34 @@ def main():
ednsevalzone.save_pickle(results_strict, 'strict')
ednsevalzone.save_pickle(results_permissive, 'permissive')
ednsevalzone.save_summary(summary)
print(summary.text)
return summary
def scan_tcp(domain_nsset, nsname_ipsets, domain_ipset):
logging.info('generating input data for genreport tool')
with open('ednscomp.input', 'w') as ednscomp_input:
ednscomp_input.writelines(genednscomp.generate(nsname_ipsets, domain_ipset))
logging.info('executing TCP tests')
testtcp.repeat_genreport(2)
tcpcompresults = glob.glob('tcpcompresult-*')
if not tcpcompresults:
logging.critical('error: no tcpcompresult-* files from previous step found, exiting')
sys.exit(2)
logging.info('processing genreport output in TCP-mandatory mode (small UDP buffer sizes)')
nsstats_strict = tcpcomp2pickle.collect_server_stats(tcpcomp2pickle.eval_tcp_strict, tcpcompresults)
tcpcomp2pickle.save(nsstats_strict, 'strict')
logging.info('processing genreport output in TCP-not-mandatory mode (big UDP buffer sizes)')
nsstats_permissive = tcpcomp2pickle.collect_server_stats(tcpcomp2pickle.eval_tcp_permissive, tcpcompresults)
tcpcomp2pickle.save(nsstats_permissive, 'permissive')
summary, results_strict, results_permissive = ednsevalzone.evaluate(nsstats_strict, nsstats_permissive, domain_nsset, nsname_ipsets, domain_ipset)
ednsevalzone.save_pickle(results_strict, 'strict')
ednsevalzone.save_pickle(results_permissive, 'permissive')
ednsevalzone.save_summary(summary)
return summary
if __name__ == "__main__":
testedns.check_env()
......
......@@ -43,11 +43,11 @@ Running scan
------------
Usage::
$ allinone.py <canonicalized zone file> <zone origin>
$ allinone.py edns2019 <canonicalized zone file> <zone origin>
Example::
$ allinone.py zone.nodnssec example.net.
$ allinone.py edns2019 zone.nodnssec example.net.
Once the zone is loaded into memory the script will print informational
messages about progress. Make a coffee or let it run overnight ...
......
#!/usr/bin/python3
import datetime
import logging
import subprocess
import sys
def repeat_genreport(cycles: int):
logging.info('Hint: use tail -f to monitor progress of individual genreport runs')
with open('ednscomp.input', 'rb') as ednscomp_input:
for cycle in range(1, cycles + 1):
with open('tcpcompresult-{}'.format(datetime.datetime.utcnow().isoformat()),
'wb') as ednscomp_output:
logging.info('genreport round {} / {}, output file {}'.format(
cycle, cycles, ednscomp_output.name))
subprocess.run(check=True, stdin=ednscomp_input, stdout=ednscomp_output,
args=['genreport', '-m', '500', '-p', '-s', '-i', 'do', '-i', 'tcp', '-i', 'ednstcp'])
ednscomp_input.seek(0)
def check_env():
# check if genreport is in PATH and can be executed
try:
subprocess.run(check=True, input='', args=['genreport'])
except:
logging.exception('unable to execute genreport tool, make sure it is in PATH')
raise SystemExit('fatal error: genreport is required')
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')
try:
cycles = int(sys.argv[1])
except IndexError:
cycles = 10
except ValueError:
logging.critical('Usage: %s [number_of_genreport_rounds]', sys.argv[0])
sys.exit(1)
check_env()
repeat_genreport(cycles)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment