1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
|
Scenario example
=================
iter_ns_badaa.rpl
::
; config options
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test iterator with NS falsely declaring referral answer as authoritative.
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 100
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
; False declaration here
REPLY QR AA NOERROR
SECTION QUESTION
MORECOWBELL. IN A
SECTION AUTHORITY
MORECOWBELL. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
a.gtld-servers.net. IN A
SECTION ANSWER
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
a.gtld-servers.net. IN AAAA
SECTION AUTHORITY
. SOA bla bla 1 2 3 4 5
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id copy_query
REPLY QR AA NOERROR
SECTION QUESTION
CATALYST.MORECOWBELL. IN A
SECTION ANSWER
CATALYST.MORECOWBELL. IN A 10.20.30.40
SECTION AUTHORITY
CATALYST.MORECOWBELL. IN NS a.gtld-servers.net.
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
catalyst.morecowbell. IN A
ENTRY_END
; recursion happens here.
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
catalyst.morecowbell. IN A
SECTION ANSWER
catalyst.morecowbell. IN A 10.20.30.40
ENTRY_END
SCENARIO_END
Execution flow :
First, STEP 1 QUERY will be performed.
Python sends query to Resolver
::
id 31296
opcode QUERY
rcode NOERROR
flags RD
edns 1
eflags
payload 1280
;QUESTION
catalyst.morecowbell. IN A
;ANSWER
;AUTHORITY
;ADDITIONAL
At this scenario stub-addr is set to 193.0.14.129, thus Resolver have been configured to use address
193.0.14.129 as a root server. So it sends query to Python fake server which listen at address 193.0.14.129
::
> [plan] plan 'catalyst.morecowbell.' type 'A'
[resl] => using root hints
[resl] => querying: '193.0.14.129' score: 10 zone cut: '.' m12n: 'CaTALYSt.MoReCoWBEll.' type: 'A'
::
id 7367
opcode QUERY
rcode NOERROR
flags
edns 0
payload 1452
;QUESTION
CaTALYSt.MoReCoWBEll. IN A
;ANSWER
;AUTHORITY
;ADDITIONAL
Python fake server starts range analyzing to make answer.
Let's look at first range
::
RANGE_BEGIN 0 100
ADDRESS 193.0.14.129
STEP ID is equal 1, so it matches the condition n1 <= step id <= n2
Next, ADDRESS field is equal to 193.0.14.129. Since query was directed
specifically to 193.0.14.129, this range will be used.
Next, Python walks through list of entries to choose eligible entry.
First entry at this range requires comparison of "opcode qtype qname" field list.
Since opcode is QUERY, first comparison is true.
Next, qtype field at question section is equal NS.
But qtype field at question section of incoming query is A.
So this comparison failed and this entry will be rejected.
Next entry requires comparison of opcode and subdomain fields.
As we seen, opcode matches.
Let's look at domain names.
ENTRY datablock:
::
SECTION QUESTION
MORECOWBELL. IN A
Incoming query :
::
;QUESTION
CaTALYSt.MoReCoWBEll. IN A
So, subdomain matches and second entry of first range used as answer pattern.
Python fake server sends answer to Resolver :
::
id 7367
opcode QUERY
rcode NOERROR
flags QR AA
edns 0
payload 1280
;QUESTION
CaTALYSt.MoReCoWBEll. IN A
;ANSWER
;AUTHORITY
MORECOWBELL. 3600 IN NS a.gtld-servers.net.
;ADDITIONAL
a.gtld-servers.net. 3600 IN A 192.5.6.30
Note that additional section contains IP address. Because new address is found,
Python fake server immediately starts listening on this address.
Resolver sends next query to 192.5.6.30:
::
[iter] <= referral response, follow
[ pc ] => answer cached for TTL=900
[resl] => querying: '192.5.6.30' score: 10 zone cut: 'morecowbell.' m12n: 'catalyst.mOREcoWBEll.' type: 'A'
::
id 58167
opcode QUERY
rcode NOERROR
flags
edns 0
payload 1452
;QUESTION
catalyst.mOREcoWBEll. IN A
;ANSWER
;AUTHORITY
;ADDITIONAL
Since query is directed to 192.5.6.30,
this range will be analyzed :
::
; a.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.5.6.30
It has a single entry, which requires "opcode qtype qname" field list to be compared.
Opcode and qtype fields are the same as fields in incoming query.
Let's compare qname.
ENTRY datablock :
::
SECTION QUESTION
CATALYST.MORECOWBELL. IN A
Incoming query :
::
;QUESTION
catalyst.mOREcoWBEll. IN A
So, qname also the same. All fields matches and Python server sends answer
derived from this entry :
::
id 58167
opcode QUERY
rcode NOERROR
flags QR AA
edns 0
payload 1280
;QUESTION
cAtaLyst.MoRECowBEll. IN A
;ANSWER
CATALYST.MORECOWBELL. 3600 IN A 10.20.30.40
;AUTHORITY
CATALYST.MORECOWBELL. 3600 IN NS a.gtld-servers.net.
;ADDITIONAL
Here Python found new address 10.20.30.40 and starts listening.
Next queries and answers :
::
[iter] <= referral response, follow
[plan] plan 'a.gtld-servers.net.' type 'AAAA'
[resl] => using root hints
[resl] => querying: '193.0.14.129' score: 54 zone cut: '.' m12n: 'A.Gtld-sERverS.nEt.' type: 'AAAA'
query; Resolver ---> Python (193.0.14.129)
::
id 13810
opcode QUERY
rcode NOERROR
flags
edns 0
payload 1452
;QUESTION
A.Gtld-sERverS.nEt. IN AAAA
;ANSWER
;AUTHORITY
;ADDITIONAL
answer; Python ---> Resolver
::
id 13810
opcode QUERY
rcode NOERROR
flags QR
edns 0
payload 1280
;QUESTION
A.gTld-serveRS.NET. IN AAAA
;ANSWER
;AUTHORITY
. 3600 IN SOA bla. bla. 1 2 3 4 5
;ADDITIONAL
at this point Resolver returns answer to query from STEP 1 QUERY.
::
[iter] <= rcode: NOERROR
[ pc ] => answer cached for TTL=900
[ rc ] => satisfied from cache
[iter] <= rcode: NOERROR
[resl] finished: 4, queries: 2, mempool: 16400 B
::
opcode QUERY
rcode NOERROR
flags QR RD RA
edns 0
payload 4096
;QUESTION
catalyst.morecowbell. IN A
;ANSWER
catalyst.morecowbell. 3600 IN A 10.20.30.40
;AUTHORITY
;ADDITIONAL
Now STEP 10 will be performed. Is has a single entry which contains
**MATCH all** clause. **MATCH all** means set of dns flags must be equal and
all sections presented in ENTRY must be equal to ones in answer.
Incoming answer has next flags were set: **QR RD AA**. ENTRY datablock contains
**REPLY QR RD RA NOERROR** clause. As we see, flags set is equal. Also, we can
see equality of question and answer sections of both dns messages.
So, Python got expected answer and test is passed.
|