]>
Commit | Line | Data |
---|---|---|
ec5f5c6b RG |
1 | #!/usr/bin/env python |
2 | from datetime import datetime, timedelta | |
ec5f5c6b | 3 | import os |
856c35e3 | 4 | import time |
b1bec9f0 | 5 | import dns |
ec5f5c6b RG |
6 | from dnsdisttests import DNSDistTest |
7 | ||
b1bec9f0 RG |
8 | class TestAdvancedAllow(DNSDistTest): |
9 | ||
10 | _config_template = """ | |
11 | addAction(makeRule("allowed.advanced.tests.powerdns.com."), AllowAction()) | |
12 | addAction(AllRule(), DropAction()) | |
13 | newServer{address="127.0.0.1:%s"} | |
14 | """ | |
15 | ||
16 | def testAdvancedAllow(self): | |
17 | """ | |
18 | Advanced: Allowed qname is not dropped | |
19 | ||
20 | A query for allowed.advanced.tests.powerdns.com. should be allowed | |
21 | while others should be dropped. | |
22 | """ | |
23 | name = 'allowed.advanced.tests.powerdns.com.' | |
24 | query = dns.message.make_query(name, 'A', 'IN') | |
25 | response = dns.message.make_response(query) | |
26 | rrset = dns.rrset.from_text(name, | |
27 | 3600, | |
28 | dns.rdataclass.IN, | |
29 | dns.rdatatype.A, | |
30 | '127.0.0.1') | |
31 | response.answer.append(rrset) | |
32 | ||
33 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
34 | self.assertTrue(receivedQuery) | |
35 | self.assertTrue(receivedResponse) | |
36 | receivedQuery.id = query.id | |
37 | self.assertEquals(query, receivedQuery) | |
38 | self.assertEquals(response, receivedResponse) | |
39 | ||
40 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
41 | self.assertTrue(receivedQuery) | |
42 | self.assertTrue(receivedResponse) | |
43 | receivedQuery.id = query.id | |
44 | self.assertEquals(query, receivedQuery) | |
45 | self.assertEquals(response, receivedResponse) | |
46 | ||
47 | def testAdvancedAllowDropped(self): | |
48 | """ | |
49 | Advanced: Not allowed qname is dropped | |
50 | ||
51 | A query for notallowed.advanced.tests.powerdns.com. should be dropped. | |
52 | """ | |
53 | name = 'notallowed.advanced.tests.powerdns.com.' | |
54 | query = dns.message.make_query(name, 'A', 'IN') | |
55 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
56 | self.assertEquals(receivedResponse, None) | |
57 | ||
58 | (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False) | |
59 | self.assertEquals(receivedResponse, None) | |
60 | ||
ec5f5c6b RG |
61 | class TestAdvancedFixupCase(DNSDistTest): |
62 | ||
ec5f5c6b RG |
63 | _config_template = """ |
64 | truncateTC(true) | |
65 | fixupCase(true) | |
66 | newServer{address="127.0.0.1:%s"} | |
67 | """ | |
68 | ||
ec5f5c6b RG |
69 | def testAdvancedFixupCase(self): |
70 | """ | |
617dfe22 RG |
71 | Advanced: Fixup Case |
72 | ||
ec5f5c6b RG |
73 | Send a query with lower and upper chars, |
74 | make the backend return a lowercase version, | |
75 | check that dnsdist fixes the response. | |
76 | """ | |
77 | name = 'fiXuPCasE.advanced.tests.powerdns.com.' | |
78 | query = dns.message.make_query(name, 'A', 'IN') | |
79 | lowercasequery = dns.message.make_query(name.lower(), 'A', 'IN') | |
80 | response = dns.message.make_response(lowercasequery) | |
81 | expectedResponse = dns.message.make_response(query) | |
82 | rrset = dns.rrset.from_text(name, | |
83 | 3600, | |
84 | dns.rdataclass.IN, | |
85 | dns.rdatatype.A, | |
86 | '127.0.0.1') | |
87 | response.answer.append(rrset) | |
88 | expectedResponse.answer.append(rrset) | |
89 | ||
90 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
91 | self.assertTrue(receivedQuery) | |
92 | self.assertTrue(receivedResponse) | |
93 | receivedQuery.id = query.id | |
ec5f5c6b RG |
94 | self.assertEquals(query, receivedQuery) |
95 | self.assertEquals(expectedResponse, receivedResponse) | |
96 | ||
97 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
98 | self.assertTrue(receivedQuery) | |
99 | self.assertTrue(receivedResponse) | |
100 | receivedQuery.id = query.id | |
ec5f5c6b RG |
101 | self.assertEquals(query, receivedQuery) |
102 | self.assertEquals(expectedResponse, receivedResponse) | |
103 | ||
104 | ||
105 | class TestAdvancedRemoveRD(DNSDistTest): | |
106 | ||
ec5f5c6b RG |
107 | _config_template = """ |
108 | addNoRecurseRule("norecurse.advanced.tests.powerdns.com.") | |
109 | newServer{address="127.0.0.1:%s"} | |
110 | """ | |
111 | ||
ec5f5c6b RG |
112 | def testAdvancedNoRD(self): |
113 | """ | |
617dfe22 RG |
114 | Advanced: No RD |
115 | ||
ec5f5c6b RG |
116 | Send a query with RD, |
117 | check that dnsdist clears the RD flag. | |
118 | """ | |
119 | name = 'norecurse.advanced.tests.powerdns.com.' | |
120 | query = dns.message.make_query(name, 'A', 'IN') | |
121 | expectedQuery = dns.message.make_query(name, 'A', 'IN') | |
122 | expectedQuery.flags &= ~dns.flags.RD | |
123 | ||
124 | response = dns.message.make_response(query) | |
125 | rrset = dns.rrset.from_text(name, | |
126 | 3600, | |
127 | dns.rdataclass.IN, | |
128 | dns.rdatatype.A, | |
129 | '127.0.0.1') | |
130 | response.answer.append(rrset) | |
131 | ||
132 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
133 | self.assertTrue(receivedQuery) | |
134 | self.assertTrue(receivedResponse) | |
135 | receivedQuery.id = expectedQuery.id | |
ec5f5c6b RG |
136 | self.assertEquals(expectedQuery, receivedQuery) |
137 | self.assertEquals(response, receivedResponse) | |
138 | ||
139 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
140 | self.assertTrue(receivedQuery) | |
141 | self.assertTrue(receivedResponse) | |
142 | receivedQuery.id = expectedQuery.id | |
ec5f5c6b RG |
143 | self.assertEquals(expectedQuery, receivedQuery) |
144 | self.assertEquals(response, receivedResponse) | |
145 | ||
146 | def testAdvancedKeepRD(self): | |
147 | """ | |
617dfe22 RG |
148 | Advanced: No RD canary |
149 | ||
ec5f5c6b RG |
150 | Send a query with RD for a canary domain, |
151 | check that dnsdist does not clear the RD flag. | |
152 | """ | |
153 | name = 'keeprecurse.advanced.tests.powerdns.com.' | |
154 | query = dns.message.make_query(name, 'A', 'IN') | |
155 | ||
156 | response = dns.message.make_response(query) | |
157 | rrset = dns.rrset.from_text(name, | |
158 | 3600, | |
159 | dns.rdataclass.IN, | |
160 | dns.rdatatype.A, | |
161 | '127.0.0.1') | |
162 | response.answer.append(rrset) | |
163 | ||
164 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
165 | self.assertTrue(receivedQuery) | |
166 | self.assertTrue(receivedResponse) | |
167 | receivedQuery.id = query.id | |
ec5f5c6b RG |
168 | self.assertEquals(query, receivedQuery) |
169 | self.assertEquals(response, receivedResponse) | |
170 | ||
171 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
172 | self.assertTrue(receivedQuery) | |
173 | self.assertTrue(receivedResponse) | |
174 | receivedQuery.id = query.id | |
ec5f5c6b RG |
175 | self.assertEquals(query, receivedQuery) |
176 | self.assertEquals(response, receivedResponse) | |
177 | ||
178 | ||
179 | class TestAdvancedAddCD(DNSDistTest): | |
180 | ||
ec5f5c6b RG |
181 | _config_template = """ |
182 | addDisableValidationRule("setcd.advanced.tests.powerdns.com.") | |
b1bec9f0 | 183 | addAction(makeRule("setcdviaaction.advanced.tests.powerdns.com."), DisableValidationAction()) |
ec5f5c6b RG |
184 | newServer{address="127.0.0.1:%s"} |
185 | """ | |
186 | ||
ec5f5c6b RG |
187 | def testAdvancedSetCD(self): |
188 | """ | |
617dfe22 RG |
189 | Advanced: Set CD |
190 | ||
ec5f5c6b RG |
191 | Send a query with CD cleared, |
192 | check that dnsdist set the CD flag. | |
193 | """ | |
194 | name = 'setcd.advanced.tests.powerdns.com.' | |
195 | query = dns.message.make_query(name, 'A', 'IN') | |
b1bec9f0 RG |
196 | expectedQuery = dns.message.make_query(name, 'A', 'IN') |
197 | expectedQuery.flags |= dns.flags.CD | |
198 | ||
199 | response = dns.message.make_response(query) | |
200 | rrset = dns.rrset.from_text(name, | |
201 | 3600, | |
202 | dns.rdataclass.IN, | |
203 | dns.rdatatype.A, | |
204 | '127.0.0.1') | |
205 | response.answer.append(rrset) | |
206 | ||
207 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
208 | self.assertTrue(receivedQuery) | |
209 | self.assertTrue(receivedResponse) | |
210 | receivedQuery.id = expectedQuery.id | |
211 | self.assertEquals(expectedQuery, receivedQuery) | |
212 | self.assertEquals(response, receivedResponse) | |
213 | ||
214 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
215 | self.assertTrue(receivedQuery) | |
216 | self.assertTrue(receivedResponse) | |
217 | receivedQuery.id = expectedQuery.id | |
218 | self.assertEquals(expectedQuery, receivedQuery) | |
219 | self.assertEquals(response, receivedResponse) | |
220 | ||
221 | def testAdvancedSetCDViaAction(self): | |
222 | """ | |
223 | Advanced: Set CD via Action | |
224 | ||
225 | Send a query with CD cleared, | |
226 | check that dnsdist set the CD flag. | |
227 | """ | |
228 | name = 'setcdviaaction.advanced.tests.powerdns.com.' | |
229 | query = dns.message.make_query(name, 'A', 'IN') | |
230 | expectedQuery = dns.message.make_query(name, 'A', 'IN') | |
ec5f5c6b RG |
231 | expectedQuery.flags |= dns.flags.CD |
232 | ||
233 | response = dns.message.make_response(query) | |
234 | rrset = dns.rrset.from_text(name, | |
235 | 3600, | |
236 | dns.rdataclass.IN, | |
237 | dns.rdatatype.A, | |
238 | '127.0.0.1') | |
239 | response.answer.append(rrset) | |
240 | ||
241 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
242 | self.assertTrue(receivedQuery) | |
243 | self.assertTrue(receivedResponse) | |
244 | receivedQuery.id = expectedQuery.id | |
ec5f5c6b RG |
245 | self.assertEquals(expectedQuery, receivedQuery) |
246 | self.assertEquals(response, receivedResponse) | |
247 | ||
248 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
249 | self.assertTrue(receivedQuery) | |
250 | self.assertTrue(receivedResponse) | |
251 | receivedQuery.id = expectedQuery.id | |
ec5f5c6b RG |
252 | self.assertEquals(expectedQuery, receivedQuery) |
253 | self.assertEquals(response, receivedResponse) | |
254 | ||
255 | def testAdvancedKeepNoCD(self): | |
256 | """ | |
617dfe22 RG |
257 | Advanced: Preserve CD canary |
258 | ||
ec5f5c6b RG |
259 | Send a query without CD for a canary domain, |
260 | check that dnsdist does not set the CD flag. | |
261 | """ | |
262 | name = 'keepnocd.advanced.tests.powerdns.com.' | |
263 | query = dns.message.make_query(name, 'A', 'IN') | |
264 | ||
265 | response = dns.message.make_response(query) | |
266 | rrset = dns.rrset.from_text(name, | |
267 | 3600, | |
268 | dns.rdataclass.IN, | |
269 | dns.rdatatype.A, | |
270 | '127.0.0.1') | |
271 | response.answer.append(rrset) | |
272 | ||
273 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
274 | self.assertTrue(receivedQuery) | |
275 | self.assertTrue(receivedResponse) | |
276 | receivedQuery.id = query.id | |
ec5f5c6b RG |
277 | self.assertEquals(query, receivedQuery) |
278 | self.assertEquals(response, receivedResponse) | |
279 | ||
280 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
281 | self.assertTrue(receivedQuery) | |
282 | self.assertTrue(receivedResponse) | |
283 | receivedQuery.id = query.id | |
ec5f5c6b RG |
284 | self.assertEquals(query, receivedQuery) |
285 | self.assertEquals(response, receivedResponse) | |
286 | ||
b1bec9f0 RG |
287 | class TestAdvancedClearRD(DNSDistTest): |
288 | ||
289 | _config_template = """ | |
290 | addNoRecurseRule("clearrd.advanced.tests.powerdns.com.") | |
291 | addAction(makeRule("clearrdviaaction.advanced.tests.powerdns.com."), NoRecurseAction()) | |
292 | newServer{address="127.0.0.1:%s"} | |
293 | """ | |
294 | ||
295 | def testAdvancedClearRD(self): | |
296 | """ | |
297 | Advanced: Clear RD | |
298 | ||
299 | Send a query with RD set, | |
300 | check that dnsdist clears the RD flag. | |
301 | """ | |
302 | name = 'clearrd.advanced.tests.powerdns.com.' | |
303 | query = dns.message.make_query(name, 'A', 'IN') | |
304 | expectedQuery = dns.message.make_query(name, 'A', 'IN') | |
305 | expectedQuery.flags &= ~dns.flags.RD | |
306 | ||
307 | response = dns.message.make_response(query) | |
308 | rrset = dns.rrset.from_text(name, | |
309 | 3600, | |
310 | dns.rdataclass.IN, | |
311 | dns.rdatatype.A, | |
312 | '127.0.0.1') | |
313 | response.answer.append(rrset) | |
314 | ||
315 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
316 | self.assertTrue(receivedQuery) | |
317 | self.assertTrue(receivedResponse) | |
318 | receivedQuery.id = expectedQuery.id | |
319 | self.assertEquals(expectedQuery, receivedQuery) | |
320 | self.assertEquals(response, receivedResponse) | |
321 | ||
322 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
323 | self.assertTrue(receivedQuery) | |
324 | self.assertTrue(receivedResponse) | |
325 | receivedQuery.id = expectedQuery.id | |
326 | self.assertEquals(expectedQuery, receivedQuery) | |
327 | self.assertEquals(response, receivedResponse) | |
328 | ||
329 | def testAdvancedClearRDViaAction(self): | |
330 | """ | |
331 | Advanced: Clear RD via Action | |
332 | ||
333 | Send a query with RD set, | |
334 | check that dnsdist clears the RD flag. | |
335 | """ | |
336 | name = 'clearrdviaaction.advanced.tests.powerdns.com.' | |
337 | query = dns.message.make_query(name, 'A', 'IN') | |
338 | expectedQuery = dns.message.make_query(name, 'A', 'IN') | |
339 | expectedQuery.flags &= ~dns.flags.RD | |
340 | ||
341 | response = dns.message.make_response(query) | |
342 | rrset = dns.rrset.from_text(name, | |
343 | 3600, | |
344 | dns.rdataclass.IN, | |
345 | dns.rdatatype.A, | |
346 | '127.0.0.1') | |
347 | response.answer.append(rrset) | |
348 | ||
349 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
350 | self.assertTrue(receivedQuery) | |
351 | self.assertTrue(receivedResponse) | |
352 | receivedQuery.id = expectedQuery.id | |
353 | self.assertEquals(expectedQuery, receivedQuery) | |
354 | self.assertEquals(response, receivedResponse) | |
355 | ||
356 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
357 | self.assertTrue(receivedQuery) | |
358 | self.assertTrue(receivedResponse) | |
359 | receivedQuery.id = expectedQuery.id | |
360 | self.assertEquals(expectedQuery, receivedQuery) | |
361 | self.assertEquals(response, receivedResponse) | |
362 | ||
363 | def testAdvancedKeepRD(self): | |
364 | """ | |
365 | Advanced: Preserve RD canary | |
366 | ||
367 | Send a query with RD for a canary domain, | |
368 | check that dnsdist does not clear the RD flag. | |
369 | """ | |
370 | name = 'keeprd.advanced.tests.powerdns.com.' | |
371 | query = dns.message.make_query(name, 'A', 'IN') | |
372 | ||
373 | response = dns.message.make_response(query) | |
374 | rrset = dns.rrset.from_text(name, | |
375 | 3600, | |
376 | dns.rdataclass.IN, | |
377 | dns.rdatatype.A, | |
378 | '127.0.0.1') | |
379 | response.answer.append(rrset) | |
380 | ||
381 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
382 | self.assertTrue(receivedQuery) | |
383 | self.assertTrue(receivedResponse) | |
384 | receivedQuery.id = query.id | |
385 | self.assertEquals(query, receivedQuery) | |
386 | self.assertEquals(response, receivedResponse) | |
387 | ||
388 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
389 | self.assertTrue(receivedQuery) | |
390 | self.assertTrue(receivedResponse) | |
391 | receivedQuery.id = query.id | |
392 | self.assertEquals(query, receivedQuery) | |
393 | self.assertEquals(response, receivedResponse) | |
394 | ||
ec5f5c6b RG |
395 | |
396 | class TestAdvancedACL(DNSDistTest): | |
397 | ||
ec5f5c6b RG |
398 | _config_template = """ |
399 | newServer{address="127.0.0.1:%s"} | |
400 | """ | |
18a0e7c6 | 401 | _acl = ['192.0.2.1/32'] |
ec5f5c6b RG |
402 | |
403 | def testACLBlocked(self): | |
404 | """ | |
617dfe22 RG |
405 | Advanced: ACL blocked |
406 | ||
ec5f5c6b RG |
407 | Send an A query to "tests.powerdns.com.", |
408 | we expect no response since 127.0.0.1 is not on the | |
409 | ACL. | |
410 | """ | |
903853f4 | 411 | name = 'tests.powerdns.com.' |
7791f83a | 412 | query = dns.message.make_query(name, 'A', 'IN') |
7791f83a RG |
413 | |
414 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
903853f4 | 415 | self.assertEquals(receivedResponse, None) |
7791f83a RG |
416 | |
417 | (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False) | |
903853f4 RG |
418 | self.assertEquals(receivedResponse, None) |
419 | ||
420 | class TestAdvancedDelay(DNSDistTest): | |
421 | ||
422 | _config_template = """ | |
423 | addAction(AllRule(), DelayAction(1000)) | |
424 | newServer{address="127.0.0.1:%s"} | |
425 | """ | |
7791f83a | 426 | |
903853f4 | 427 | def testDelayed(self): |
7791f83a | 428 | """ |
903853f4 | 429 | Advanced: Delayed |
7791f83a | 430 | |
903853f4 RG |
431 | Send an A query to "tests.powerdns.com.", |
432 | check that the response delay is longer than 1000 ms | |
433 | over UDP, less than that over TCP. | |
7791f83a | 434 | """ |
903853f4 RG |
435 | name = 'tests.powerdns.com.' |
436 | query = dns.message.make_query(name, 'A', 'IN') | |
437 | response = dns.message.make_response(query) | |
7791f83a RG |
438 | rrset = dns.rrset.from_text(name, |
439 | 60, | |
440 | dns.rdataclass.IN, | |
903853f4 RG |
441 | dns.rdatatype.A, |
442 | '192.0.2.1') | |
443 | response.answer.append(rrset) | |
7791f83a | 444 | |
903853f4 RG |
445 | begin = datetime.now() |
446 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
447 | end = datetime.now() | |
448 | receivedQuery.id = query.id | |
449 | self.assertEquals(query, receivedQuery) | |
450 | self.assertEquals(response, receivedResponse) | |
451 | self.assertTrue((end - begin) > timedelta(0, 1)) | |
452 | ||
453 | begin = datetime.now() | |
454 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
455 | end = datetime.now() | |
456 | receivedQuery.id = query.id | |
457 | self.assertEquals(query, receivedQuery) | |
458 | self.assertEquals(response, receivedResponse) | |
459 | self.assertTrue((end - begin) < timedelta(0, 1)) | |
7791f83a | 460 | |
e7a1029c RG |
461 | |
462 | class TestAdvancedTruncateAnyAndTCP(DNSDistTest): | |
463 | ||
464 | _config_template = """ | |
465 | truncateTC(false) | |
466 | addAction(AndRule({QTypeRule("ANY"), TCPRule(true)}), TCAction()) | |
467 | newServer{address="127.0.0.1:%s"} | |
468 | """ | |
469 | def testTruncateAnyOverTCP(self): | |
470 | """ | |
471 | Advanced: Truncate ANY over TCP | |
472 | ||
b1bec9f0 | 473 | Send an ANY query to "anytruncatetcp.advanced.tests.powerdns.com.", |
e7a1029c RG |
474 | should be truncated over TCP, not over UDP (yes, it makes no sense, |
475 | deal with it). | |
476 | """ | |
b1bec9f0 | 477 | name = 'anytruncatetcp.advanced.tests.powerdns.com.' |
e7a1029c RG |
478 | query = dns.message.make_query(name, 'ANY', 'IN') |
479 | ||
480 | response = dns.message.make_response(query) | |
481 | rrset = dns.rrset.from_text(name, | |
482 | 3600, | |
483 | dns.rdataclass.IN, | |
484 | dns.rdatatype.A, | |
485 | '127.0.0.1') | |
486 | ||
487 | response.answer.append(rrset) | |
488 | ||
489 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
490 | self.assertTrue(receivedQuery) | |
491 | self.assertTrue(receivedResponse) | |
492 | receivedQuery.id = query.id | |
e7a1029c RG |
493 | self.assertEquals(query, receivedQuery) |
494 | self.assertEquals(receivedResponse, response) | |
495 | ||
496 | expectedResponse = dns.message.make_response(query) | |
497 | expectedResponse.flags |= dns.flags.TC | |
498 | ||
499 | (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False) | |
e7a1029c RG |
500 | self.assertEquals(receivedResponse, expectedResponse) |
501 | ||
502 | class TestAdvancedAndNot(DNSDistTest): | |
503 | ||
504 | _config_template = """ | |
505 | addAction(AndRule({NotRule(QTypeRule("A")), TCPRule(false)}), RCodeAction(4)) | |
506 | newServer{address="127.0.0.1:%s"} | |
507 | """ | |
508 | def testAOverUDPReturnsNotImplementedCanary(self): | |
509 | """ | |
510 | Advanced: !A && UDP canary | |
511 | ||
512 | dnsdist is configured to reply 'not implemented' for query | |
513 | over UDP AND !qtype A. | |
514 | We send an A query over UDP and TCP, and check that the | |
515 | response is OK. | |
516 | """ | |
b1bec9f0 | 517 | name = 'andnot.advanced.tests.powerdns.com.' |
e7a1029c RG |
518 | query = dns.message.make_query(name, 'A', 'IN') |
519 | response = dns.message.make_response(query) | |
520 | rrset = dns.rrset.from_text(name, | |
521 | 3600, | |
522 | dns.rdataclass.IN, | |
523 | dns.rdatatype.A, | |
524 | '127.0.0.1') | |
525 | response.answer.append(rrset) | |
526 | ||
527 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
528 | self.assertTrue(receivedQuery) | |
529 | self.assertTrue(receivedResponse) | |
530 | receivedQuery.id = query.id | |
e7a1029c RG |
531 | self.assertEquals(query, receivedQuery) |
532 | self.assertEquals(receivedResponse, response) | |
533 | ||
534 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
535 | self.assertTrue(receivedQuery) | |
536 | self.assertTrue(receivedResponse) | |
537 | receivedQuery.id = query.id | |
e7a1029c RG |
538 | self.assertEquals(query, receivedQuery) |
539 | self.assertEquals(receivedResponse, response) | |
540 | ||
541 | def testAOverUDPReturnsNotImplemented(self): | |
542 | """ | |
543 | Advanced: !A && UDP | |
544 | ||
545 | dnsdist is configured to reply 'not implemented' for query | |
546 | over UDP AND !qtype A. | |
547 | We send a TXT query over UDP and TCP, and check that the | |
548 | response is OK for TCP and 'not implemented' for UDP. | |
549 | """ | |
b1bec9f0 | 550 | name = 'andnot.advanced.tests.powerdns.com.' |
e7a1029c RG |
551 | query = dns.message.make_query(name, 'TXT', 'IN') |
552 | ||
553 | expectedResponse = dns.message.make_response(query) | |
554 | expectedResponse.set_rcode(dns.rcode.NOTIMP) | |
555 | ||
556 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
e7a1029c RG |
557 | self.assertEquals(receivedResponse, expectedResponse) |
558 | ||
559 | response = dns.message.make_response(query) | |
560 | rrset = dns.rrset.from_text(name, | |
561 | 3600, | |
562 | dns.rdataclass.IN, | |
563 | dns.rdatatype.TXT, | |
564 | 'nothing to see here') | |
565 | response.answer.append(rrset) | |
566 | ||
567 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
568 | self.assertTrue(receivedQuery) | |
569 | self.assertTrue(receivedResponse) | |
570 | receivedQuery.id = query.id | |
e7a1029c RG |
571 | self.assertEquals(query, receivedQuery) |
572 | self.assertEquals(receivedResponse, response) | |
573 | ||
574 | class TestAdvancedOr(DNSDistTest): | |
575 | ||
576 | _config_template = """ | |
577 | addAction(OrRule({QTypeRule("A"), TCPRule(false)}), RCodeAction(4)) | |
578 | newServer{address="127.0.0.1:%s"} | |
579 | """ | |
580 | def testAAAAOverUDPReturnsNotImplemented(self): | |
581 | """ | |
582 | Advanced: A || UDP: AAAA | |
583 | ||
584 | dnsdist is configured to reply 'not implemented' for query | |
585 | over UDP OR qtype A. | |
586 | We send an AAAA query over UDP and TCP, and check that the | |
587 | response is 'not implemented' for UDP and OK for TCP. | |
588 | """ | |
b1bec9f0 | 589 | name = 'aorudp.advanced.tests.powerdns.com.' |
e7a1029c RG |
590 | query = dns.message.make_query(name, 'AAAA', 'IN') |
591 | response = dns.message.make_response(query) | |
592 | rrset = dns.rrset.from_text(name, | |
593 | 3600, | |
594 | dns.rdataclass.IN, | |
595 | dns.rdatatype.AAAA, | |
596 | '::1') | |
597 | response.answer.append(rrset) | |
598 | ||
599 | expectedResponse = dns.message.make_response(query) | |
600 | expectedResponse.set_rcode(dns.rcode.NOTIMP) | |
601 | ||
602 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
e7a1029c RG |
603 | self.assertEquals(receivedResponse, expectedResponse) |
604 | ||
605 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
606 | self.assertTrue(receivedQuery) | |
607 | self.assertTrue(receivedResponse) | |
608 | receivedQuery.id = query.id | |
e7a1029c RG |
609 | self.assertEquals(query, receivedQuery) |
610 | self.assertEquals(receivedResponse, response) | |
611 | ||
612 | def testAOverUDPReturnsNotImplemented(self): | |
613 | """ | |
614 | Advanced: A || UDP: A | |
615 | ||
616 | dnsdist is configured to reply 'not implemented' for query | |
617 | over UDP OR qtype A. | |
618 | We send an A query over UDP and TCP, and check that the | |
619 | response is 'not implemented' for both. | |
620 | """ | |
b1bec9f0 | 621 | name = 'aorudp.advanced.tests.powerdns.com.' |
e7a1029c RG |
622 | query = dns.message.make_query(name, 'A', 'IN') |
623 | ||
624 | expectedResponse = dns.message.make_response(query) | |
625 | expectedResponse.set_rcode(dns.rcode.NOTIMP) | |
626 | ||
627 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
e7a1029c RG |
628 | self.assertEquals(receivedResponse, expectedResponse) |
629 | ||
630 | (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False) | |
e7a1029c | 631 | self.assertEquals(receivedResponse, expectedResponse) |
886e2cf2 | 632 | |
b1bec9f0 RG |
633 | |
634 | class TestAdvancedLogAction(DNSDistTest): | |
635 | ||
636 | _config_template = """ | |
637 | newServer{address="127.0.0.1:%s"} | |
638 | addAction(AllRule(), LogAction("dnsdist.log", false)) | |
639 | """ | |
640 | def testAdvancedLogAction(self): | |
641 | """ | |
642 | Advanced: Log all queries | |
643 | ||
644 | """ | |
645 | count = 50 | |
646 | name = 'logaction.advanced.tests.powerdns.com.' | |
647 | query = dns.message.make_query(name, 'A', 'IN') | |
648 | response = dns.message.make_response(query) | |
649 | rrset = dns.rrset.from_text(name, | |
650 | 3600, | |
651 | dns.rdataclass.IN, | |
652 | dns.rdatatype.A, | |
653 | '127.0.0.1') | |
654 | response.answer.append(rrset) | |
655 | ||
656 | for _ in range(count): | |
657 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
658 | self.assertTrue(receivedQuery) | |
659 | self.assertTrue(receivedResponse) | |
660 | receivedQuery.id = query.id | |
b1bec9f0 RG |
661 | self.assertEquals(query, receivedQuery) |
662 | self.assertEquals(response, receivedResponse) | |
663 | ||
664 | self.assertTrue(os.path.isfile('dnsdist.log')) | |
665 | self.assertTrue(os.stat('dnsdist.log').st_size > 0) | |
666 | ||
667 | class TestAdvancedDNSSEC(DNSDistTest): | |
668 | ||
669 | _config_template = """ | |
670 | newServer{address="127.0.0.1:%s"} | |
671 | addAction(DNSSECRule(), DropAction()) | |
672 | """ | |
673 | def testAdvancedDNSSECDrop(self): | |
674 | """ | |
675 | Advanced: DNSSEC Rule | |
676 | ||
677 | """ | |
678 | name = 'dnssec.advanced.tests.powerdns.com.' | |
679 | query = dns.message.make_query(name, 'A', 'IN') | |
680 | doquery = dns.message.make_query(name, 'A', 'IN', want_dnssec=True) | |
681 | response = dns.message.make_response(query) | |
682 | rrset = dns.rrset.from_text(name, | |
683 | 3600, | |
684 | dns.rdataclass.IN, | |
685 | dns.rdatatype.A, | |
686 | '127.0.0.1') | |
687 | response.answer.append(rrset) | |
688 | ||
689 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
690 | self.assertTrue(receivedQuery) | |
691 | self.assertTrue(receivedResponse) | |
692 | receivedQuery.id = query.id | |
b1bec9f0 RG |
693 | self.assertEquals(query, receivedQuery) |
694 | self.assertEquals(response, receivedResponse) | |
695 | ||
696 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
697 | self.assertTrue(receivedQuery) | |
698 | self.assertTrue(receivedResponse) | |
699 | receivedQuery.id = query.id | |
b1bec9f0 RG |
700 | self.assertEquals(query, receivedQuery) |
701 | self.assertEquals(response, receivedResponse) | |
702 | ||
703 | (_, receivedResponse) = self.sendUDPQuery(doquery, response) | |
704 | self.assertEquals(receivedResponse, None) | |
705 | (_, receivedResponse) = self.sendTCPQuery(doquery, response) | |
706 | self.assertEquals(receivedResponse, None) | |
707 | ||
708 | class TestAdvancedQClass(DNSDistTest): | |
709 | ||
710 | _config_template = """ | |
711 | newServer{address="127.0.0.1:%s"} | |
712 | addAction(QClassRule(3), DropAction()) | |
713 | """ | |
714 | def testAdvancedQClassChaosDrop(self): | |
715 | """ | |
716 | Advanced: Drop QClass CHAOS | |
717 | ||
718 | """ | |
719 | name = 'qclasschaos.advanced.tests.powerdns.com.' | |
720 | query = dns.message.make_query(name, 'TXT', 'CHAOS') | |
721 | response = dns.message.make_response(query) | |
722 | rrset = dns.rrset.from_text(name, | |
723 | 3600, | |
724 | dns.rdataclass.CH, | |
725 | dns.rdatatype.TXT, | |
726 | 'hop') | |
727 | response.answer.append(rrset) | |
728 | ||
729 | (_, receivedResponse) = self.sendUDPQuery(query, response) | |
730 | self.assertEquals(receivedResponse, None) | |
731 | (_, receivedResponse) = self.sendTCPQuery(query, response) | |
732 | self.assertEquals(receivedResponse, None) | |
733 | ||
734 | def testAdvancedQClassINAllow(self): | |
735 | """ | |
736 | Advanced: Allow QClass IN | |
737 | ||
738 | """ | |
739 | name = 'qclassin.advanced.tests.powerdns.com.' | |
740 | query = dns.message.make_query(name, 'A', 'IN') | |
741 | response = dns.message.make_response(query) | |
742 | rrset = dns.rrset.from_text(name, | |
743 | 3600, | |
744 | dns.rdataclass.IN, | |
745 | dns.rdatatype.A, | |
746 | '127.0.0.1') | |
747 | response.answer.append(rrset) | |
748 | ||
749 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
750 | self.assertTrue(receivedQuery) | |
751 | self.assertTrue(receivedResponse) | |
752 | receivedQuery.id = query.id | |
b1bec9f0 RG |
753 | self.assertEquals(query, receivedQuery) |
754 | self.assertEquals(response, receivedResponse) | |
755 | ||
756 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
757 | self.assertTrue(receivedQuery) | |
758 | self.assertTrue(receivedResponse) | |
759 | receivedQuery.id = query.id | |
b1bec9f0 RG |
760 | self.assertEquals(query, receivedQuery) |
761 | self.assertEquals(response, receivedResponse) | |
88d05ca1 | 762 | |
46a839bf | 763 | |
88d05ca1 RG |
764 | class TestAdvancedNonTerminalRule(DNSDistTest): |
765 | ||
766 | _config_template = """ | |
767 | newServer{address="127.0.0.1:%s", pool="real"} | |
768 | addAction(AllRule(), DisableValidationAction()) | |
769 | addAction(AllRule(), PoolAction("real")) | |
770 | addAction(AllRule(), DropAction()) | |
771 | """ | |
772 | def testAdvancedNonTerminalRules(self): | |
773 | """ | |
774 | Advanced: Non terminal rules | |
775 | ||
776 | We check that DisableValidationAction() is applied | |
777 | but does not stop the processing, then that | |
778 | PoolAction() is applied _and_ stop the processing. | |
779 | """ | |
780 | name = 'nonterminal.advanced.tests.powerdns.com.' | |
781 | query = dns.message.make_query(name, 'A', 'IN') | |
782 | expectedQuery = dns.message.make_query(name, 'A', 'IN') | |
783 | expectedQuery.flags |= dns.flags.CD | |
784 | response = dns.message.make_response(query) | |
785 | rrset = dns.rrset.from_text(name, | |
786 | 3600, | |
787 | dns.rdataclass.IN, | |
788 | dns.rdatatype.A, | |
46a839bf | 789 | '192.0.2.1') |
88d05ca1 RG |
790 | response.answer.append(rrset) |
791 | ||
792 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
793 | self.assertTrue(receivedQuery) | |
794 | self.assertTrue(receivedResponse) | |
795 | receivedQuery.id = expectedQuery.id | |
796 | self.assertEquals(expectedQuery, receivedQuery) | |
797 | self.assertEquals(response, receivedResponse) | |
798 | ||
799 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
800 | self.assertTrue(receivedQuery) | |
801 | self.assertTrue(receivedResponse) | |
802 | receivedQuery.id = expectedQuery.id | |
803 | self.assertEquals(expectedQuery, receivedQuery) | |
804 | self.assertEquals(response, receivedResponse) | |
46a839bf RG |
805 | |
806 | class TestAdvancedStringOnlyServer(DNSDistTest): | |
807 | ||
808 | _config_template = """ | |
809 | newServer("127.0.0.1:%s") | |
810 | """ | |
811 | ||
812 | def testAdvancedStringOnlyServer(self): | |
813 | """ | |
814 | Advanced: "string-only" server is placed in the default pool | |
815 | """ | |
816 | name = 'string-only-server.advanced.tests.powerdns.com.' | |
817 | query = dns.message.make_query(name, 'A', 'IN') | |
818 | response = dns.message.make_response(query) | |
819 | rrset = dns.rrset.from_text(name, | |
820 | 3600, | |
821 | dns.rdataclass.IN, | |
822 | dns.rdatatype.A, | |
823 | '192.0.2.1') | |
824 | response.answer.append(rrset) | |
825 | ||
826 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
827 | self.assertTrue(receivedQuery) | |
828 | self.assertTrue(receivedResponse) | |
829 | receivedQuery.id = query.id | |
830 | self.assertEquals(query, receivedQuery) | |
831 | self.assertEquals(response, receivedResponse) | |
832 | ||
833 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
834 | self.assertTrue(receivedQuery) | |
835 | self.assertTrue(receivedResponse) | |
836 | receivedQuery.id = query.id | |
837 | self.assertEquals(query, receivedQuery) | |
838 | self.assertEquals(response, receivedResponse) | |
0f72fd5c RG |
839 | |
840 | class TestAdvancedRestoreFlagsOnSelfResponse(DNSDistTest): | |
841 | ||
842 | _config_template = """ | |
843 | addAction(AllRule(), DisableValidationAction()) | |
844 | addAction(AllRule(), SpoofAction("192.0.2.1")) | |
845 | newServer{address="127.0.0.1:%s"} | |
846 | """ | |
847 | ||
848 | def testAdvancedRestoreFlagsOnSpoofResponse(self): | |
849 | """ | |
850 | Advanced: Restore flags on spoofed response | |
851 | ||
852 | Send a query with CD flag cleared, dnsdist is | |
853 | instructed to set it, then to spoof the response, | |
854 | check that response has the flag cleared. | |
855 | """ | |
856 | name = 'spoofed.restoreflags.advanced.tests.powerdns.com.' | |
857 | query = dns.message.make_query(name, 'A', 'IN') | |
858 | # dnsdist set RA = RD for spoofed responses | |
859 | query.flags &= ~dns.flags.RD | |
860 | expectedQuery = dns.message.make_query(name, 'A', 'IN') | |
861 | ||
862 | response = dns.message.make_response(query) | |
863 | rrset = dns.rrset.from_text(name, | |
864 | 60, | |
865 | dns.rdataclass.IN, | |
866 | dns.rdatatype.A, | |
867 | '192.0.2.1') | |
868 | response.answer.append(rrset) | |
869 | ||
870 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
871 | self.assertTrue(receivedResponse) | |
872 | self.assertEquals(response, receivedResponse) | |
873 | ||
874 | (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False) | |
875 | self.assertTrue(receivedResponse) | |
876 | self.assertEquals(response, receivedResponse) | |
856c35e3 RG |
877 | |
878 | class TestAdvancedQPS(DNSDistTest): | |
879 | ||
880 | _config_template = """ | |
881 | addQPSLimit("qps.advanced.tests.powerdns.com", 10) | |
882 | newServer{address="127.0.0.1:%s"} | |
883 | """ | |
884 | ||
885 | def testAdvancedQPSLimit(self): | |
886 | """ | |
887 | Advanced: QPS Limit | |
888 | ||
889 | Send queries to "qps.advanced.tests.powerdns.com." | |
890 | check that dnsdist drops queries when the max QPS has been reached. | |
891 | """ | |
892 | maxQPS = 10 | |
893 | name = 'qps.advanced.tests.powerdns.com.' | |
894 | query = dns.message.make_query(name, 'A', 'IN') | |
895 | response = dns.message.make_response(query) | |
896 | rrset = dns.rrset.from_text(name, | |
897 | 60, | |
898 | dns.rdataclass.IN, | |
899 | dns.rdatatype.A, | |
900 | '192.0.2.1') | |
901 | response.answer.append(rrset) | |
902 | ||
903 | for _ in range(maxQPS): | |
904 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
905 | receivedQuery.id = query.id | |
906 | self.assertEquals(query, receivedQuery) | |
907 | self.assertEquals(response, receivedResponse) | |
908 | ||
909 | # we should now be dropped | |
910 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
911 | self.assertEquals(receivedResponse, None) | |
912 | ||
913 | time.sleep(1) | |
914 | ||
915 | # again, over TCP this time | |
916 | for _ in range(maxQPS): | |
917 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
918 | receivedQuery.id = query.id | |
919 | self.assertEquals(query, receivedQuery) | |
920 | self.assertEquals(response, receivedResponse) | |
921 | ||
922 | ||
923 | (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False) | |
924 | self.assertEquals(receivedResponse, None) | |
925 | ||
926 | class TestAdvancedQPSNone(DNSDistTest): | |
927 | ||
928 | _config_template = """ | |
929 | addQPSLimit("qpsnone.advanced.tests.powerdns.com", 100) | |
930 | addAction(AllRule(), RCodeAction(5)) | |
931 | newServer{address="127.0.0.1:%s"} | |
932 | """ | |
933 | ||
934 | def testAdvancedQPSNone(self): | |
935 | """ | |
936 | Advanced: Not matching QPS returns None, not Allow | |
937 | ||
938 | Send queries to "qps.advanced.tests.powerdns.com." | |
939 | check that the rule returns None when the QPS has not been | |
940 | reached, not Allow. | |
941 | """ | |
942 | name = 'qpsnone.advanced.tests.powerdns.com.' | |
943 | query = dns.message.make_query(name, 'A', 'IN') | |
944 | expectedResponse = dns.message.make_response(query) | |
945 | expectedResponse.set_rcode(dns.rcode.REFUSED) | |
946 | ||
947 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
948 | self.assertEquals(receivedResponse, expectedResponse) | |
949 | ||
950 | (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False) | |
951 | self.assertEquals(receivedResponse, expectedResponse) |