implement 'max-query-restarts'

implement, document, and test the 'max-query-restarts' option
which specifies the query restart limit - the number of times
we can follow CNAMEs before terminating resolution.

(cherry picked from commit 104f3b82fb)
This commit is contained in:
Evan Hunt 2024-06-25 23:49:00 -07:00
parent a11367ade3
commit 2e04f0380c
9 changed files with 60 additions and 8 deletions

View file

@ -175,6 +175,7 @@ options {\n\
max-ncache-ttl 10800; /* 3 hours */\n\
max-recursion-depth 7;\n\
max-recursion-queries 32;\n\
max-query-restarts 11;\n\
max-stale-ttl 86400; /* 1 day */\n\
message-compression yes;\n\
min-ncache-ttl 0; /* 0 hours */\n\

View file

@ -5585,6 +5585,11 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
INSIST(result == ISC_R_SUCCESS);
dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj));
obj = NULL;
result = named_config_get(maps, "max-query-restarts", &obj);
INSIST(result == ISC_R_SUCCESS);
dns_view_setmaxrestarts(view, cfg_obj_asuint32(obj));
obj = NULL;
result = named_config_get(maps, "fetches-per-zone", &obj);
INSIST(result == ISC_R_SUCCESS);

View file

@ -35,11 +35,28 @@ key rndc_key {
algorithm @DEFAULT_HMAC@;
};
key restart16 {
secret "1234abcd8765";
algorithm @DEFAULT_HMAC@;
};
controls {
inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "." {
type hint;
file "root.hint";
view restart16 {
match-clients { key restart16; none; };
max-query-restarts 16;
zone "." {
type hint;
file "root.hint";
};
};
view default {
zone "." {
type hint;
file "root.hint";
};
};

View file

@ -442,11 +442,13 @@ n=$((n + 1))
echo_i "checking CNAME loops are detected (resolver) ($n)"
ret=0
$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
$DIG $DIGOPTS @10.53.0.7 loop.example >dig.out.test$n
grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
grep "ANSWER: 0" dig.out.test$n >/dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
$DIG $DIGOPTS @10.53.0.7 loop.example >dig.out.1.test$n
grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1
grep "ANSWER: 12" dig.out.1.test$n >/dev/null || ret=1
# also check with max-query-restarts 16:
$DIG $DIGOPTS @10.53.0.7 -y "${DEFAULT_HMAC}:restart16:1234abcd8765" loop.example >dig.out.2.test$n
grep "status: NOERROR" dig.out.2.test$n >/dev/null || ret=1
grep "ANSWER: 17" dig.out.2.test$n >/dev/null || ret=1
n=$((n + 1))
echo_i "checking CNAME loops are detected (auth) ($n)"

View file

@ -77,6 +77,7 @@ options {
check-names primary warn;
check-names secondary ignore;
max-cache-size 20000000000000;
max-query-restarts 10;
nta-lifetime 604800;
nta-recheck 604800;
validate-except {
@ -109,6 +110,7 @@ view "first" {
max-ixfr-ratio unlimited;
};
dnssec-validation auto;
max-query-restarts 15;
zone-statistics terse;
};
view "second" {

View file

@ -4697,6 +4697,14 @@ Tuning
is a CNAME, then the subsequent lookup for the target of the CNAME is
counted separately.) The default is 32.
.. namedconf:statement:: max-query-restarts
:tags: server, query
:short: Sets the maximum number of chained CNAMEs to follow
This sets the maximum number of successive CNAME targets to follow
when resolving a client query, before terminating the query to avoid a
CNAME loop. Valid values are 1 to 255. The default is 11.
.. namedconf:statement:: notify-delay
:tags: transfer, zone
:short: Sets the delay (in seconds) between sending sets of NOTIFY messages for a zone.

View file

@ -180,6 +180,7 @@ options {
max-ixfr-ratio ( unlimited | <percentage> );
max-journal-size ( default | unlimited | <sizeval> );
max-ncache-ttl <duration>;
max-query-restarts <integer>;
max-records <integer>;
max-records-per-type <integer>;
max-recursion-depth <integer>;
@ -472,6 +473,7 @@ view <string> [ <class> ] {
max-ixfr-ratio ( unlimited | <percentage> );
max-journal-size ( default | unlimited | <sizeval> );
max-ncache-ttl <duration>;
max-query-restarts <integer>;
max-records <integer>;
max-records-per-type <integer>;
max-recursion-depth <integer>;

View file

@ -1943,6 +1943,20 @@ check_options(const cfg_obj_t *options, const cfg_obj_t *config,
}
}
obj = NULL;
(void)cfg_map_get(options, "max-query-restarts", &obj);
if (obj != NULL) {
uint32_t restarts = cfg_obj_asuint32(obj);
if (restarts == 0 || restarts > 255) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"'max-query-restarts' is out of "
"range 1..255)");
if (result == ISC_R_SUCCESS) {
result = ISC_R_RANGE;
}
}
}
if (actx != NULL) {
cfg_aclconfctx_detach(&actx);
}

View file

@ -2105,6 +2105,7 @@ static cfg_clausedef_t view_clauses[] = {
{ "max-ncache-ttl", &cfg_type_duration, 0 },
{ "max-recursion-depth", &cfg_type_uint32, 0 },
{ "max-recursion-queries", &cfg_type_uint32, 0 },
{ "max-query-restarts", &cfg_type_uint32, 0 },
{ "max-stale-ttl", &cfg_type_duration, 0 },
{ "max-udp-size", &cfg_type_uint32, 0 },
{ "message-compression", &cfg_type_boolean, 0 },