mirror of
https://github.com/isc-projects/bind9.git
synced 2026-07-07 10:40:54 -04:00
System test covering SERVFAIL cache and CNAME
Add a system test for the case where resolution SERVFAILs because the fetch context reaches the `max-query-count` threshold while following a CNAME. Resolving the CNAME target independently should still work, because the SERVFAIL cache stores the original query name rather than the target.
This commit is contained in:
parent
1fe179973e
commit
d238b8eece
3 changed files with 113 additions and 0 deletions
53
bin/tests/system/sfcache_cname/ans1/ans.py
Normal file
53
bin/tests/system/sfcache_cname/ans1/ans.py
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
|
||||
import dns.name
|
||||
import dns.rcode
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
import dns.rrset
|
||||
|
||||
from isctest.asyncserver import AsyncDnsServer, QnameQtypeHandler, StaticResponseHandler
|
||||
|
||||
|
||||
def rrset(
|
||||
qname: dns.name.Name | str,
|
||||
rtype: dns.rdatatype.RdataType,
|
||||
rdata: str,
|
||||
ttl: int = 300,
|
||||
) -> dns.rrset.RRset:
|
||||
return dns.rrset.from_text(qname, ttl, dns.rdataclass.IN, rtype, rdata)
|
||||
|
||||
|
||||
class Tld1Handler(QnameQtypeHandler, StaticResponseHandler):
|
||||
qnames = ["foo.tld1."]
|
||||
qtypes = [dns.rdatatype.A]
|
||||
answer = [rrset("foo.tld1.", dns.rdatatype.CNAME, "tld2.")]
|
||||
|
||||
|
||||
class Tld2Handler(QnameQtypeHandler, StaticResponseHandler):
|
||||
qnames = ["tld2."]
|
||||
qtypes = [dns.rdatatype.A]
|
||||
answer = [rrset("tld2.", dns.rdatatype.A, "1.2.3.4")]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
server = AsyncDnsServer(default_aa=True, default_rcode=dns.rcode.NOERROR)
|
||||
server.install_response_handlers(
|
||||
Tld1Handler(),
|
||||
Tld2Handler(),
|
||||
)
|
||||
server.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
26
bin/tests/system/sfcache_cname/ns2/named.conf.j2
Normal file
26
bin/tests/system/sfcache_cname/ns2/named.conf.j2
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
options {
|
||||
query-source address @ns.ip@;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { @ns.ip@; };
|
||||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
dnssec-validation no;
|
||||
qname-minimization off;
|
||||
servfail-ttl 5;
|
||||
max-query-count 2;
|
||||
};
|
||||
|
||||
{% include "_common/controls.conf.j2" %}
|
||||
|
||||
zone "tld1." {
|
||||
type forward;
|
||||
forward only;
|
||||
forwarders { 10.53.0.1; };
|
||||
};
|
||||
|
||||
zone "tld2." {
|
||||
type forward;
|
||||
forward only;
|
||||
forwarders { 10.53.0.1; };
|
||||
};
|
||||
34
bin/tests/system/sfcache_cname/tests_sfcache_cname.py
Normal file
34
bin/tests/system/sfcache_cname/tests_sfcache_cname.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
|
||||
import dns.message
|
||||
|
||||
import isctest
|
||||
|
||||
|
||||
# A SERVFAIL produced while following a CNAME must be cached against the
|
||||
# original query name, not the CNAME target.
|
||||
#
|
||||
# ans1 serves "foo.tld1 CNAME tld2" and "tld2 A 1.2.3.4"; ns2 forwards
|
||||
# both zones to it with "max-query-count 2". Resolving "foo.tld1/A"
|
||||
# follows the CNAME to "tld2" and then exhausts the query budget, so the
|
||||
# client gets SERVFAIL. That failure must be cached under the original
|
||||
# name ("foo.tld1"), so a subsequent direct query for the CNAME target
|
||||
# ("tld2") is not blocked by the SERVFAIL cache and resolves normally.
|
||||
def test_sfcache_cname(ns2):
|
||||
msg = dns.message.make_query("foo.tld1.", "A")
|
||||
res = isctest.query.udp(msg, ns2.ip)
|
||||
isctest.check.servfail(res)
|
||||
|
||||
msg = dns.message.make_query("tld2.", "A")
|
||||
res = isctest.query.udp(msg, ns2.ip)
|
||||
isctest.check.noerror(res)
|
||||
Loading…
Reference in a new issue