knot-dns/tests-extra/tests/modules/synthrecord/test.py
2022-12-10 15:52:12 +01:00

160 lines
7.8 KiB
Python

#!/usr/bin/env python3
''' Check 'synth_record' query module synthetic responses. '''
from dnstest.test import Test
from dnstest.module import ModSynthRecord, ModOnlineSign
import random
import re
t = Test()
ModSynthRecord.check()
onlinesign = random.choice([True, False])
try:
ModOnlineSign.check()
except:
onlinesign = False
# Zone indexes
FWD = 0
REV4 = 1
REV6 = 2
REV = 3
REV4CIDR = 4
# 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.zone("ip6.arpa.", storage=".") + \
t.zone("0/25.2.0.10.in-addr.arpa.", storage=".", file_name="0-25.2.0.10.in-addr.arpa.zone")
t.link(zone, knot)
# Configure 'synth_record' modules for auto forward/reverse zones
knot.add_module(zone[FWD], ModSynthRecord("forward", None, None, "192.168.0.1"))
knot.add_module(zone[FWD], ModSynthRecord("forward", "dynamic-", "900", "[ 192.168.1.0-192.168.1.127, 2620:0:b61::/52 ]"))
knot.add_module(zone[REV4], ModSynthRecord("reverse", "dynamic-", "900", "[ 192.168.3.0/25, 192.168.1.0/25, 192.168.2.0/25 ]", "forward."))
knot.add_module(zone[REV6], ModSynthRecord("reverse", "dynamic-", "900", "2620:0000:0b61::-2620:0000:0b61:0fff:ffff:ffff:ffff:ffff", "forward."))
knot.add_module(zone[REV], ModSynthRecord("reverse", "", "900", "::0/0", "forward."))
knot.add_module(zone[REV4CIDR], ModSynthRecord("reverse", "dynamic-", "900", "[ 10.0.2.0/25 ]", "forward."))
if onlinesign:
for z in zone:
knot.add_module(z, ModOnlineSign())
def check_rrsig(resp, expect):
resp.check_count(expect if onlinesign else 0, rtype="RRSIG", section="answer")
def check_nsec(resp, expect):
resp.check_count(expect if onlinesign else 0, rtype="NSEC", section="authority")
resp.check_count(expect + 1 if onlinesign else 0, rtype="RRSIG", section="authority") # +1 for SOA
t.start()
# Static address mapping
static_map = [ ("192.168.1.42", "42." + zone[REV4].name, "static4-a.forward."),
("2620:0:b61::42", "2.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0." + zone[REV6].name, "static6-a.forward.") ]
# Check static reverse records
for (_, reverse, forward) in static_map:
resp = knot.dig(reverse, "PTR", dnssec=True)
resp.check(forward, rcode="NOERROR", flags="QR AA", ttl=172800)
check_rrsig(resp, 1)
# Check static forward records
for (addr, reverse, forward) in static_map:
rrtype = "AAAA" if ":" in addr else "A"
resp = knot.dig(forward, rrtype, dnssec=True)
resp.check(addr, rcode="NOERROR", flags="QR AA", ttl=7200)
check_rrsig(resp, 1)
# Check positive dynamic reverse records
dynamic_map = [ ("192.168.1.1", "1." + zone[REV4].name, "dynamic-192-168-1-1." + zone[FWD].name),
("2620:0:b61::1", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0." + zone[REV6].name, "dynamic-2620-0-b61--1." + zone[FWD].name) ]
# < > < > < > < > < > < > < > < >
reverse_extra = [ ("", "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0." + zone[REV].name, "0-0--0." + zone[FWD].name),
("", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0." + zone[REV].name, "0-0--1." + zone[FWD].name),
("", "0.0.0.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0." + zone[REV].name, "0-0--1-0." + zone[FWD].name),
("", "0.0.0.0.0.0.0.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0." + zone[REV].name, "0-0--1-0-0." + zone[FWD].name),
("", "0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0." + zone[REV].name, "0-0--1-0-0-0." + zone[FWD].name),
("", "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0." + zone[REV].name, "0-0-0-1--0." + zone[FWD].name),
("", "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.0.0.0.0.0.0.0." + zone[REV].name, "0-0-1--0." + zone[FWD].name),
("", "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.0.0.0." + zone[REV].name, "0-1--0." + zone[FWD].name),
("", "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0." + zone[REV].name, "1-0--0." + zone[FWD].name),
("", "0.0.0.1.0.0.2.0.0.3.0.0.4.0.0.0.a.b.c.d.0.e.f.0.a.a.0.0.0.0.b.b." + zone[REV].name, "bb00-aa-fe0-dcba-4-30-200-1000." + zone[FWD].name) ]
reverse_cidr = [ ("", "126." + zone[REV4CIDR].name, "dynamic-10-0-2-126." + zone[FWD].name) ]
for (_, reverse, forward) in dynamic_map + reverse_extra + reverse_cidr:
resp = knot.dig(reverse, "PTR", dnssec=True)
resp.check(forward, rcode="NOERROR", flags="QR AA", ttl=900)
check_rrsig(resp, 1)
# Check positive dynamic forward records (default TTL and prefix)
resp = knot.dig("192-168-0-1.forward", "A", dnssec=True)
resp.check("192.168.0.1", rcode="NOERROR", ttl=3600)
check_rrsig(resp, 1)
# Check positive dynamic forward records
forward_extra = [ ("2620:0:b61::", "", "dynamic-2620-0-b61--." + zone[FWD].name),
("2620:0:b61::1", "", "dynamic-2620-0-b61--1." + zone[FWD].name),
("2620:0:b61::10", "", "dynamic-2620-0-b61--10." + zone[FWD].name),
("2620:0:b61::100", "", "dynamic-2620-0-b61--100." + zone[FWD].name),
("2620:0:b61::1000", "", "dynamic-2620-0-b61--1000." + zone[FWD].name),
("2620:0:b61::", "", "dynamic-2620-0-b61-0-0-0-0-0." + zone[FWD].name) ]
for (addr, reverse, forward) in dynamic_map + forward_extra:
rrtype = "AAAA" if ":" in addr else "A"
resp = knot.dig(forward, rrtype, dnssec=True)
resp.check(addr, rcode="NOERROR", flags="QR AA", ttl=900)
check_rrsig(resp, 1)
# Check NODATA answer for all records
for (addr, reverse, forward) in dynamic_map:
resp = knot.dig(reverse, "TXT", dnssec=True)
resp.check(nordata=forward, rcode="NOERROR", flags="QR AA", ttl=172800)
check_nsec(resp, 1)
resp = knot.dig(forward, "TXT", dnssec=True)
resp.check(nordata=addr, rcode="NOERROR", flags="QR AA", ttl=172800)
check_nsec(resp, 1)
# Check NODATA on resulting empty-non-terminals
for (_, reverse, forward) in dynamic_map + reverse_extra:
while knot.dig(reverse, "SOA").count("SOA") < 1: # until we hit zone apex
reverse = re.sub(r'^[^.]*\.', '', reverse) # cut out the leftmost label
resp = knot.dig(reverse, "PTR", dnssec=True)
resp.check(nordata=forward, rcode="NOERROR", flags="QR AA", ttl=172800)
check_nsec(resp, 1)
# Check "out of subnet range" query response
nxdomain_map = [ ("192.168.1.128", "128." + zone[REV4].name, "dynamic-192-168-1-128." + zone[FWD].name),
("2620:0:b61:1000::", "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1." + zone[REV6].name,
"dynamic-2620-0000-0b61-1000-0000-0000-0000-0000." + zone[FWD].name) ]
for (addr, reverse, forward) in nxdomain_map:
rrtype = "AAAA" if ":" in addr else "A"
exp_rcode = "NXDOMAIN" if not onlinesign else "NOERROR" # Onlinesign promotes NXDOMAIN to NODATA
resp = knot.dig(reverse, "PTR", dnssec=True)
resp.check(rcode=exp_rcode, flags="QR AA")
check_nsec(resp, 1)
resp = knot.dig(forward, rrtype, dnssec=True)
resp.check(rcode=exp_rcode, flags="QR AA")
check_nsec(resp, 1)
# Check alias leading to synthetic name
alias_map = [ ("192.168.1.1", None, "cname4." + zone[FWD].name),
("2620:0:b61::1", None, "cname6." + zone[FWD].name) ]
for (addr, _, forward) in alias_map:
rrtype = "AAAA" if ":" in addr else "A"
resp = knot.dig(forward, rrtype, dnssec=True)
resp.check(addr, rcode="NOERROR", flags="QR AA", ttl=900)
check_rrsig(resp, 2)
# Check ANY type question
for (addr, reverse, forward) in dynamic_map:
resp = knot.dig(forward, "ANY", dnssec=True)
resp.check(rcode="NOERROR", flags="QR AA")
check_rrsig(resp, 1)
t.end()