mirror of
https://gitlab.nic.cz/knot/knot-dns.git
synced 2026-05-28 04:02:31 -04:00
nameserver: decrease maximum CNAME/DNAME chain length from 20 to 5
The reason for this change is to reduce possible amplification attacks and other negative effects of long processing loops. Also most resolvers don't accept multiple jumps without requerying, so this change should be harmless.
This commit is contained in:
parent
06a319cab0
commit
1f98f8dc18
4 changed files with 32 additions and 11 deletions
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
|
||||
/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
#include "knot/nameserver/process_query.h"
|
||||
|
||||
/*! \brief Don't follow CNAME/DNAME chain beyond this depth. */
|
||||
#define CNAME_CHAIN_MAX 20
|
||||
#define CNAME_CHAIN_MAX 5
|
||||
|
||||
/*!
|
||||
* \brief Answer query from an IN class zone.
|
||||
|
|
|
|||
|
|
@ -70,7 +70,11 @@ d.dname-tree CNAME cname-wildcard
|
|||
e.dname-tree CNAME e.dname
|
||||
f.dname-tree DNAME f.f.dname-tree
|
||||
|
||||
dname-loop DNAME loop.dname-loop
|
||||
dname-outloop DNAME loop.dname-outloop
|
||||
|
||||
loop.dname-inloop A 1.2.3.4
|
||||
loop.dname-inloop DNAME dname-inloop
|
||||
|
||||
dname-out DNAME outside.zone.
|
||||
dname-dangl DNAME dangling
|
||||
dname.below.sub DNAME dname-tree
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ resp.check_count(3, rtype="CNAME")
|
|||
|
||||
resp = knot.dig("chain.follow", "AAAA", udp=False)
|
||||
resp.check(rcode="NOERROR")
|
||||
resp.check_count(20, rtype="CNAME")
|
||||
resp.check_count(5, rtype="CNAME")
|
||||
resp.check_count(0, rtype="AAAA")
|
||||
|
||||
# query for RRSIG
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ resp.cmp(bind)
|
|||
# Long CNAME loop (Bind truncates the loop at 17 records)
|
||||
resp = knot.dig("ab.flags", "A", udp=True)
|
||||
resp.check(rcode="NOERROR")
|
||||
compare(resp.count(rtype="CNAME", section="answer"), 19, "Count of CNAME records in loop.")
|
||||
compare(resp.count(rtype="CNAME", section="answer"), 5, "Count of CNAME records in loop.")
|
||||
|
||||
''' CNAME in MX EXCHANGE. '''
|
||||
|
||||
|
|
@ -212,15 +212,32 @@ resp.check_record(name="dname.flags.", rtype="DNAME", ttl=3600, rdata="
|
|||
resp.check_record(name="x.f.dname.flags.", rtype="CNAME", ttl=3600, rdata="x.f.dname-tree.flags.")
|
||||
resp.check_record(name="f.dname-tree.flags.", rtype="DNAME", ttl=3600, rdata="f.f.dname-tree.flags.")
|
||||
resp.check_record(name="x.f.dname-tree.flags.", rtype="CNAME", ttl=3600, rdata="x.f.f.dname-tree.flags.")
|
||||
resp.check_counts(22, 0, 0)
|
||||
# resp.cmp(bind) BIND responds partially unrolled CNAME loop
|
||||
resp.check_counts(7, 0, 0)
|
||||
# resp.cmp(bind) BIND responds deeply unrolled CNAME loop
|
||||
|
||||
# Infinite DNAME loop
|
||||
resp = knot.dig("end.dname-loop.flags", "A", udp=False)
|
||||
resp = knot.dig("end.dname-outloop.flags", "A", udp=True)
|
||||
resp.check(rcode="NOERROR")
|
||||
resp.check_record(name="dname-loop.flags.", rtype="DNAME", ttl=3600, rdata="loop.dname-loop.flags.")
|
||||
compare(resp.count(rtype="CNAME", section="answer"), 20, "Count of synthesized CNAME records in loop.")
|
||||
resp.check_record(name="end.loop.loop.loop.dname-loop.flags.", rtype="CNAME", ttl=3600, rdata="end.loop.loop.loop.loop.dname-loop.flags.")
|
||||
resp.check_record(name="dname-outloop.flags.", rtype="DNAME", ttl=3600, rdata="loop.dname-outloop.flags.")
|
||||
compare(resp.count(rtype="CNAME", section="answer"), 5, "Count of synthesized CNAME records in loop.")
|
||||
resp.check_record(name="end.loop.loop.loop.loop.dname-outloop.flags.", rtype="CNAME", ttl=3600,
|
||||
rdata="end.loop.loop.loop.loop.loop.dname-outloop.flags.")
|
||||
resp.check_counts(6, 0, 0)
|
||||
|
||||
# Recursive DNAME loop - full
|
||||
resp = knot.dig("loop.loop.loop.loop.loop.loop.dname-inloop.flags", "A", udp=True)
|
||||
resp.check(rcode="NOERROR")
|
||||
resp.check_record(name="loop.dname-inloop.flags.", rtype="DNAME", ttl=3600, rdata="dname-inloop.flags.")
|
||||
compare(resp.count(rtype="CNAME", section="answer"), 5, "Count of synthesized CNAME records in loop.")
|
||||
resp.check_record(name="loop.dname-inloop.flags.", rtype="A", ttl=3600, rdata="1.2.3.4")
|
||||
resp.check_counts(7, 0, 0)
|
||||
|
||||
# Recursive DNAME loop - incomplete
|
||||
resp = knot.dig("loop.loop.loop.loop.loop.loop.loop.dname-inloop.flags", "A", udp=True)
|
||||
resp.check(rcode="NOERROR")
|
||||
resp.check_record(name="loop.dname-inloop.flags.", rtype="DNAME", ttl=3600, rdata="dname-inloop.flags.")
|
||||
compare(resp.count(rtype="CNAME", section="answer"), 5, "Count of synthesized CNAME records in loop.")
|
||||
resp.check_counts(6, 0, 0)
|
||||
|
||||
''' Wildcard answers. '''
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue