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