#!/usr/bin/env python3 ''' Test for loading badly formed record ''' from dnstest.test import Test t = Test() master = t.server("knot") zone = t.zone("badrecord.", "badrecord.zone", storage=".") t.link(zone, master) t.start() # Check if the server is answering and zone _isn't_ loaded resp = master.dig("badrecord.", "SOA", udp=True) # @note Either REFUSED or SERVFAIL is fine, Knot treats unloadable # zone as expired while the older version ignored such zone. resp.check(rcode="SERVFAIL") # Stop master. master.stop() t.end()
#!/usr/bin/env python3 ''' Test querying rset with too many rdata ''' import random import dns.exception import dns.rcode import dns.tsig from dnstest.utils import * from dnstest.test import Test t = Test(tsig=False) master = t.server("knot") ZONE = "example.com." HUGE = "huge.%s" % ZONE zone = t.zone(ZONE, storage=".") rndfix = random.randint(1, 65000) for i in range(1, 3000): zone[0].append_rndAAAA(HUGE, rndfix, i) t.link(zone, master) t.start() master.zone_wait(zone) resp = master.dig(HUGE, "AAAA", udp=True) resp.check(rcode="NOERROR", flags="TC")
#!/usr/bin/env python3 '''Test of freeze-thaw feature''' from dnstest.test import Test from dnstest.utils import * t = Test(tsig=False) master = t.server("knot") zone = t.zone_rnd(1, records=300, dnssec=False) t.link(zone, master) master.dnssec(zone[0]).enable = True def soa_rrsig(server, zones): resp = server.dig(zones[0].name, "SOA", dnssec=True) return resp.resp.answer[1].to_rdataset()[0].to_text() master.ctl_params_append = ["-t", "35"] t.start() master.zone_wait(zone) rrsig0 = soa_rrsig(master, zone) master.ctl("zone-sign") # non-blocking
#!/usr/bin/env python3 '''Test insecure<->secure delegation transitions with NSEC3PARAM changes.''' import random from dnstest.test import Test t = Test() master = t.server("knot") zones = t.zone("example.") t.link(zones, master) master.dnssec(zones[0]).enable = True master.dnssec(zones[0]).nsec3 = True master.dnssec(zones[0]).nsec3_opt_out = True master.dnssec(zones[0]).nsec3_iters = 1 t.start() master.zones_wait(zones) master.dnssec(zones[0]).nsec3_iters = 2 master.gen_confile() master.reload() t.sleep(8) up = master.update(zones) up.add("b.example.", 3600, "DS", "57855 5 1 B6DCD485719ADCA18E5F3D48A2331627FDD3636B") up.send()
#!/usr/bin/env python3 '''Manual DDNS testing''' from dnstest.utils import * from dnstest.test import Test import random t = Test() def check_soa(master, prev_soa): soa_resp = master.dig("ddns.", "SOA") compare(prev_soa, soa_resp.resp.answer, "SOA changed when it shouldn't") def verify(master, zone, dnssec): if not dnssec: return master.flush() t.sleep(1) master.zone_verify(zone) def do_normal_tests(master, zone, dnssec=False): # add node check_log("Node addition") up = master.update(zone) up.add("rrtest.ddns.", 3600, "A", "1.2.3.4") up.send("NOERROR") resp = master.dig("rrtest.ddns.", "A") resp.check(rcode="NOERROR", rdata="1.2.3.4")
#!/usr/bin/env python3 ''' Check 'dnstap' query module functionality. ''' import os import re from dnstest.test import Test from dnstest.module import ModDnstap from dnstest.utils import * t = Test() ModDnstap.check() # Initialize server configuration knot = t.server("knot") zone = t.zone("flags.") t.link(zone, knot) # Configure 'dnstap' module for all queries (default). dflt_sink = t.out_dir + "/all.tap" knot.add_module(None, ModDnstap(dflt_sink)) # Configure 'dnstap' module for flags zone only. flags_sink = t.out_dir + "/flags.tap" knot.add_module(zone, ModDnstap(flags_sink)) t.start() dflt_qname = "dnstap_default_test" resp = knot.dig(dflt_qname + ".example", "NS") flags_qname = "dnstap_flags_test"
#!/usr/bin/env python3 '''Test for maximum UDP payload size with respect to IP family''' from dnstest.test import Test t = Test() server4 = t.server("knot", address=4) server6 = t.server("knot", address=6) zone = t.zone("flags.") # Set common payload limit for 512-byte message with 11-byte EDNS section. server4.max_udp_payload = 523 server6.max_udp_payload = 523 t.link(zone, server4) t.link(zone, server6) t.start() # Check common limit if 512 fits and 513 does not. resp = server4.dig("512resp.flags", "TXT", udp=True, bufsize=4096) resp.check(noflags="TC") resp = server4.dig("513resp.flags", "TXT", udp=True, bufsize=4096) resp.check(flags="TC") resp = server6.dig("512resp.flags", "TXT", udp=True, bufsize=4096) resp.check(noflags="TC") resp = server6.dig("513resp.flags", "TXT", udp=True, bufsize=4096)
found_dnskeys = dnskeys.count("DNSKEY") found_rrsigs = soa.count("RRSIG") expect_dnskeys = 3 if expect_dnskey else 2 expect_rrsigs = 2 if expect_rrsig else 1 check_log("DNSKEYs: %d (expected %d) RRSIGs: %d (expected %d)" % (found_dnskeys, expect_dnskeys, found_rrsigs, expect_rrsigs)); if found_dnskeys != expect_dnskeys or found_rrsigs != expect_rrsigs: set_err("BAD DNSKEY: " + msg) detail_log("!DNSKEYs not published and activated as expected: " + msg) detail_log(SEP) t = Test() knot = t.server("knot") knot.dnssec_enable = True zone = t.zone("example.com.") t.link(zone, knot) # install keys (one always enabled, one for testing) shutil.copytree(os.path.join(t.data_dir, "keys"), knot.keydir) # parameters ZONE = "example.com" KEYID = "712d0d0d57fa0aa006b5e20cd84e23941e5f3ab2" WAIT_SIGN = 2 #
#!/usr/bin/env python3 """Test for EDNS version""" from dnstest.test import Test from dnstest.utils import * t = Test() server = t.server("knot") zone = t.zone("example.com.") t.link(zone, server) t.start() # Supported EDNS version 0. resp = server.dig("example.com", "SOA", edns=0) resp.check(rcode="NOERROR", edns_version=0) # Unsupported EDNS version 1. resp = server.dig("example.com", "SOA", edns=1) resp.check(rcode="BADVERS", edns_version=0) compare(resp.count(section="answer"), 0, "Answer count") compare(resp.count(section="authority"), 0, "Authority count") compare(resp.count(section="additional"), 0, "Additional count") t.end()
return ''.join(random.choice(chars) for _ in range(63)) def flood(server, zone): rr = None updates = [] for i in range(UPDATE_COUNT): update = server.update(zone) for j in range(UPDATE_SIZE): rr = [randstr() + "." + zone[0].name, 3600, "TXT", randstr()] update.add(*rr) update.send() return rr random.seed() t = Test() zone = t.zone_rnd(1, dnssec=False, records=4) master = t.server("knot") # set journal limit for the master master.ixfr_fslimit = "800k" slaves = [t.server("knot") for _ in range(2)] # set journal limit for one of the slaves slaves[0].ixfr_fslimit = "500k" for s in slaves: t.link(zone, master, s, ddns=True, ixfr=True) t.start()
#!/usr/bin/env python3 """ Multi-master failover tests. """ from dnstest.test import Test t = Test() # testing zone zone = t.zone_rnd(1, dnssec=False, records=1)[0] zone.update_soa(serial=1, refresh=600, retry=600, expire=3600) # +---------+ +---------+ # | master1 <-------+ master2 | # +----^----+ +----^----+ # | | # | +---------+ | # +---+ slave +---+ # +---------+ master1 = t.server("knot") master2 = t.server("bind") slave = t.server("knot") # flush zones immediatelly for server in [master1, master2, slave]: slave.zonefile_sync = "0" t.link([zone], master1, master2)
#!/usr/bin/env python3 '''Test for IXFR from Knot to Knot''' from dnstest.test import Test t = Test() master = t.server("knot") slave = t.server("knot") zones = t.zone_rnd(5, records=50) + t.zone("records.") t.link(zones, master, slave, ixfr=True) t.start() # Wait for AXFR to slave server. serials_init = master.zones_wait(zones) slave.zones_wait(zones) serials_prev = serials_init for i in range(4): # Update zone files on master. for zone in zones: master.update_zonefile(zone, random=True) master.reload() # Wait for IXFR to slave. serials = master.zones_wait(zones, serials_prev) slave.zones_wait(zones, serials_prev) serials_prev = serials
#!/usr/bin/env python3 '''Test for loading of dumped zone''' from dnstest.test import Test t = Test() master = t.server("bind") slave = t.server("knot") reference = t.server("bind") zones = t.zone_rnd(4) + t.zone(".") + t.zone("records.") t.link(zones, master, slave) t.link(zones, reference) t.start() # Wait for servers. master.zones_wait(zones) slave.zones_wait(zones) reference.zones_wait(zones) # Dump zones on slave. slave.flush() # Compare master with reference server t.xfr_diff(reference, master, zones) # Compare slave with reference server
#!/usr/bin/env python3 '''Test for server version over CH/TXT''' from dnstest.test import Test t = Test() ver = "ver. 1.3.1-p3" server1 = t.server("knot", version=ver) server2 = t.server("knot", version=True) server3 = t.server("knot", version=False) server4 = t.server("knot") t.start() # 1a) Custom version string. resp = server1.dig("version.server", "TXT", "CH") resp.check('"' + ver + '"') # 1b) Bind old version of above. resp = server1.dig("version.bind", "TXT", "CH") resp.check('"' + ver + '"') # 2) Automatic version string (can't be tested). resp = server2.dig("version.server", "TXT", "CH") resp.check(rcode="NOERROR") # 3) Explicitly disabled. resp = server3.dig("version.server", "TXT", "CH") resp.check(rcode="REFUSED")
#!/usr/bin/env python3 '''Test for signing a zone with weird records.''' from dnstest.utils import * from dnstest.test import Test t = Test() master = t.server("knot") zone = t.zone("records.") t.link(zone, master) master.dnssec(zone).enable = True t.start() master.zone_wait(zone) resp = master.dig("nxdomain.records", "A", udp=False, dnssec=True) resp.check_auth_soa_ttl(dnssec=True) resp = master.dig("mail.records.", "RRSIG", dnssec=True) resp.check_count(1, rtype="RRSIG") t.sleep(1) master.flush() t.sleep(1) # Verify signed zone file. master.zone_verify(zone) t.stop()
#!/usr/bin/env python3 '''Test for reload of a changed zone (serial up, nochange, serial down). ''' from dnstest.test import Test from dnstest.utils import * t = Test() master = t.server("bind") slave = t.server("knot") zone = t.zone("example.com.", storage=".") t.link(zone, master, slave) # Load newer zone to the slave slave.update_zonefile(zone, version=1) t.start() serial_master = master.zone_wait(zone) serial_slave = slave.zone_wait(zone) # Check that the slave's serial is larger than master's assert serial_master <= serial_slave # Force refresh slave.ctl("zone-retransfer example.com.") t.sleep(2) serial_slave = slave.zone_wait(zone)
resp = master.dig(nsec_zone, "IXFR", serial=serial) for msg in resp.resp: for rr in msg.answer: if rr.rdtype not in [ dns.rdatatype.SOA, dns.rdatatype.NSEC, dns.rdatatype.RRSIG ]: return False if rr.rdtype == dns.rdatatype.RRSIG: if (not rr.match(rr.name, rr.rdclass, dns.rdatatype.RRSIG, dns.rdatatype.NSEC)) and \ (not rr.match(rr.name, rr.rdclass, dns.rdatatype.RRSIG, dns.rdatatype.SOA)): # RRSIG covering something else than NSEC or SOA. return False return True t = Test() master = t.server("knot") nsec_zone = t.zone_rnd(1, dnssec=True, nsec3=False) nsec3_zone = t.zone_rnd(1, dnssec=True, nsec3=0) static_zone = t.zone("example.", storage=".") t.link(nsec_zone, master) t.link(nsec3_zone, master) t.link(static_zone, master) master.dnssec(nsec_zone).alg = "rsasha1" master.dnssec(nsec3_zone).alg = "rsasha1" master.dnssec(nsec3_zone).nsec3 = True master.dnssec(static_zone).alg = "rsasha1" master.dnssec(nsec_zone).cds_publish = "rollover"
from subprocess import check_call from dnstest.utils import * from dnstest.test import Test from dnstest.params import get_binary # Find PROTOS binaries protos_bin = [ "c09-dns-query-r1.jar", "c09-dns-zonetransfer-r1.jar" ] protos_java_bin = get_binary("PROTOS_JAVA_BIN", "java") protos_query_bin = get_binary("PROTOS_QUERY_BIN", protos_bin[0]) protos_zonetransfer_bin = get_binary("PROTOS_ZONETRANSFER_BIN", protos_bin[1]) if not protos_java_bin: raise Skip("Java not found") if not protos_query_bin: raise Skip("'%s' PROTOS binary not found" % protos_bin[0]) t = Test(address=4, tsig=False) # PROTOS works on IPv4, no TSIG master = t.server("dummy") slave = t.server("knot") zone = t.zone("protos.invalid.", exists=False) t.link(zone, master, slave) # Update configuration t.start() ''' Run PROTOS test case with given parameters. ''' def protos_run(name, binfile, params): if not binfile: return check_call([protos_java_bin, "-jar", binfile] + params, stdout=open(master.fout, mode="w"), stderr=open(master.ferr, mode="w")) shutil.move(master.fout, master.fout + "." + name)
#!/usr/bin/env python3 '''TTL mismatch test''' from dnstest.utils import * from dnstest.test import Test t = Test() zone = t.zone("example.com.") master = t.server("knot") t.link(zone, master, ddns=True) t.start() # Add new RR with different TTL to a RRSet that is already in the zone # The UPDATE should be REFUSED check_log("Add RR with different TTL") up = master.update(zone) up.add("mail.example.com.", 1000, "A", "1.2.3.4") up.send("REFUSED") resp = master.dig("mail.example.com.", "A") resp.check_record(section="answer", rtype="A", ttl="3600", rdata="192.0.2.3") resp.check_record(section="answer", rtype="A", nordata="1.2.3.4") # Try to add two RRs belonging to one RRSet, but with different TTLs # The UPDATE should be REFUSED # This also tests rollback in case of addition
#!/usr/bin/env python3 '''Test for EDNS0/NSID identification''' from dnstest.test import Test t = Test() name = "Knot DNS server" hex_name = "0x01020304" server1 = t.server("knot", nsid=name) server2 = t.server("knot", nsid=False) server3 = t.server("knot") server4 = t.server("knot", nsid=hex_name) zone = t.zone("example.com.") t.link(zone, server1) t.link(zone, server2) t.link(zone, server3) t.link(zone, server4) t.start() # 1) Custom identification string. resp = server1.dig("example.com", "SOA", nsid=True) resp.check_edns(nsid=name) # 2) Disabled. resp = server2.dig("example.com", "SOA", nsid=True) resp.check_edns()
#!/usr/bin/env python3 '''Test of zone-in-journal: AXFR & IXFR to zonefile-less slave''' from dnstest.test import Test t = Test() master = t.server("knot") slave = t.server("knot") zone = t.zone("example.com.") t.link(zone, master, slave, journal_content="all") slave.zonefile_sync = "-1" t.start() master.zone_wait(zone) slave.zone_wait(zone) # Check if bootstrapped and unflushed zone is accessible without master available. master.stop() slave.stop() t.sleep(2) slave.start() slave.zone_wait(zone) resp = slave.dig("mail.example.com.", "A") resp.check(rcode="NOERROR", rdata="192.0.2.3")
#!/usr/bin/env python3 '''Test for Knot clean-up after interruption of AXFR from Bind''' from dnstest.test import Test from dnstest.utils import * t = Test() master = t.server("bind") slave = t.server("knot") zones = t.zone_rnd(1, dnssec=False, records=50000) t.link(zones, master, slave) t.start() t.sleep(2) check_log("Killing master %s" % master.name) master.proc.kill() t.sleep(5) t.end()
#!/usr/bin/env python3 '''Test for transition from NSEC to NSEC3 on auto-signed zone.''' from dnstest.utils import * from dnstest.test import Test t = Test() master = t.server("knot") slave = t.server("bind") zone = t.zone_rnd(1, dnssec=False) t.link(zone, master, slave) t.start() # Wait for listening server with unsigned zone. old_serial = master.zone_wait(zone) slave.zone_wait(zone) t.xfr_diff(master, slave, zone) # Check NSEC absence. master.check_nsec(zone, nonsec=True) master.stop() # Enable autosigning. master.dnssec_enable = True master.gen_key(zone, ksk=True, alg="NSEC3RSASHA1") master.gen_key(zone, alg="NSEC3RSASHA1") master.gen_key(zone, ksk=True, alg="RSASHA256") master.gen_key(zone, alg="RSASHA256")
t.xfr_diff(master, slave, zone) def do_steps(master, slave, zone): # add records serials = [] update_zone(master, slave, zone, range(1, CHANGE_COUNT + 1), change_serial=False, serials=serials) # remove added records, in descending order rev = list(range(1, CHANGE_COUNT + 1)) rev.reverse() # increase serials so that server accepts them serials = list(map(lambda x: x + 1000, serials)) serials.reverse() update_zone(master, slave, zone, rev[1:], change_serial=True, serials=serials) t = Test() # Create NSEC and NSEC3 servers nsec_master = t.server("knot") nsec3_master = t.server("knot") nsec_slave = t.server("bind") nsec3_slave = t.server("bind") zone = t.zone("example.", storage=".") t.link(zone, nsec_master, nsec_slave) t.link(zone, nsec3_master, nsec3_slave) # Enable autosigning nsec_master.dnssec_enable = True nsec_master.gen_key(zone, ksk=True, alg="RSASHA256")
#!/usr/bin/env python3 '''Test for NSEC and NSEC3 fix after zone update (ddns, ixfr)''' from dnstest.utils import * from dnstest.test import Test from dnstest.keys import Keymgr import random t = Test() master0 = t.server("knot") master = t.server("knot") slave = t.server("knot") zones1 = t.zone_rnd(20, dnssec=False, records=1) + \ t.zone_rnd(20, dnssec=False, records=10) + \ t.zone_rnd(5, dnssec=False, records=100) + \ t.zone("records.") zone0 = t.zone("dk.", storage=".") zones = zones1 + zone0 t.link(zone0, master0, master) t.link(zones, master, slave) master.disable_notify = True slave.disable_notify = True for zone in zones: master.dnssec(zone).enable = True master.dnssec(zone).nsec3 = random.choice([True, False]) master.dnssec(zone).nsec3_iters = 2
#!/usr/bin/env python3 ''' Check 'synth_record' query module synthetic responses. ''' from dnstest.test import Test from dnstest.module import ModSynthRecord t = Test() ModSynthRecord.check() # Zone indexes FWD = 0 REV4 = 1 REV6 = 2 # Initialize server configuration knot = t.server("knot") zone = t.zone("forward.", storage=".") + \ t.zone("1.168.192.in-addr.arpa.", storage=".") + \ t.zone("1.6.b.0.0.0.0.0.0.2.6.2.ip6.arpa.", storage=".") t.link(zone, knot) # Enable DNSSEC knot.dnssec_enable = True for z in zone: knot.gen_key(z, ksk=True, alg="RSASHA256") knot.gen_key(z, alg="RSASHA256") # Configure 'synth_record' modules for auto forward/reverse zones knot.add_module(zone[FWD], ModSynthRecord("forward", None, None, "192.168.0.1"))
#!/usr/bin/env python3 """ Multi-master failover tests. """ from dnstest.test import Test t = Test() # testing zone zone = t.zone_rnd(1, dnssec=False, records=1)[0] zone.update_soa(serial=1, refresh=600, retry=600, expire=3600) # +---------+ +---------+ # | master1 <-------+ master2 | # +----^----+ +----^----+ # | | # | +---------+ | # +---+ slave +---+ # +---------+ master1 = t.server("knot") master2 = t.server("bind") slave = t.server("knot") # flush zones immediatelly for server in [master1, master2, slave]: slave.zonefile_sync = "0" t.link([zone], master1, master2) t.link([zone], master1, slave)
#!/usr/bin/env python3 '''Test for auto-rebootstrap if the slave zone file is invalid.''' from dnstest.test import Test t = Test() master = t.server("bind") slave = t.server("knot") zone = t.zone("invalid.", storage=".") t.link(zone, master, slave) # Create invalid zone file. slave.update_zonefile(zone, version=1) t.start() # Wait for zones and compare them. master.zones_wait(zone) slave.zones_wait(zone) t.xfr_diff(master, slave, zone) t.end()
#!/usr/bin/env python3 '''Test for response to IXFR request with newer serial''' from dnstest.utils import * from dnstest.test import Test t = Test() knot = t.server("knot") zone = t.zone("example.com.") t.link(zone, knot, ixfr=True) t.start() serial_init = knot.zone_wait(zone) resp = knot.dig("example.com", "IXFR", serial=serial_init + 1) resp.check_xfr() compare(resp.msg_count(), 1, "Only one message") compare(resp.count("SOA"), 1, "Only one RR in Answer section") compare(resp.count("ANY"), 1, "Only one RR in the whole message.") t.end()
#!/usr/bin/env python3 '''Test for mismatched TTLs handling on slave zone load.''' '''NOTE: dnspython can't keep different TTLs in one rrset. So we can't check the slave server properly.''' from dnstest.test import Test t = Test() master = t.server("dummy") slave = t.server("knot") zone = t.zone("ttl-mismatch.", storage=".", exists=False) t.link(zone, master, slave) # Create invalid zone file. slave.update_zonefile(zone, version=1) t.start() # Check if the zone was loaded. resp = slave.dig("ttl.ttl-mismatch.", "A") resp.check(rcode="NOERROR", flags="QR AA", noflags="TC AD RA") t.end()
#!/usr/bin/env python3 '''Test for EDNS version''' from dnstest.test import Test from dnstest.utils import * t = Test() server = t.server("knot") zone = t.zone("example.com.") t.link(zone, server) t.start() # Supported EDNS version 0. resp = server.dig("example.com", "SOA", edns=0) resp.check(rcode="NOERROR", edns_version=0) # Unsupported EDNS version 1. resp = server.dig("example.com", "SOA", edns=1) resp.check(rcode="BADVERS", edns_version=0) compare(resp.count(section="answer"), 0, "Answer count") compare(resp.count(section="authority"), 0, "Authority count") compare(resp.count(section="additional"), 0, "Additional count") t.end()
#!/usr/bin/env python3 '''Test for server identification over CH/TXT''' from dnstest.test import Test t = Test() name = "Knot DNS server name" server1 = t.server("knot", ident=name) server2 = t.server("knot") server3 = t.server("knot", ident=False) t.start() # 1a) Custom identification string. resp = server1.dig("id.server", "TXT", "CH") resp.check('"' + name + '"') # 1b) Bind old version of above. resp = server1.dig("hostname.bind", "TXT", "CH") resp.check('"' + name + '"') # 2) Default FQDN hostname. resp = server2.dig("id.server", "TXT", "CH") resp.check(t.hostname) # 3) Disabled. resp = server3.dig("id.server", "TXT", "CH") resp.check(rcode="REFUSED")
#!/usr/bin/env python3 '''Test for IXFR from Knot to Bind with TTL changed by RR addition''' from dnstest.test import Test t = Test() master = t.server("knot") slave = t.server("bind") zones = t.zone("example.com.") t.link(zones, master, slave, ixfr=True) t.start() serials_init = slave.zones_wait(zones) up = master.update(zones) up.add("example.com.", 500, "MX", "20 dns1") up.send("NOERROR") slave.zones_wait(zones, serials_init) t.xfr_diff(master, slave, zones, serials_init) t.end()
#!/usr/bin/env python3 """ Basic checks for CNAME following. - Query for CNAME, NSEC, RRSIG is not followed. - Query for ANY meta type is not followed. - Query for any other type is followed. """ from dnstest.test import Test t = Test() knot = t.server("knot") zone = t.zone("follow", storage=".") t.link(zone, knot) t.start() # follow CNAME (type exists) resp = knot.dig("test.follow", "AAAA") resp.check(rcode="NOERROR", flags="AA") resp.check_rr("answer", "test.follow", "CNAME") resp.check_rr("answer", "follow", "AAAA") resp.check_empty("authority") # follow CNAME (type doesn't exist)
#!/usr/bin/env python3 '''Test for zone semantic checks during zone commit.''' import os from dnstest.libknot import libknot from dnstest.test import Test from dnstest.utils import * t = Test() knot = t.server("knot") ctl = libknot.control.KnotCtl() ZONE_NAME = "testzone." t.start() ctl.connect(os.path.join(knot.dir, "knot.sock")) # Add new zone. ctl.send_block(cmd="conf-begin") resp = ctl.receive_block() ctl.send_block(cmd="conf-set", section="zone", item="domain", data=ZONE_NAME) resp = ctl.receive_block() ctl.send_block(cmd="conf-commit") resp = ctl.receive_block()
def reload_server(t, s): s.reload() t.sleep(1) def restart_server(t, s): s.stop() s.start() def reload_or_restart(t, s): if random.choice([True, False]): restart_server(t, s) else: reload_server(t, s) t = Test() random.seed() # this zone has refresh = 1s, retry = 1s and expire = 1s + 2s for connection timeouts zone = t.zone("example.", storage=".") servers = create_servers(t) t.start() #stop the servers so that the zone does not expire for server_pair in servers: server_pair[0].stop() server_pair[1].stop()
#!/usr/bin/env python3 '''Test for AXFR from Knot to Bind''' from dnstest.test import Test t = Test() master = t.server("knot") slave = t.server("bind") zones = t.zone_rnd(10) + t.zone(".") + t.zone("wild.") + \ t.zone("cname-loop.") + t.zone("records.") t.link(zones, master, slave) t.start() master.zones_wait(zones) slave.zones_wait(zones) t.xfr_diff(master, slave, zones) t.end()
#!/usr/bin/env python3 '''Test for transition from NSEC to NSEC3 on auto-signed zone using DDNS.''' from dnstest.utils import * from dnstest.test import Test t = Test() master = t.server("knot") slave = t.server("bind") zone = t.zone_rnd(1, dnssec=False) t.link(zone, master, slave, ddns=True) t.start() # Wait for listening server with unsigned zone. old_serial = master.zone_wait(zone) slave.zone_wait(zone) t.xfr_diff(master, slave, zone) # Check NSEC absence. master.check_nsec(zone, nonsec=True) master.stop() # Enable autosigning. master.dnssec_enable = True master.gen_key(zone, ksk=True, alg="NSEC3RSASHA1") master.gen_key(zone, alg="NSEC3RSASHA1") master.gen_key(zone, ksk=True, alg="RSASHA256")
#!/usr/bin/env python3 '''Test for dropping of out of zone records during incoming XFR''' from dnstest.test import Test t = Test() master = t.server("bind") slave = t.server("knot") zone = t.zone("out-of-zone.") t.link(zone, master, slave) t.start() master.zones_wait(zone) slave.zones_wait(zone) t.xfr_diff(master, slave, zone) t.end()
#!/usr/bin/env python3 from dnstest.test import Test t = Test(tsig=True, stress=False) knot = t.server("knot") zone = t.zone("example.com") t.link(zone, knot, ddns=True) t.start() zone[0].name = "examPle.com" update = knot.update(zone) update.add("kNoT.ExamPle.com.", 60, "TXT", "test") update.add("test.example.com.", 60, "TXT", "test") update.send("NOERROR") resp = knot.dig("knot.example.com.", "TXT") resp.check(rcode="NOERROR", rdata="test") t.end()
'''RRL module functionality test''' import dns.exception import dns.message import dns.query import os import time from dnstest.libknot import libknot from dnstest.test import Test from dnstest.module import ModRRL from dnstest.utils import * ctl = libknot.control.KnotCtl() t = Test(stress=False) ModRRL.check() knot = t.server("knot") zones = t.zone_rnd(2, dnssec=False, records=1) t.link(zones, knot) def send_queries(server, name, run_time=1.0, query_time=0.05): """ Send UDP queries to the server for certain time and get replies statistics. """ replied, slipped, dropped = 0, 0, 0 start = time.time() while time.time() < start + run_time:
#!/usr/bin/env python3 '''NSEC test based on RFC-4035 example.''' from dnstest.test import Test t = Test() knot = t.server("knot") knot.DIG_TIMEOUT = 2 bind = t.server("bind") zone = t.zone("example.", "example.zone.nsec", storage=".") t.link(zone, knot) t.link(zone, bind) t.start() # B1. Answer. resp = knot.dig("x.w.example", "MX", dnssec=True) resp.check(rcode="NOERROR", flags="QR AA", eflags="DO") resp.cmp(bind) # B2. Name Error. resp = knot.dig("ml.example", "A", dnssec=True) resp.check(rcode="NXDOMAIN", flags="QR AA", eflags="DO") resp.cmp(bind) # B3. No Data Error. resp = knot.dig("ns1.example", "MX", dnssec=True) resp.check(rcode="NOERROR", flags="QR AA", eflags="DO")
#!/usr/bin/env python3 '''Test for IXFR from Knot to Bind''' from dnstest.test import Test t = Test() master = t.server("knot") slave = t.server("bind") zones = t.zone_rnd(5, records=50) + t.zone("wild.") + \ t.zone("cname-loop.") + t.zone("records.") t.link(zones, master, slave, ixfr=True) t.start() # Wait for AXFR to slave server. serials_init = master.zones_wait(zones) slave.zones_wait(zones) serials_prev = serials_init for i in range(4): # Update zone files on master. for zone in zones: master.update_zonefile(zone, random=True) master.reload() t.sleep(5) # Wait for IXFR to slave.
#!/usr/bin/env python3 '''Test of Knot behavior when master has older SOA''' from dnstest.test import Test TEST_START_EXPECTED = 4 t = Test() master = t.server("knot") slave = t.server("knot") zone = t.zone("example.", storage=".") t.link(zone, master, slave) master.disable_notify = True slave.disable_notify = True t.start() # initial convenience check master.zone_wait(zone) slave.zone_wait(zone) resp = slave.dig("added.example.", "A") resp.check(rcode="NOERROR", rdata="1.2.3.4") # check that slave ignored outdated master
if before_keys < 2 or after_keys > 1: check_zone(server, zone, total_keys, 2, 1, 1 if before_keys > 1 else 2, desc + ": both still active") # else skip the test as we have no control on KSK and ZSK retiring asynchronously wait_for_rrsig_count(t, server, "DNSKEY", 1, 20) if before_keys < 2 or after_keys > 1: check_zone(server, zone, total_keys, 1, 1, 1, desc + ": old key retired") # else skip the test as we have no control on KSK and ZSK retiring asynchronously wait_for_dnskey_count(t, server, after_keys, 20) check_zone(server, zone, after_keys, 1, 1, 1, desc + ": old key removed") t = Test() ModOnlineSign.check() parent = t.server("knot") parent_zone = t.zone("com.", storage=".") t.link(parent_zone, parent) child = t.server("knot") child_zone = t.zone("example.com.") t.link(child_zone, child) def cds_submission(): cds = child.dig(ZONE, "CDS") cds_rdata = cds.resp.answer[0].to_rdataset()[0].to_text()
#!/usr/bin/env python3 '''Test that removal of nonexisting or addition of existing record over IXFR is not accepted by a slave''' from dnstest.test import Test from dnstest.utils import * t = Test() master = t.server("knot") slave = t.server("knot") zone = t.zone("existing.", storage=".") t.link(zone, master, slave, ixfr=True) slave.update_zonefile(zone, version="slave0") t.start() serial = master.zone_wait(zone) slave.zone_wait(zone) # Check that removal of nonexisting record is not accepted master.update_zonefile(zone, version=1) master.reload() serial = slave.zone_wait(zone, serial) if not slave.log_search("no such record in zone found" ) or not slave.log_search("fallback to AXFR"):
#!/usr/bin/env python3 '''Test for flush event''' from dnstest.utils import * from dnstest.test import Test import os FLUSH_SLEEP = 5.5 t = Test() master = t.server("bind") slave = t.server("knot") slave.zonefile_sync = "5s" zone = t.zone("example.") zone_path = slave.dir + "/slave/" + zone[0].file_name t.link(zone, master, slave) t.start() slave.stop() try: os.remove(zone_path) except: pass slave.start() slave.zone_wait(zone) #check that the zone file has not been flushed if os.path.exists(zone_path):
break # Verify the zone instead of a dumb sleep server.zone_backup(zone, flush=True) server.zone_verify(zone) if time.monotonic() > endtime: break def writef(filename, contents): with open(filename, "w") as f: f.write(contents) t = Test() knot = t.server("knot") ZONE = "example.com." FUTURE = 55 TICK = 5 STARTUP = 10 zone = t.zone(ZONE) t.link(zone, knot) knot.zonefile_sync = 24 * 60 * 60 knot.dnssec(zone).enable = True knot.dnssec(zone).manual = True knot.dnssec(zone).alg = "ECDSAP384SHA384"
from dnstest.test import Test def test_expire(zone, server): resp = server.dig(zone[0].name, "SOA") resp.check(rcode="SERVFAIL") def break_xfrout(server): with open(server.confile, "r+") as f: config = f.read() f.seek(0) f.truncate() config = config.replace(" acl:", " #acl:") f.write(config) t = Test(tsig=False) # this zone has refresh = 1s, retry = 1s and expire = 8s zone = t.zone("example.", storage=".") EXPIRE_SLEEP = 15 master = t.server("knot") slave = t.server("knot") slave.tcp_idle_timeout = "1s" t.link(zone, master, slave) t.start() master.zone_wait(zone) slave.zone_wait(zone)
#!/usr/bin/env python3 '''NSEC test based on RFC-4035 example.''' from dnstest.test import Test t = Test() knot = t.server("knot") knot.DIG_TIMEOUT = 2 bind = t.server("bind") zone = t.zone("example.", "example.zone.nsec", storage=".") t.link(zone, knot) t.link(zone, bind) t.start() # B1. Answer. resp = knot.dig("x.w.example", "MX", dnssec=True) resp.check(rcode="NOERROR", flags="QR AA", eflags="DO") resp.cmp(bind) # B2. Name Error. resp = knot.dig("ml.example", "A", dnssec=True) resp.check(rcode="NXDOMAIN", flags="QR AA", eflags="DO") resp.cmp(bind) # B3. No Data Error. resp = knot.dig("ns1.example", "MX", dnssec=True) resp.check(rcode="NOERROR", flags="QR AA", eflags="DO") resp.cmp(bind)
if found_dnskeys != expect_dnskeys or found_rrsigs != expect_rrsigs: set_err("BAD DNSKEY: " + msg) detail_log("!DNSKEYs not published and activated as expected: " + msg) detail_log(SEP) # return date 'offset' seconds in future def date_offset(offset): delta = datetime.timedelta(seconds=offset) current_time = datetime.datetime.utcnow() future_time = current_time + delta return datetime.datetime.strftime(future_time, "%Y%m%d%H%M%S") t = Test() knot = t.server("knot") knot.dnssec_enable = True zone = t.zone("example.com.") t.link(zone, knot) # install keys (one always enabled, one for testing) shutil.copytree(os.path.join(t.data_dir, "keys"), knot.keydir) # parameters key_file = os.path.join(knot.keydir, "test.private") date_past = "19700101000001" date_future = "20400101000000" WAIT_SIGN = 2
#!/usr/bin/env python3 """ DNSSEC Single-Type Signing Scheme, RFC 6781 """ from dnstest.utils import * from dnstest.test import Test t = Test() knot = t.server("knot") zones = t.zone_rnd(5, dnssec=False, records=10) t.link(zones, knot) t.start() # one KSK knot.gen_key(zones[0], ksk=True, zsk=True, alg="ECDSAP256SHA256", key_len="256") # multiple KSKs knot.gen_key(zones[1], ksk=True, zsk=True, alg="ECDSAP384SHA384", key_len="384") knot.gen_key(zones[1], ksk=True, zsk=True, alg="ECDSAP256SHA256", key_len="256") # different algorithms: KSK+ZSK pair, one KSK knot.gen_key(zones[2], ksk=True, alg="ECDSAP256SHA256", key_len="256") knot.gen_key(zones[2], ksk=False, alg="ECDSAP256SHA256", key_len="256") knot.gen_key(zones[2], ksk=True, zsk=True, alg="ECDSAP384SHA384", key_len="384") # one ZSK knot.gen_key(zones[3], ksk=False, alg="ECDSAP256SHA256", key_len="256").change_role(ksk=True, zsk=True) for zone in zones[:-1]: knot.dnssec(zone).enable = True
#!/usr/bin/env python3 '''TTL mismatch test''' from dnstest.utils import * from dnstest.test import Test t = Test() zone = t.zone("example.com.") master = t.server("knot") t.link(zone, master, ddns=True) t.start() # Add new RR with different TTL to a RRSet that is already in the zone # The UPDATE should be accepted and all previous TTLs should change to be the same value check_log("Add RR with different TTL") up = master.update(zone) up.add("mail.example.com.", 1000, "A", "1.2.3.4") up.send("NOERROR") resp = master.dig("mail.example.com.", "A") resp.check(rcode="NOERROR") resp.check_record(section="answer", rtype="A", ttl="1000", rdata="192.0.2.3") resp.check_record(section="answer", rtype="A", ttl="1000", rdata="1.2.3.4") # Try to add two RRs belonging to one RRSet, but with different TTLs # The UPDATE should be accepted and all TTLs should change to be the same value check_log("Add RRSet with incoherent TTLs")
#!/usr/bin/env python3 '''Manual DDNS testing''' from dnstest.utils import * from dnstest.test import Test t = Test() def check_soa(master, prev_soa): soa_resp = master.dig("ddns.", "SOA") compare(prev_soa, soa_resp.resp.answer, "SOA changed when it shouldn't") def verify(master, zone, dnssec): if not dnssec: return master.flush() t.sleep(1) master.zone_verify(zone) def do_normal_tests(master, zone, dnssec=False): # add node check_log("Node addition") up = master.update(zone) up.add("rrtest.ddns.", 3600, "A", "1.2.3.4") up.send("NOERROR") resp = master.dig("rrtest.ddns.", "A") resp.check(rcode="NOERROR", rdata="1.2.3.4") verify(master, zone, dnssec) # add record to existing rrset
check_soa_diff(master, slave, zone[0], min_diff, max_diff) # test AXFR bootstrap with shifted serial slave.stop() server_purge(slave, zone, False) update = master.update(zone) update.add("new2.example.com.", 3600, "A", addr) update.send("NOERROR") t.sleep(1) slave.start() slave.zone_wait(zone) check_new_rr(slave, new2) check_soa_diff(master, slave, zone[0], min_diff, max_diff) t = Test() master = t.server("knot") slave = t.server("knot") zone = t.zone("example.com.", storage=".") t.link(zone, master, slave, ddns=True) slave.dnssec(zone).enable = True t.start() test_one(master, slave, zone, "increment", "increment", 1000, 0, 0, 2, 3) test_one(master, slave, zone, "unixtime", "unixtime", int(time.time()), 1, 30, 1, 30)
#!/usr/bin/env python3 '''Test for header flags in response''' from dnstest.test import Test t = Test() knot = t.server("knot") bind = t.server("bind") zone = t.zone("flags.") # Disable ANY over UDP knot.disable_any = True t.link(zone, knot) t.link(zone, bind) t.start() # RD flag preservation. resp = knot.dig("flags", "NS", flags="RD") resp.check(flags="QR AA RD", noflags="TC RA AD CD Z") resp.cmp(bind) # CD flag preservation. resp = knot.dig("flags", "NS", flags="CD") resp.check(flags="QR AA CD", noflags="TC RA AD RD Z") resp.cmp(bind) # TC flag must be cleared resp = knot.dig("flags", "NS", flags="TC")
#!/usr/bin/env python3 '''Test for reload of a changed zone (serial up, nochange, serial down).''' from dnstest.test import Test from dnstest.utils import set_err, detail_log import random t = Test() master = t.server("knot") # Zone setup zone = t.zone("serial.", storage=".") t.link(zone, master, ixfr=True) t.start() # Load zones serial = master.zone_wait(zone) def reload_zone(version, exp_serial, exp_version): master.update_zonefile(zone, version) if random.random() < 0.5: master.reload() else: master.ctl(random.choice(["-f", " "]) + " zone-reload " + zone[0].name, wait=True)
#!/usr/bin/env python3 '''Test for loading of dumped zone''' from dnstest.test import Test t = Test() master = t.server("bind") slave = t.server("knot") reference = t.server("bind") zones = t.zone_rnd(4) + t.zone(".") + t.zone("records.") t.link(zones, master, slave) t.link(zones, reference) t.start() # Wait for servers. master.zones_wait(zones) slave.zones_wait(zones) reference.zones_wait(zones) # Dump zones on slave. slave.flush(wait=True) # Compare master with reference server t.xfr_diff(reference, master, zones) # Compare slave with reference server t.xfr_diff(reference, slave, zones)
check_log("ZONE SOA TIMERS: REFRESH = 1, RETRY = 20, EXPIRE = 10") master.update_zonefile(zone, version=2) init_servers(master, slave) test_run_case(t, master, slave, action) def reload_server(t, s): s.reload() t.sleep(1) def restart_server(t, s): s.stop() s.start() t = Test() zone = t.zone("example.", storage=".") servers = create_servers(t, 2, zone) t.start() check_log("/// ACTION RELOAD ///") test_run(t, servers[0], zone, reload_server) check_log("/// ACTION RESTART ///") test_run(t, servers[1], zone, restart_server) t.stop()
#!/usr/bin/env python3 '''Test for empty rdata loading.''' from dnstest.test import Test t = Test() master = t.server("knot") slave = t.server("knot") zone = t.zone("empty.", storage=".") t.link(zone, master, slave) t.start() master.zones_wait(zone) slave.zones_wait(zone) slave.flush() t.sleep(1) t.end()