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