mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-29 05:28:00 +00:00
[master] improve RRL handling of deferrals and slipped NXDOMAIN
3590. [bug] When using RRL on recursive servers, defer rate-limiting until after recursion is complete; also, use correct rcode for slipped NXDOMAIN responses. [RT #33604]
This commit is contained in:
parent
c6eb92beb1
commit
89be55dc90
5
CHANGES
5
CHANGES
@ -1,3 +1,8 @@
|
|||||||
|
3590. [bug] When using RRL on recursive servers, defer
|
||||||
|
rate-limiting until after recursion is complete;
|
||||||
|
also, use correct rcode for slipped NXDOMAIN
|
||||||
|
responses. [RT #33604]
|
||||||
|
|
||||||
3589. [func] Report serial numbers in when starting zone transfers.
|
3589. [func] Report serial numbers in when starting zone transfers.
|
||||||
Report accepted NOTIFY requests including serial.
|
Report accepted NOTIFY requests including serial.
|
||||||
[RT# 33037]
|
[RT# 33037]
|
||||||
|
@ -6244,15 +6244,25 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Rate limit these responses to this client.
|
* Rate limit these responses to this client.
|
||||||
|
* Do not delay counting and handling obvious referrals,
|
||||||
|
* since those won't come here again.
|
||||||
|
* Delay handling delegations for which we are certain to recurse and
|
||||||
|
* return here (DNS_R_DELEGATION, not a child of one of our
|
||||||
|
* own zones, and recursion enabled)
|
||||||
|
* Don't mess with responses rewritten by RPZ
|
||||||
|
* Count each response at most once.
|
||||||
*/
|
*/
|
||||||
if (client->view->rrl != NULL &&
|
if (client->view->rrl != NULL &&
|
||||||
((fname != NULL && dns_name_isabsolute(fname)) ||
|
((fname != NULL && dns_name_isabsolute(fname)) ||
|
||||||
(result == ISC_R_NOTFOUND && !RECURSIONOK(client))) &&
|
(result == ISC_R_NOTFOUND && !RECURSIONOK(client))) &&
|
||||||
|
!(result == DNS_R_DELEGATION && !is_zone && RECURSIONOK(client)) &&
|
||||||
|
(client->query.rpz_st == NULL ||
|
||||||
|
(client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0)&&
|
||||||
(client->query.attributes & NS_QUERYATTR_RRL_CHECKED) == 0) {
|
(client->query.attributes & NS_QUERYATTR_RRL_CHECKED) == 0) {
|
||||||
dns_rdataset_t nc_rdataset;
|
dns_rdataset_t nc_rdataset;
|
||||||
isc_boolean_t wouldlog;
|
isc_boolean_t wouldlog;
|
||||||
char log_buf[DNS_RRL_LOG_BUF_LEN];
|
char log_buf[DNS_RRL_LOG_BUF_LEN];
|
||||||
isc_result_t nc_result;
|
isc_result_t nc_result, resp_result;
|
||||||
dns_rrl_result_t rrl_result;
|
dns_rrl_result_t rrl_result;
|
||||||
|
|
||||||
client->query.attributes |= NS_QUERYATTR_RRL_CHECKED;
|
client->query.attributes |= NS_QUERYATTR_RRL_CHECKED;
|
||||||
@ -6265,7 +6275,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
|||||||
*/
|
*/
|
||||||
if (db != NULL)
|
if (db != NULL)
|
||||||
tname = dns_db_origin(db);
|
tname = dns_db_origin(db);
|
||||||
rrl_result = result;
|
resp_result = result;
|
||||||
} else if (result == DNS_R_NCACHENXDOMAIN &&
|
} else if (result == DNS_R_NCACHENXDOMAIN &&
|
||||||
rdataset != NULL &&
|
rdataset != NULL &&
|
||||||
dns_rdataset_isassociated(rdataset) &&
|
dns_rdataset_isassociated(rdataset) &&
|
||||||
@ -6289,12 +6299,12 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
|||||||
}
|
}
|
||||||
dns_rdataset_disassociate(&nc_rdataset);
|
dns_rdataset_disassociate(&nc_rdataset);
|
||||||
}
|
}
|
||||||
rrl_result = DNS_R_NXDOMAIN;
|
resp_result = DNS_R_NXDOMAIN;
|
||||||
} else if (result == DNS_R_NXRRSET ||
|
} else if (result == DNS_R_NXRRSET ||
|
||||||
result == DNS_R_EMPTYNAME) {
|
result == DNS_R_EMPTYNAME) {
|
||||||
rrl_result = DNS_R_NXRRSET;
|
resp_result = DNS_R_NXRRSET;
|
||||||
} else if (result == DNS_R_DELEGATION) {
|
} else if (result == DNS_R_DELEGATION) {
|
||||||
rrl_result = result;
|
resp_result = result;
|
||||||
} else if (result == ISC_R_NOTFOUND) {
|
} else if (result == ISC_R_NOTFOUND) {
|
||||||
/*
|
/*
|
||||||
* Handle referral to ".", including when recursion
|
* Handle referral to ".", including when recursion
|
||||||
@ -6302,15 +6312,15 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
|||||||
* been loaded or we have "additional-from-cache no".
|
* been loaded or we have "additional-from-cache no".
|
||||||
*/
|
*/
|
||||||
tname = dns_rootname;
|
tname = dns_rootname;
|
||||||
rrl_result = DNS_R_DELEGATION;
|
resp_result = DNS_R_DELEGATION;
|
||||||
} else {
|
} else {
|
||||||
rrl_result = ISC_R_SUCCESS;
|
resp_result = ISC_R_SUCCESS;
|
||||||
}
|
}
|
||||||
rrl_result = dns_rrl(client->view, &client->peeraddr,
|
rrl_result = dns_rrl(client->view, &client->peeraddr,
|
||||||
ISC_TF((client->attributes
|
ISC_TF((client->attributes
|
||||||
& NS_CLIENTATTR_TCP) != 0),
|
& NS_CLIENTATTR_TCP) != 0),
|
||||||
client->message->rdclass, qtype, tname,
|
client->message->rdclass, qtype, tname,
|
||||||
rrl_result, client->now,
|
resp_result, client->now,
|
||||||
wouldlog, log_buf, sizeof(log_buf));
|
wouldlog, log_buf, sizeof(log_buf));
|
||||||
if (rrl_result != DNS_RRL_RESULT_OK) {
|
if (rrl_result != DNS_RRL_RESULT_OK) {
|
||||||
/*
|
/*
|
||||||
@ -6348,6 +6358,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
|||||||
dns_nsstatscounter_rateslipped);
|
dns_nsstatscounter_rateslipped);
|
||||||
client->message->flags |=
|
client->message->flags |=
|
||||||
DNS_MESSAGEFLAG_TC;
|
DNS_MESSAGEFLAG_TC;
|
||||||
|
if (resp_result == DNS_R_NXDOMAIN)
|
||||||
|
client->message->rcode =
|
||||||
|
dns_rcode_nxdomain;
|
||||||
}
|
}
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ options {
|
|||||||
|
|
||||||
rate-limit {
|
rate-limit {
|
||||||
responses-per-second 2;
|
responses-per-second 2;
|
||||||
all-per-second 70;
|
all-per-second 50;
|
||||||
slip 3;
|
slip 3;
|
||||||
exempt-clients { 10.53.0.7; };
|
exempt-clients { 10.53.0.7; };
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ SYSTEMTESTTOP=..
|
|||||||
. $SYSTEMTESTTOP/conf.sh
|
. $SYSTEMTESTTOP/conf.sh
|
||||||
|
|
||||||
#set -x
|
#set -x
|
||||||
#set -o noclobber
|
|
||||||
|
|
||||||
ns1=10.53.0.1 # root, defining the others
|
ns1=10.53.0.1 # root, defining the others
|
||||||
ns2=10.53.0.2 # test server
|
ns2=10.53.0.2 # test server
|
||||||
@ -90,22 +89,16 @@ digcmd () {
|
|||||||
|
|
||||||
|
|
||||||
# $1=number of tests $2=target domain $3=dig options
|
# $1=number of tests $2=target domain $3=dig options
|
||||||
CNT=1
|
QNUM=1
|
||||||
burst () {
|
burst () {
|
||||||
BURST_LIMIT=$1; shift
|
BURST_LIMIT=$1; shift
|
||||||
BURST_DOM_BASE="$1"; shift
|
BURST_DOM_BASE="$1"; shift
|
||||||
while test "$BURST_LIMIT" -ge 1; do
|
while test "$BURST_LIMIT" -ge 1; do
|
||||||
if test $CNT -lt 10; then
|
CNT=`expr "00$QNUM" : '.*\(...\)'`
|
||||||
CNT="00$CNT"
|
|
||||||
else
|
|
||||||
if test $CNT -lt 100; then
|
|
||||||
CNT="0$CNT"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
eval BURST_DOM="$BURST_DOM_BASE"
|
eval BURST_DOM="$BURST_DOM_BASE"
|
||||||
FILE="dig.out-$BURST_DOM-$CNT"
|
FILE="dig.out-$BURST_DOM-$CNT"
|
||||||
digcmd $FILE $BURST_DOM $* &
|
digcmd $FILE $BURST_DOM $* &
|
||||||
CNT=`expr $CNT + 1`
|
QNUM=`expr $QNUM + 1`
|
||||||
BURST_LIMIT=`expr "$BURST_LIMIT" - 1`
|
BURST_LIMIT=`expr "$BURST_LIMIT" - 1`
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
@ -116,29 +109,32 @@ burst () {
|
|||||||
ck_result() {
|
ck_result() {
|
||||||
BAD=
|
BAD=
|
||||||
wait
|
wait
|
||||||
ADDRS=`ls dig.out-$1-*=$2 2>/dev/null | wc -l | tr -d ' '`
|
ADDRS=`ls dig.out-$1-*=$2 2>/dev/null | wc -l`
|
||||||
TC=`ls dig.out-$1-*=TC 2>/dev/null | wc -l | tr -d ' '`
|
# count simple truncated and truncated NXDOMAIN as TC
|
||||||
DROP=`ls dig.out-$1-*=drop 2>/dev/null | wc -l | tr -d ' '`
|
TC=`ls dig.out-$1-*=TC dig.out-$1-*=NXDOMAINTC 2>/dev/null | wc -l`
|
||||||
NXDOMAIN=`ls dig.out-$1-*=NXDOMAIN 2>/dev/null | wc -l | tr -d ' '`
|
DROP=`ls dig.out-$1-*=drop 2>/dev/null | wc -l`
|
||||||
SERVFAIL=`ls dig.out-$1-*=SERVFAIL 2>/dev/null | wc -l | tr -d ' '`
|
# count NXDOMAIN and truncated NXDOMAIN as NXDOMAIN
|
||||||
|
NXDOMAIN=`ls dig.out-$1-*=NXDOMAIN dig.out-$1-*=NXDOMAINTC 2>/dev/null \
|
||||||
|
| wc -l`
|
||||||
|
SERVFAIL=`ls dig.out-$1-*=SERVFAIL 2>/dev/null | wc -l`
|
||||||
if test $ADDRS -ne "$3"; then
|
if test $ADDRS -ne "$3"; then
|
||||||
setret "I:$ADDRS instead of $3 '$2' responses for $1"
|
setret "I:"$ADDRS" instead of $3 '$2' responses for $1"
|
||||||
BAD=yes
|
BAD=yes
|
||||||
fi
|
fi
|
||||||
if test $TC -ne "$4"; then
|
if test $TC -ne "$4"; then
|
||||||
setret "I:$TC instead of $4 truncation responses for $1"
|
setret "I:"$TC" instead of $4 truncation responses for $1"
|
||||||
BAD=yes
|
BAD=yes
|
||||||
fi
|
fi
|
||||||
if test $DROP -ne "$5"; then
|
if test $DROP -ne "$5"; then
|
||||||
setret "I:$DROP instead of $5 dropped responses for $1"
|
setret "I:"$DROP" instead of $5 dropped responses for $1"
|
||||||
BAD=yes
|
BAD=yes
|
||||||
fi
|
fi
|
||||||
if test $NXDOMAIN -ne "$6"; then
|
if test $NXDOMAIN -ne "$6"; then
|
||||||
setret "I:$NXDOMAIN instead of $6 NXDOMAIN responses for $1"
|
setret "I:"$NXDOMAIN" instead of $6 NXDOMAIN responses for $1"
|
||||||
BAD=yes
|
BAD=yes
|
||||||
fi
|
fi
|
||||||
if test $SERVFAIL -ne "$7"; then
|
if test $SERVFAIL -ne "$7"; then
|
||||||
setret "I:$SERVFAIL instead of $7 error responses for $1"
|
setret "I:"$SERVFAIL" instead of $7 error responses for $1"
|
||||||
BAD=yes
|
BAD=yes
|
||||||
fi
|
fi
|
||||||
if test -z "$BAD"; then
|
if test -z "$BAD"; then
|
||||||
@ -151,11 +147,11 @@ ckstats () {
|
|||||||
LABEL="$1"; shift
|
LABEL="$1"; shift
|
||||||
TYPE="$1"; shift
|
TYPE="$1"; shift
|
||||||
EXPECTED="$1"; shift
|
EXPECTED="$1"; shift
|
||||||
CNT=`sed -n -e "s/[ ]*\([0-9]*\).responses $TYPE for rate limits.*/\1/p" \
|
C=`sed -n -e "s/[ ]*\([0-9]*\).responses $TYPE for rate limits.*/\1/p" \
|
||||||
ns2/named.stats | tail -1`
|
ns2/named.stats | tail -1`
|
||||||
CNT=`expr 0$CNT + 0`
|
C=`expr 0$C + 0`
|
||||||
if test "$CNT" -ne $EXPECTED; then
|
if test "$C" -ne $EXPECTED; then
|
||||||
setret "I:wrong $LABEL $TYPE statistics of $CNT instead of $EXPECTED"
|
setret "I:wrong $LABEL $TYPE statistics of $C instead of $EXPECTED"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +166,7 @@ burst 5 a1.tld3 +norec
|
|||||||
burst 3 a1.tld2
|
burst 3 a1.tld2
|
||||||
# 1 second delay allows an additional response.
|
# 1 second delay allows an additional response.
|
||||||
sleep 1
|
sleep 1
|
||||||
burst 21 a1.tld2
|
burst 10 a1.tld2
|
||||||
# Request 30 different qnames to try a wildcard.
|
# Request 30 different qnames to try a wildcard.
|
||||||
burst 30 'x$CNT.a2.tld2'
|
burst 30 'x$CNT.a2.tld2'
|
||||||
# These should be counted and limited but are not. See RT33138.
|
# These should be counted and limited but are not. See RT33138.
|
||||||
@ -179,8 +175,8 @@ burst 10 'y.x$CNT.a2.tld2'
|
|||||||
# IP TC drop NXDOMAIN SERVFAIL
|
# IP TC drop NXDOMAIN SERVFAIL
|
||||||
# referrals to "."
|
# referrals to "."
|
||||||
ck_result a1.tld3 '' 2 1 2 0 0
|
ck_result a1.tld3 '' 2 1 2 0 0
|
||||||
# check 24 results including 1 second delay that allows an additional response
|
# check 13 results including 1 second delay that allows an additional response
|
||||||
ck_result a1.tld2 192.0.2.1 3 7 14 0 0
|
ck_result a1.tld2 192.0.2.1 3 4 6 0 0
|
||||||
|
|
||||||
# Check the wild card answers.
|
# Check the wild card answers.
|
||||||
# The parent name of the 30 requests is counted.
|
# The parent name of the 30 requests is counted.
|
||||||
@ -192,64 +188,68 @@ ck_result 'y.x*.a2.tld2' 192.0.2.2 10 0 0 0 0
|
|||||||
#########
|
#########
|
||||||
sec_start
|
sec_start
|
||||||
|
|
||||||
burst 1 'y$CNT.a3.tld3'; wait; burst 20 'y$CNT.a3.tld3'
|
burst 10 'x.a3.tld3'
|
||||||
burst 20 'z$CNT.a4.tld2'
|
burst 10 'y$CNT.a3.tld3'
|
||||||
|
burst 10 'z$CNT.a4.tld2'
|
||||||
|
|
||||||
# Recursion.
|
# 10 identical recursive responses are limited
|
||||||
# The first answer is counted separately because it is counted against
|
ck_result 'x.a3.tld3' 192.0.3.3 2 3 5 0 0
|
||||||
# the rate limit on recursing to the server for a3.tld3. The remaining 20
|
|
||||||
# are counted as local responses from the cache.
|
|
||||||
ck_result 'y*.a3.tld3' 192.0.3.3 3 6 12 0 0
|
|
||||||
|
|
||||||
# NXDOMAIN responses are also limited based on the parent name.
|
# 10 different recursive responses are not limited
|
||||||
ck_result 'z*.a4.tld2' x 0 6 12 2 0
|
ck_result 'y*.a3.tld3' 192.0.3.3 10 0 0 0 0
|
||||||
|
|
||||||
|
# 10 different NXDOMAIN responses are limited based on the parent name.
|
||||||
|
# We count 13 responses because we count truncated NXDOMAIN responses
|
||||||
|
# as both truncated and NXDOMAIN.
|
||||||
|
ck_result 'z*.a4.tld2' x 0 3 5 5 0
|
||||||
|
|
||||||
$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p 9953 -s $ns2 stats
|
$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p 9953 -s $ns2 stats
|
||||||
ckstats first dropped 58
|
ckstats first dropped 36
|
||||||
ckstats first truncated 30
|
ckstats first truncated 21
|
||||||
|
|
||||||
|
|
||||||
#########
|
#########
|
||||||
sec_start
|
sec_start
|
||||||
|
|
||||||
burst 20 a5.tld2 +tcp
|
burst 10 a5.tld2 +tcp
|
||||||
burst 20 a6.tld2 -b $ns7
|
burst 10 a6.tld2 -b $ns7
|
||||||
burst 20 a7.tld4
|
burst 10 a7.tld4
|
||||||
burst 2 a8.tld2 AAAA
|
burst 2 a8.tld2 AAAA
|
||||||
burst 2 a8.tld2 TXT
|
burst 2 a8.tld2 TXT
|
||||||
burst 2 a8.tld2 SPF
|
burst 2 a8.tld2 SPF
|
||||||
|
|
||||||
|
# IP TC drop NXDOMAIN SERVFAIL
|
||||||
# TCP responses are not rate limited
|
# TCP responses are not rate limited
|
||||||
ck_result a5.tld2 192.0.2.5 20 0 0 0 0
|
ck_result a5.tld2 192.0.2.5 10 0 0 0 0
|
||||||
|
|
||||||
# whitelisted client is not rate limited
|
# whitelisted client is not rate limited
|
||||||
ck_result a6.tld2 192.0.2.6 20 0 0 0 0
|
ck_result a6.tld2 192.0.2.6 10 0 0 0 0
|
||||||
|
|
||||||
# Errors such as SERVFAIL are rate limited. The numbers are confusing, because
|
# Errors such as SERVFAIL are rate limited.
|
||||||
# other rate limiting can be triggered before the SERVFAIL limit is reached.
|
ck_result a7.tld4 x 0 0 8 0 2
|
||||||
ck_result a7.tld4 192.0.2.1 0 6 12 0 2
|
|
||||||
|
|
||||||
# NODATA responses are counted as the same regardless of qtype.
|
# NODATA responses are counted as the same regardless of qtype.
|
||||||
ck_result a8.tld2 '' 2 2 2 0 0
|
ck_result a8.tld2 '' 2 2 2 0 0
|
||||||
|
|
||||||
$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p 9953 -s $ns2 stats
|
$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p 9953 -s $ns2 stats
|
||||||
ckstats second dropped 72
|
ckstats second dropped 46
|
||||||
ckstats second truncated 38
|
ckstats second truncated 23
|
||||||
|
|
||||||
|
|
||||||
#########
|
#########
|
||||||
sec_start
|
sec_start
|
||||||
|
|
||||||
|
# IP TC drop NXDOMAIN SERVFAIL
|
||||||
# all-per-second
|
# all-per-second
|
||||||
# The qnames are all unique but the client IP address is constant.
|
# The qnames are all unique but the client IP address is constant.
|
||||||
CNT=101
|
QNUM=101
|
||||||
burst 80 'all$CNT.a9.tld2'
|
burst 60 'all$CNT.a9.tld2'
|
||||||
|
|
||||||
ck_result 'a*.a9.tld2' 192.0.2.8 70 0 10 0 0
|
ck_result 'a*.a9.tld2' 192.0.2.8 50 0 10 0 0
|
||||||
|
|
||||||
$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p 9953 -s $ns2 stats
|
$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p 9953 -s $ns2 stats
|
||||||
ckstats final dropped 82
|
ckstats final dropped 56
|
||||||
ckstats final truncated 38
|
ckstats final truncated 23
|
||||||
|
|
||||||
|
|
||||||
echo "I:exit status: $ret"
|
echo "I:exit status: $ret"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user