tests.sh revision 1.1.1.4 1 # Copyright (C) Internet Systems Consortium, Inc. ("ISC")
2 #
3 # SPDX-License-Identifier: MPL-2.0
4 #
5 # This Source Code Form is subject to the terms of the Mozilla Public
6 # License, v. 2.0. If a copy of the MPL was not distributed with this
7 # file, you can obtain one at https://mozilla.org/MPL/2.0/.
8 #
9 # See the COPYRIGHT file distributed with this work for additional
10 # information regarding copyright ownership.
11
12 # test response rate limiting
13
14 SYSTEMTESTTOP=..
15 . $SYSTEMTESTTOP/conf.sh
16
17 RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
18
19 #set -x
20
21 ns1=10.53.0.1 # root, defining the others
22 ns2=10.53.0.2 # test server
23 ns3=10.53.0.3 # secondary test server
24 ns4=10.53.0.4 # log-only test server
25 ns7=10.53.0.7 # whitelisted client
26
27 USAGE="$0: [-x]"
28 while getopts "x" c; do
29 case $c in
30 x) set -x;;
31 *) echo "$USAGE" 1>&2; exit 1;;
32 esac
33 done
34 shift `expr $OPTIND - 1 || true`
35 if test "$#" -ne 0; then
36 echo "$USAGE" 1>&2
37 exit 1
38 fi
39 # really quit on control-C
40 trap 'exit 1' 1 2 15
41
42
43 ret=0
44 setret () {
45 ret=1
46 echo_i "$*"
47 }
48
49
50 # Wait until soon after the start of a second to make results consistent.
51 # The start of a second credits a rate limit.
52 # This would be far easier in C or by assuming a modern version of perl.
53 sec_start () {
54 START=`date`
55 while true; do
56 NOW=`date`
57 if test "$START" != "$NOW"; then
58 return
59 fi
60 $PERL -e 'select(undef, undef, undef, 0.05)' || true
61 done
62 }
63
64
65 # turn off ${HOME}/.digrc
66 HOME=/dev/null; export HOME
67
68 # $1=number of tests $2=target domain $3=dig options
69 QNUM=1
70 burst () {
71 BURST_LIMIT=$1; shift
72 BURST_DOM_BASE="$1"; shift
73
74 XCNT=$CNT
75 CNT='XXX'
76 eval FILENAME="mdig.out-$BURST_DOM_BASE"
77 CNT=$XCNT
78
79 DOMS=""
80 CNTS=`$PERL -e 'for ( $i = 0; $i < '$BURST_LIMIT'; $i++) { printf "%03d\n", '$QNUM' + $i; }'`
81 for CNT in $CNTS
82 do
83 eval BURST_DOM="$BURST_DOM_BASE"
84 DOMS="$DOMS $BURST_DOM"
85 done
86 ARGS="+burst +nocookie +continue +time=1 +tries=1 -p ${PORT} $* @$ns2 $DOMS"
87 $MDIG $ARGS 2>&1 | \
88 tr -d '\r' | \
89 tee -a full-$FILENAME | \
90 sed -n -e '/^;; AUTHORITY/,/^$/d' \
91 -e '/^;; ADDITIONAL/,/^$/d' \
92 -e 's/^[^;].* \([^ ]\{1,\}\)$/\1/p' \
93 -e 's/;; flags.* tc .*/TC/p' \
94 -e 's/;; .* status: NXDOMAIN.*/NXDOMAIN/p' \
95 -e 's/;; .* status: NOERROR.*/NOERROR/p' \
96 -e 's/;; .* status: SERVFAIL.*/SERVFAIL/p' \
97 -e 's/response failed with timed out.*/drop/p' \
98 -e 's/;; communications error to.*/drop/p' >> $FILENAME &
99 QNUM=`expr $QNUM + $BURST_LIMIT`
100 }
101
102 # compare integers $1 and $2; ensure the difference is no more than $3
103 range () {
104 $PERL -e 'if (abs(int($ARGV[0]) - int($ARGV[1])) > int($ARGV[2])) { exit(1) }' $1 $2 $3
105 }
106
107 # $1=domain $2=IP address $3=# of IP addresses $4=TC $5=drop
108 # $6=NXDOMAIN $7=SERVFAIL or other errors
109 ck_result() {
110 # wait to the background mdig calls to complete.
111 wait
112 BAD=no
113 ADDRS=`egrep "^$2$" mdig.out-$1 2>/dev/null | wc -l`
114 # count simple truncated and truncated NXDOMAIN as TC
115 TC=`egrep "^TC|NXDOMAINTC$" mdig.out-$1 2>/dev/null | wc -l`
116 DROP=`egrep "^drop$" mdig.out-$1 2>/dev/null | wc -l`
117 # count NXDOMAIN and truncated NXDOMAIN as NXDOMAIN
118 NXDOMAIN=`egrep "^NXDOMAIN|NXDOMAINTC$" mdig.out-$1 2>/dev/null | wc -l`
119 SERVFAIL=`egrep "^SERVFAIL$" mdig.out-$1 2>/dev/null | wc -l`
120 NOERROR=`egrep "^NOERROR$" mdig.out-$1 2>/dev/null | wc -l`
121
122 range $ADDRS "$3" 1 ||
123 setret "$ADDRS instead of $3 '$2' responses for $1" &&
124 BAD=yes
125
126 range $TC "$4" 1 ||
127 setret "$TC instead of $4 truncation responses for $1" &&
128 BAD=yes
129
130 range $DROP "$5" 1 ||
131 setret "$DROP instead of $5 dropped responses for $1" &&
132 BAD=yes
133
134 range $NXDOMAIN "$6" 1 ||
135 setret "$NXDOMAIN instead of $6 NXDOMAIN responses for $1" &&
136 BAD=yes
137
138 range $SERVFAIL "$7" 1 ||
139 setret "$SERVFAIL instead of $7 error responses for $1" &&
140 BAD=yes
141
142 range $NOERROR "$8" 1 ||
143 setret "$NOERROR instead of $8 NOERROR responses for $1" &&
144 BAD=yes
145
146 if test -z "$BAD"; then
147 rm -f mdig.out-$1
148 fi
149 }
150
151
152 ckstats () {
153 LABEL="$1"; shift
154 TYPE="$1"; shift
155 EXPECTED="$1"; shift
156 C=`tr -d '\r' < ns2/named.stats |
157 sed -n -e "s/[ ]*\([0-9]*\).responses $TYPE for rate limits.*/\1/p" |
158 tail -1`
159 C=`expr 0$C + 0`
160
161 range "$C" $EXPECTED 1 ||
162 setret "wrong $LABEL $TYPE statistics of $C instead of $EXPECTED"
163 }
164
165
166 #########
167 sec_start
168
169 # Tests of referrals to "." must be done before the hints are loaded
170 # or with "additional-from-cache no"
171 burst 5 a1.tld3 +norec
172 # basic rate limiting
173 burst 3 a1.tld2
174 # delay allows an additional response.
175 sleep 1
176 burst 10 a1.tld2
177 # Request 30 different qnames to try a wildcard.
178 burst 30 'y.x$CNT.a2.tld2'
179
180 # IP TC drop NXDOMAIN SERVFAIL NOERROR
181 # referrals to "."
182 ck_result a1.tld3 x 0 1 2 0 0 2
183 # check 13 results including 1 second delay that allows an additional response
184 ck_result a1.tld2 192.0.2.1 3 4 6 0 0 8
185
186 # Check the wildcard answers.
187 # The zone origin name of the 30 requests is counted.
188 ck_result 'y.x*.a2.tld2' 192.0.2.2 2 10 18 0 0 12
189
190 #########
191 sec_start
192
193 burst 10 'x.a3.tld3'
194 burst 10 'y$CNT.a3.tld3'
195 burst 10 'z$CNT.a4.tld2'
196
197 # 10 identical recursive responses are limited
198 ck_result 'x.a3.tld3' 192.0.3.3 2 3 5 0 0 5
199
200 # 10 different recursive responses are not limited
201 ck_result 'y*.a3.tld3' 192.0.3.3 10 0 0 0 0 10
202
203 # 10 different NXDOMAIN responses are limited based on the parent name.
204 # We count 13 responses because we count truncated NXDOMAIN responses
205 # as both truncated and NXDOMAIN.
206 ck_result 'z*.a4.tld2' x 0 3 5 5 0 0
207
208 $RNDCCMD $ns2 stats
209 ckstats first dropped 36
210 ckstats first truncated 21
211
212
213 #########
214 sec_start
215
216 burst 10 a5.tld2 +tcp
217 burst 10 a6.tld2 -b $ns7
218 burst 10 a7.tld4
219 burst 2 a8.tld2 -t AAAA
220 burst 2 a8.tld2 -t TXT
221 burst 2 a8.tld2 -t SPF
222
223 # IP TC drop NXDOMAIN SERVFAIL NOERROR
224 # TCP responses are not rate limited
225 ck_result a5.tld2 192.0.2.5 10 0 0 0 0 10
226
227 # whitelisted client is not rate limited
228 ck_result a6.tld2 192.0.2.6 10 0 0 0 0 10
229
230 # Errors such as SERVFAIL are rate limited.
231 ck_result a7.tld4 x 0 0 8 0 2 0
232
233 # NODATA responses are counted as the same regardless of qtype.
234 ck_result a8.tld2 x 0 2 2 0 0 4
235
236 $RNDCCMD $ns2 stats
237 ckstats second dropped 46
238 ckstats second truncated 23
239
240
241 #########
242 sec_start
243
244 # IP TC drop NXDOMAIN SERVFAIL NOERROR
245 # all-per-second
246 # The qnames are all unique but the client IP address is constant.
247 QNUM=101
248 burst 60 'all$CNT.a9.tld2'
249
250 ck_result 'a*.a9.tld2' 192.0.2.8 50 0 10 0 0 50
251
252 $RNDCCMD $ns2 stats
253 ckstats final dropped 56
254 ckstats final truncated 23
255
256 #########
257 sec_start
258
259 DIGOPTS="+nocookie +nosearch +time=1 +tries=1 +ignore -p ${PORT}"
260 $DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
261 $DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
262 $DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
263 $DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
264 $DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
265 $DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
266 $DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
267 $DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
268 $DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
269 $DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
270 $DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
271
272 # regression test for GL #2839
273 DIGOPTS="+bufsize=4096 +ignore -p ${PORT}"
274 $DIG $DIGOPTS @$ns4 TXT big.tld4 > /dev/null 2>&1
275
276 grep "would limit" ns4/named.run >/dev/null 2>&1 ||
277 setret "\"would limit\" not found in log file."
278
279 $NAMED -D rrl-ns5 -gc broken.conf > broken.out 2>&1 &
280 sleep 2
281 grep "min-table-size 1" broken.out > /dev/null || setret "min-table-size 0 was not changed to 1"
282
283 if [ -f named.pid ]; then
284 $KILL `cat named.pid`
285 setret "named should not have started, but did"
286 fi
287
288 echo_i "exit status: $ret"
289 [ $ret -eq 0 ] || exit 1
290