]> git.ipfire.org Git - thirdparty/pdns.git/blob - regression-tests.dnsdist/test_Advanced.py
Merge pull request #6824 from klaus3000/improve-slavecheck-logging
[thirdparty/pdns.git] / regression-tests.dnsdist / test_Advanced.py
1 #!/usr/bin/env python
2 import base64
3 from datetime import datetime, timedelta
4 import os
5 import string
6 import time
7 import dns
8 from dnsdisttests import DNSDistTest
9
10 class TestAdvancedAllow(DNSDistTest):
11
12 _config_template = """
13 addAction(AllRule(), NoneAction())
14 addAction(makeRule("allowed.advanced.tests.powerdns.com."), AllowAction())
15 addAction(AllRule(), DropAction())
16 newServer{address="127.0.0.1:%s"}
17 """
18
19 def testAdvancedAllow(self):
20 """
21 Advanced: Allowed qname is not dropped
22
23 A query for allowed.advanced.tests.powerdns.com. should be allowed
24 while others should be dropped.
25 """
26 name = 'allowed.advanced.tests.powerdns.com.'
27 query = dns.message.make_query(name, 'A', 'IN')
28 response = dns.message.make_response(query)
29 rrset = dns.rrset.from_text(name,
30 3600,
31 dns.rdataclass.IN,
32 dns.rdatatype.A,
33 '127.0.0.1')
34 response.answer.append(rrset)
35
36 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
37 self.assertTrue(receivedQuery)
38 self.assertTrue(receivedResponse)
39 receivedQuery.id = query.id
40 self.assertEquals(query, receivedQuery)
41 self.assertEquals(response, receivedResponse)
42
43 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
44 self.assertTrue(receivedQuery)
45 self.assertTrue(receivedResponse)
46 receivedQuery.id = query.id
47 self.assertEquals(query, receivedQuery)
48 self.assertEquals(response, receivedResponse)
49
50 def testAdvancedAllowDropped(self):
51 """
52 Advanced: Not allowed qname is dropped
53
54 A query for notallowed.advanced.tests.powerdns.com. should be dropped.
55 """
56 name = 'notallowed.advanced.tests.powerdns.com.'
57 query = dns.message.make_query(name, 'A', 'IN')
58 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
59 self.assertEquals(receivedResponse, None)
60
61 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
62 self.assertEquals(receivedResponse, None)
63
64 class TestAdvancedFixupCase(DNSDistTest):
65
66 _config_template = """
67 truncateTC(true)
68 fixupCase(true)
69 newServer{address="127.0.0.1:%s"}
70 """
71
72 def testAdvancedFixupCase(self):
73 """
74 Advanced: Fixup Case
75
76 Send a query with lower and upper chars,
77 make the backend return a lowercase version,
78 check that dnsdist fixes the response.
79 """
80 name = 'fiXuPCasE.advanced.tests.powerdns.com.'
81 query = dns.message.make_query(name, 'A', 'IN')
82 lowercasequery = dns.message.make_query(name.lower(), 'A', 'IN')
83 response = dns.message.make_response(lowercasequery)
84 expectedResponse = dns.message.make_response(query)
85 rrset = dns.rrset.from_text(name,
86 3600,
87 dns.rdataclass.IN,
88 dns.rdatatype.A,
89 '127.0.0.1')
90 response.answer.append(rrset)
91 expectedResponse.answer.append(rrset)
92
93 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
94 self.assertTrue(receivedQuery)
95 self.assertTrue(receivedResponse)
96 receivedQuery.id = query.id
97 self.assertEquals(query, receivedQuery)
98 self.assertEquals(expectedResponse, receivedResponse)
99
100 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
101 self.assertTrue(receivedQuery)
102 self.assertTrue(receivedResponse)
103 receivedQuery.id = query.id
104 self.assertEquals(query, receivedQuery)
105 self.assertEquals(expectedResponse, receivedResponse)
106
107
108 class TestAdvancedRemoveRD(DNSDistTest):
109
110 _config_template = """
111 addAction("norecurse.advanced.tests.powerdns.com.", NoRecurseAction())
112 newServer{address="127.0.0.1:%s"}
113 """
114
115 def testAdvancedNoRD(self):
116 """
117 Advanced: No RD
118
119 Send a query with RD,
120 check that dnsdist clears the RD flag.
121 """
122 name = 'norecurse.advanced.tests.powerdns.com.'
123 query = dns.message.make_query(name, 'A', 'IN')
124 expectedQuery = dns.message.make_query(name, 'A', 'IN')
125 expectedQuery.flags &= ~dns.flags.RD
126
127 response = dns.message.make_response(query)
128 rrset = dns.rrset.from_text(name,
129 3600,
130 dns.rdataclass.IN,
131 dns.rdatatype.A,
132 '127.0.0.1')
133 response.answer.append(rrset)
134
135 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
136 self.assertTrue(receivedQuery)
137 self.assertTrue(receivedResponse)
138 receivedQuery.id = expectedQuery.id
139 self.assertEquals(expectedQuery, receivedQuery)
140 self.assertEquals(response, receivedResponse)
141
142 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
143 self.assertTrue(receivedQuery)
144 self.assertTrue(receivedResponse)
145 receivedQuery.id = expectedQuery.id
146 self.assertEquals(expectedQuery, receivedQuery)
147 self.assertEquals(response, receivedResponse)
148
149 def testAdvancedKeepRD(self):
150 """
151 Advanced: No RD canary
152
153 Send a query with RD for a canary domain,
154 check that dnsdist does not clear the RD flag.
155 """
156 name = 'keeprecurse.advanced.tests.powerdns.com.'
157 query = dns.message.make_query(name, 'A', 'IN')
158
159 response = dns.message.make_response(query)
160 rrset = dns.rrset.from_text(name,
161 3600,
162 dns.rdataclass.IN,
163 dns.rdatatype.A,
164 '127.0.0.1')
165 response.answer.append(rrset)
166
167 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
168 self.assertTrue(receivedQuery)
169 self.assertTrue(receivedResponse)
170 receivedQuery.id = query.id
171 self.assertEquals(query, receivedQuery)
172 self.assertEquals(response, receivedResponse)
173
174 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
175 self.assertTrue(receivedQuery)
176 self.assertTrue(receivedResponse)
177 receivedQuery.id = query.id
178 self.assertEquals(query, receivedQuery)
179 self.assertEquals(response, receivedResponse)
180
181
182 class TestAdvancedAddCD(DNSDistTest):
183
184 _config_template = """
185 addAction("setcd.advanced.tests.powerdns.com.", DisableValidationAction())
186 addAction(makeRule("setcdviaaction.advanced.tests.powerdns.com."), DisableValidationAction())
187 newServer{address="127.0.0.1:%s"}
188 """
189
190 def testAdvancedSetCD(self):
191 """
192 Advanced: Set CD
193
194 Send a query with CD cleared,
195 check that dnsdist set the CD flag.
196 """
197 name = 'setcd.advanced.tests.powerdns.com.'
198 query = dns.message.make_query(name, 'A', 'IN')
199 expectedQuery = dns.message.make_query(name, 'A', 'IN')
200 expectedQuery.flags |= dns.flags.CD
201
202 response = dns.message.make_response(query)
203 rrset = dns.rrset.from_text(name,
204 3600,
205 dns.rdataclass.IN,
206 dns.rdatatype.A,
207 '127.0.0.1')
208 response.answer.append(rrset)
209
210 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
211 self.assertTrue(receivedQuery)
212 self.assertTrue(receivedResponse)
213 receivedQuery.id = expectedQuery.id
214 self.assertEquals(expectedQuery, receivedQuery)
215 self.assertEquals(response, receivedResponse)
216
217 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
218 self.assertTrue(receivedQuery)
219 self.assertTrue(receivedResponse)
220 receivedQuery.id = expectedQuery.id
221 self.assertEquals(expectedQuery, receivedQuery)
222 self.assertEquals(response, receivedResponse)
223
224 def testAdvancedSetCDViaAction(self):
225 """
226 Advanced: Set CD via Action
227
228 Send a query with CD cleared,
229 check that dnsdist set the CD flag.
230 """
231 name = 'setcdviaaction.advanced.tests.powerdns.com.'
232 query = dns.message.make_query(name, 'A', 'IN')
233 expectedQuery = dns.message.make_query(name, 'A', 'IN')
234 expectedQuery.flags |= dns.flags.CD
235
236 response = dns.message.make_response(query)
237 rrset = dns.rrset.from_text(name,
238 3600,
239 dns.rdataclass.IN,
240 dns.rdatatype.A,
241 '127.0.0.1')
242 response.answer.append(rrset)
243
244 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
245 self.assertTrue(receivedQuery)
246 self.assertTrue(receivedResponse)
247 receivedQuery.id = expectedQuery.id
248 self.assertEquals(expectedQuery, receivedQuery)
249 self.assertEquals(response, receivedResponse)
250
251 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
252 self.assertTrue(receivedQuery)
253 self.assertTrue(receivedResponse)
254 receivedQuery.id = expectedQuery.id
255 self.assertEquals(expectedQuery, receivedQuery)
256 self.assertEquals(response, receivedResponse)
257
258 def testAdvancedKeepNoCD(self):
259 """
260 Advanced: Preserve CD canary
261
262 Send a query without CD for a canary domain,
263 check that dnsdist does not set the CD flag.
264 """
265 name = 'keepnocd.advanced.tests.powerdns.com.'
266 query = dns.message.make_query(name, 'A', 'IN')
267
268 response = dns.message.make_response(query)
269 rrset = dns.rrset.from_text(name,
270 3600,
271 dns.rdataclass.IN,
272 dns.rdatatype.A,
273 '127.0.0.1')
274 response.answer.append(rrset)
275
276 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
277 self.assertTrue(receivedQuery)
278 self.assertTrue(receivedResponse)
279 receivedQuery.id = query.id
280 self.assertEquals(query, receivedQuery)
281 self.assertEquals(response, receivedResponse)
282
283 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
284 self.assertTrue(receivedQuery)
285 self.assertTrue(receivedResponse)
286 receivedQuery.id = query.id
287 self.assertEquals(query, receivedQuery)
288 self.assertEquals(response, receivedResponse)
289
290 class TestAdvancedClearRD(DNSDistTest):
291
292 _config_template = """
293 addAction("clearrd.advanced.tests.powerdns.com.", NoRecurseAction())
294 addAction(makeRule("clearrdviaaction.advanced.tests.powerdns.com."), NoRecurseAction())
295 newServer{address="127.0.0.1:%s"}
296 """
297
298 def testAdvancedClearRD(self):
299 """
300 Advanced: Clear RD
301
302 Send a query with RD set,
303 check that dnsdist clears the RD flag.
304 """
305 name = 'clearrd.advanced.tests.powerdns.com.'
306 query = dns.message.make_query(name, 'A', 'IN')
307 expectedQuery = dns.message.make_query(name, 'A', 'IN')
308 expectedQuery.flags &= ~dns.flags.RD
309
310 response = dns.message.make_response(query)
311 rrset = dns.rrset.from_text(name,
312 3600,
313 dns.rdataclass.IN,
314 dns.rdatatype.A,
315 '127.0.0.1')
316 response.answer.append(rrset)
317
318 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
319 self.assertTrue(receivedQuery)
320 self.assertTrue(receivedResponse)
321 receivedQuery.id = expectedQuery.id
322 self.assertEquals(expectedQuery, receivedQuery)
323 self.assertEquals(response, receivedResponse)
324
325 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
326 self.assertTrue(receivedQuery)
327 self.assertTrue(receivedResponse)
328 receivedQuery.id = expectedQuery.id
329 self.assertEquals(expectedQuery, receivedQuery)
330 self.assertEquals(response, receivedResponse)
331
332 def testAdvancedClearRDViaAction(self):
333 """
334 Advanced: Clear RD via Action
335
336 Send a query with RD set,
337 check that dnsdist clears the RD flag.
338 """
339 name = 'clearrdviaaction.advanced.tests.powerdns.com.'
340 query = dns.message.make_query(name, 'A', 'IN')
341 expectedQuery = dns.message.make_query(name, 'A', 'IN')
342 expectedQuery.flags &= ~dns.flags.RD
343
344 response = dns.message.make_response(query)
345 rrset = dns.rrset.from_text(name,
346 3600,
347 dns.rdataclass.IN,
348 dns.rdatatype.A,
349 '127.0.0.1')
350 response.answer.append(rrset)
351
352 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
353 self.assertTrue(receivedQuery)
354 self.assertTrue(receivedResponse)
355 receivedQuery.id = expectedQuery.id
356 self.assertEquals(expectedQuery, receivedQuery)
357 self.assertEquals(response, receivedResponse)
358
359 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
360 self.assertTrue(receivedQuery)
361 self.assertTrue(receivedResponse)
362 receivedQuery.id = expectedQuery.id
363 self.assertEquals(expectedQuery, receivedQuery)
364 self.assertEquals(response, receivedResponse)
365
366 def testAdvancedKeepRD(self):
367 """
368 Advanced: Preserve RD canary
369
370 Send a query with RD for a canary domain,
371 check that dnsdist does not clear the RD flag.
372 """
373 name = 'keeprd.advanced.tests.powerdns.com.'
374 query = dns.message.make_query(name, 'A', 'IN')
375
376 response = dns.message.make_response(query)
377 rrset = dns.rrset.from_text(name,
378 3600,
379 dns.rdataclass.IN,
380 dns.rdatatype.A,
381 '127.0.0.1')
382 response.answer.append(rrset)
383
384 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
385 self.assertTrue(receivedQuery)
386 self.assertTrue(receivedResponse)
387 receivedQuery.id = query.id
388 self.assertEquals(query, receivedQuery)
389 self.assertEquals(response, receivedResponse)
390
391 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
392 self.assertTrue(receivedQuery)
393 self.assertTrue(receivedResponse)
394 receivedQuery.id = query.id
395 self.assertEquals(query, receivedQuery)
396 self.assertEquals(response, receivedResponse)
397
398
399 class TestAdvancedACL(DNSDistTest):
400
401 _config_template = """
402 newServer{address="127.0.0.1:%s"}
403 """
404 _acl = ['192.0.2.1/32']
405
406 def testACLBlocked(self):
407 """
408 Advanced: ACL blocked
409
410 Send an A query to "tests.powerdns.com.",
411 we expect no response since 127.0.0.1 is not on the
412 ACL.
413 """
414 name = 'tests.powerdns.com.'
415 query = dns.message.make_query(name, 'A', 'IN')
416
417 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
418 self.assertEquals(receivedResponse, None)
419
420 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
421 self.assertEquals(receivedResponse, None)
422
423 class TestAdvancedDelay(DNSDistTest):
424
425 _config_template = """
426 addAction(AllRule(), DelayAction(1000))
427 newServer{address="127.0.0.1:%s"}
428 """
429
430 def testDelayed(self):
431 """
432 Advanced: Delayed
433
434 Send an A query to "tests.powerdns.com.",
435 check that the response delay is longer than 1000 ms
436 over UDP, less than that over TCP.
437 """
438 name = 'tests.powerdns.com.'
439 query = dns.message.make_query(name, 'A', 'IN')
440 response = dns.message.make_response(query)
441 rrset = dns.rrset.from_text(name,
442 60,
443 dns.rdataclass.IN,
444 dns.rdatatype.A,
445 '192.0.2.1')
446 response.answer.append(rrset)
447
448 begin = datetime.now()
449 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
450 end = datetime.now()
451 receivedQuery.id = query.id
452 self.assertEquals(query, receivedQuery)
453 self.assertEquals(response, receivedResponse)
454 self.assertTrue((end - begin) > timedelta(0, 1))
455
456 begin = datetime.now()
457 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
458 end = datetime.now()
459 receivedQuery.id = query.id
460 self.assertEquals(query, receivedQuery)
461 self.assertEquals(response, receivedResponse)
462 self.assertTrue((end - begin) < timedelta(0, 1))
463
464
465 class TestAdvancedTruncateAnyAndTCP(DNSDistTest):
466
467 _config_template = """
468 truncateTC(false)
469 addAction(AndRule({QTypeRule("ANY"), TCPRule(true)}), TCAction())
470 newServer{address="127.0.0.1:%s"}
471 """
472 def testTruncateAnyOverTCP(self):
473 """
474 Advanced: Truncate ANY over TCP
475
476 Send an ANY query to "anytruncatetcp.advanced.tests.powerdns.com.",
477 should be truncated over TCP, not over UDP (yes, it makes no sense,
478 deal with it).
479 """
480 name = 'anytruncatetcp.advanced.tests.powerdns.com.'
481 query = dns.message.make_query(name, 'ANY', 'IN')
482
483 response = dns.message.make_response(query)
484 rrset = dns.rrset.from_text(name,
485 3600,
486 dns.rdataclass.IN,
487 dns.rdatatype.A,
488 '127.0.0.1')
489
490 response.answer.append(rrset)
491
492 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
493 self.assertTrue(receivedQuery)
494 self.assertTrue(receivedResponse)
495 receivedQuery.id = query.id
496 self.assertEquals(query, receivedQuery)
497 self.assertEquals(receivedResponse, response)
498
499 expectedResponse = dns.message.make_response(query)
500 expectedResponse.flags |= dns.flags.TC
501
502 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
503 self.assertEquals(receivedResponse, expectedResponse)
504
505 class TestAdvancedAndNot(DNSDistTest):
506
507 _config_template = """
508 addAction(AndRule({NotRule(QTypeRule("A")), TCPRule(false)}), RCodeAction(dnsdist.NOTIMP))
509 newServer{address="127.0.0.1:%s"}
510 """
511 def testAOverUDPReturnsNotImplementedCanary(self):
512 """
513 Advanced: !A && UDP canary
514
515 dnsdist is configured to reply 'not implemented' for query
516 over UDP AND !qtype A.
517 We send an A query over UDP and TCP, and check that the
518 response is OK.
519 """
520 name = 'andnot.advanced.tests.powerdns.com.'
521 query = dns.message.make_query(name, 'A', 'IN')
522 response = dns.message.make_response(query)
523 rrset = dns.rrset.from_text(name,
524 3600,
525 dns.rdataclass.IN,
526 dns.rdatatype.A,
527 '127.0.0.1')
528 response.answer.append(rrset)
529
530 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
531 self.assertTrue(receivedQuery)
532 self.assertTrue(receivedResponse)
533 receivedQuery.id = query.id
534 self.assertEquals(query, receivedQuery)
535 self.assertEquals(receivedResponse, response)
536
537 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
538 self.assertTrue(receivedQuery)
539 self.assertTrue(receivedResponse)
540 receivedQuery.id = query.id
541 self.assertEquals(query, receivedQuery)
542 self.assertEquals(receivedResponse, response)
543
544 def testAOverUDPReturnsNotImplemented(self):
545 """
546 Advanced: !A && UDP
547
548 dnsdist is configured to reply 'not implemented' for query
549 over UDP AND !qtype A.
550 We send a TXT query over UDP and TCP, and check that the
551 response is OK for TCP and 'not implemented' for UDP.
552 """
553 name = 'andnot.advanced.tests.powerdns.com.'
554 query = dns.message.make_query(name, 'TXT', 'IN')
555
556 expectedResponse = dns.message.make_response(query)
557 expectedResponse.set_rcode(dns.rcode.NOTIMP)
558
559 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
560 self.assertEquals(receivedResponse, expectedResponse)
561
562 response = dns.message.make_response(query)
563 rrset = dns.rrset.from_text(name,
564 3600,
565 dns.rdataclass.IN,
566 dns.rdatatype.TXT,
567 'nothing to see here')
568 response.answer.append(rrset)
569
570 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
571 self.assertTrue(receivedQuery)
572 self.assertTrue(receivedResponse)
573 receivedQuery.id = query.id
574 self.assertEquals(query, receivedQuery)
575 self.assertEquals(receivedResponse, response)
576
577 class TestAdvancedOr(DNSDistTest):
578
579 _config_template = """
580 addAction(OrRule({QTypeRule("A"), TCPRule(false)}), RCodeAction(dnsdist.NOTIMP))
581 newServer{address="127.0.0.1:%s"}
582 """
583 def testAAAAOverUDPReturnsNotImplemented(self):
584 """
585 Advanced: A || UDP: AAAA
586
587 dnsdist is configured to reply 'not implemented' for query
588 over UDP OR qtype A.
589 We send an AAAA query over UDP and TCP, and check that the
590 response is 'not implemented' for UDP and OK for TCP.
591 """
592 name = 'aorudp.advanced.tests.powerdns.com.'
593 query = dns.message.make_query(name, 'AAAA', 'IN')
594 response = dns.message.make_response(query)
595 rrset = dns.rrset.from_text(name,
596 3600,
597 dns.rdataclass.IN,
598 dns.rdatatype.AAAA,
599 '::1')
600 response.answer.append(rrset)
601
602 expectedResponse = dns.message.make_response(query)
603 expectedResponse.set_rcode(dns.rcode.NOTIMP)
604
605 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
606 self.assertEquals(receivedResponse, expectedResponse)
607
608 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
609 self.assertTrue(receivedQuery)
610 self.assertTrue(receivedResponse)
611 receivedQuery.id = query.id
612 self.assertEquals(query, receivedQuery)
613 self.assertEquals(receivedResponse, response)
614
615 def testAOverUDPReturnsNotImplemented(self):
616 """
617 Advanced: A || UDP: A
618
619 dnsdist is configured to reply 'not implemented' for query
620 over UDP OR qtype A.
621 We send an A query over UDP and TCP, and check that the
622 response is 'not implemented' for both.
623 """
624 name = 'aorudp.advanced.tests.powerdns.com.'
625 query = dns.message.make_query(name, 'A', 'IN')
626
627 expectedResponse = dns.message.make_response(query)
628 expectedResponse.set_rcode(dns.rcode.NOTIMP)
629
630 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
631 self.assertEquals(receivedResponse, expectedResponse)
632
633 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
634 self.assertEquals(receivedResponse, expectedResponse)
635
636
637 class TestAdvancedLogAction(DNSDistTest):
638
639 _config_template = """
640 newServer{address="127.0.0.1:%s"}
641 addAction(AllRule(), LogAction("dnsdist.log", false))
642 """
643 def testAdvancedLogAction(self):
644 """
645 Advanced: Log all queries
646
647 """
648 count = 50
649 name = 'logaction.advanced.tests.powerdns.com.'
650 query = dns.message.make_query(name, 'A', 'IN')
651 response = dns.message.make_response(query)
652 rrset = dns.rrset.from_text(name,
653 3600,
654 dns.rdataclass.IN,
655 dns.rdatatype.A,
656 '127.0.0.1')
657 response.answer.append(rrset)
658
659 for _ in range(count):
660 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
661 self.assertTrue(receivedQuery)
662 self.assertTrue(receivedResponse)
663 receivedQuery.id = query.id
664 self.assertEquals(query, receivedQuery)
665 self.assertEquals(response, receivedResponse)
666
667 self.assertTrue(os.path.isfile('dnsdist.log'))
668 self.assertTrue(os.stat('dnsdist.log').st_size > 0)
669
670 class TestAdvancedDNSSEC(DNSDistTest):
671
672 _config_template = """
673 newServer{address="127.0.0.1:%s"}
674 addAction(DNSSECRule(), DropAction())
675 """
676 def testAdvancedDNSSECDrop(self):
677 """
678 Advanced: DNSSEC Rule
679
680 """
681 name = 'dnssec.advanced.tests.powerdns.com.'
682 query = dns.message.make_query(name, 'A', 'IN')
683 doquery = dns.message.make_query(name, 'A', 'IN', want_dnssec=True)
684 response = dns.message.make_response(query)
685 rrset = dns.rrset.from_text(name,
686 3600,
687 dns.rdataclass.IN,
688 dns.rdatatype.A,
689 '127.0.0.1')
690 response.answer.append(rrset)
691
692 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
693 self.assertTrue(receivedQuery)
694 self.assertTrue(receivedResponse)
695 receivedQuery.id = query.id
696 self.assertEquals(query, receivedQuery)
697 self.assertEquals(response, receivedResponse)
698
699 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
700 self.assertTrue(receivedQuery)
701 self.assertTrue(receivedResponse)
702 receivedQuery.id = query.id
703 self.assertEquals(query, receivedQuery)
704 self.assertEquals(response, receivedResponse)
705
706 (_, receivedResponse) = self.sendUDPQuery(doquery, response)
707 self.assertEquals(receivedResponse, None)
708 (_, receivedResponse) = self.sendTCPQuery(doquery, response)
709 self.assertEquals(receivedResponse, None)
710
711 class TestAdvancedQClass(DNSDistTest):
712
713 _config_template = """
714 newServer{address="127.0.0.1:%s"}
715 addAction(QClassRule(DNSClass.CHAOS), DropAction())
716 """
717 def testAdvancedQClassChaosDrop(self):
718 """
719 Advanced: Drop QClass CHAOS
720
721 """
722 name = 'qclasschaos.advanced.tests.powerdns.com.'
723 query = dns.message.make_query(name, 'TXT', 'CHAOS')
724
725 (_, receivedResponse) = self.sendUDPQuery(query, response=None)
726 self.assertEquals(receivedResponse, None)
727 (_, receivedResponse) = self.sendTCPQuery(query, response=None)
728 self.assertEquals(receivedResponse, None)
729
730 def testAdvancedQClassINAllow(self):
731 """
732 Advanced: Allow QClass IN
733
734 """
735 name = 'qclassin.advanced.tests.powerdns.com.'
736 query = dns.message.make_query(name, 'A', 'IN')
737 response = dns.message.make_response(query)
738 rrset = dns.rrset.from_text(name,
739 3600,
740 dns.rdataclass.IN,
741 dns.rdatatype.A,
742 '127.0.0.1')
743 response.answer.append(rrset)
744
745 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
746 self.assertTrue(receivedQuery)
747 self.assertTrue(receivedResponse)
748 receivedQuery.id = query.id
749 self.assertEquals(query, receivedQuery)
750 self.assertEquals(response, receivedResponse)
751
752 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
753 self.assertTrue(receivedQuery)
754 self.assertTrue(receivedResponse)
755 receivedQuery.id = query.id
756 self.assertEquals(query, receivedQuery)
757 self.assertEquals(response, receivedResponse)
758
759 class TestAdvancedOpcode(DNSDistTest):
760
761 _config_template = """
762 newServer{address="127.0.0.1:%s"}
763 addAction(OpcodeRule(DNSOpcode.Notify), DropAction())
764 """
765 def testAdvancedOpcodeNotifyDrop(self):
766 """
767 Advanced: Drop Opcode NOTIFY
768
769 """
770 name = 'opcodenotify.advanced.tests.powerdns.com.'
771 query = dns.message.make_query(name, 'A', 'IN')
772 query.set_opcode(dns.opcode.NOTIFY)
773
774 (_, receivedResponse) = self.sendUDPQuery(query, response=None)
775 self.assertEquals(receivedResponse, None)
776 (_, receivedResponse) = self.sendTCPQuery(query, response=None)
777 self.assertEquals(receivedResponse, None)
778
779 def testAdvancedOpcodeUpdateINAllow(self):
780 """
781 Advanced: Allow Opcode UPDATE
782
783 """
784 name = 'opcodeupdate.advanced.tests.powerdns.com.'
785 query = dns.message.make_query(name, 'A', 'IN')
786 query.set_opcode(dns.opcode.UPDATE)
787 response = dns.message.make_response(query)
788 rrset = dns.rrset.from_text(name,
789 3600,
790 dns.rdataclass.IN,
791 dns.rdatatype.A,
792 '127.0.0.1')
793 response.answer.append(rrset)
794
795 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
796 self.assertTrue(receivedQuery)
797 self.assertTrue(receivedResponse)
798 receivedQuery.id = query.id
799 self.assertEquals(query, receivedQuery)
800 self.assertEquals(response, receivedResponse)
801
802 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
803 self.assertTrue(receivedQuery)
804 self.assertTrue(receivedResponse)
805 receivedQuery.id = query.id
806 self.assertEquals(query, receivedQuery)
807 self.assertEquals(response, receivedResponse)
808
809 class TestAdvancedNonTerminalRule(DNSDistTest):
810
811 _config_template = """
812 newServer{address="127.0.0.1:%s", pool="real"}
813 addAction(AllRule(), DisableValidationAction())
814 addAction(AllRule(), PoolAction("real"))
815 addAction(AllRule(), DropAction())
816 """
817 def testAdvancedNonTerminalRules(self):
818 """
819 Advanced: Non terminal rules
820
821 We check that DisableValidationAction() is applied
822 but does not stop the processing, then that
823 PoolAction() is applied _and_ stop the processing.
824 """
825 name = 'nonterminal.advanced.tests.powerdns.com.'
826 query = dns.message.make_query(name, 'A', 'IN')
827 expectedQuery = dns.message.make_query(name, 'A', 'IN')
828 expectedQuery.flags |= dns.flags.CD
829 response = dns.message.make_response(query)
830 rrset = dns.rrset.from_text(name,
831 3600,
832 dns.rdataclass.IN,
833 dns.rdatatype.A,
834 '192.0.2.1')
835 response.answer.append(rrset)
836
837 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
838 self.assertTrue(receivedQuery)
839 self.assertTrue(receivedResponse)
840 receivedQuery.id = expectedQuery.id
841 self.assertEquals(expectedQuery, receivedQuery)
842 self.assertEquals(response, receivedResponse)
843
844 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
845 self.assertTrue(receivedQuery)
846 self.assertTrue(receivedResponse)
847 receivedQuery.id = expectedQuery.id
848 self.assertEquals(expectedQuery, receivedQuery)
849 self.assertEquals(response, receivedResponse)
850
851 class TestAdvancedStringOnlyServer(DNSDistTest):
852
853 _config_template = """
854 newServer("127.0.0.1:%s")
855 """
856
857 def testAdvancedStringOnlyServer(self):
858 """
859 Advanced: "string-only" server is placed in the default pool
860 """
861 name = 'string-only-server.advanced.tests.powerdns.com.'
862 query = dns.message.make_query(name, 'A', 'IN')
863 response = dns.message.make_response(query)
864 rrset = dns.rrset.from_text(name,
865 3600,
866 dns.rdataclass.IN,
867 dns.rdatatype.A,
868 '192.0.2.1')
869 response.answer.append(rrset)
870
871 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
872 self.assertTrue(receivedQuery)
873 self.assertTrue(receivedResponse)
874 receivedQuery.id = query.id
875 self.assertEquals(query, receivedQuery)
876 self.assertEquals(response, receivedResponse)
877
878 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
879 self.assertTrue(receivedQuery)
880 self.assertTrue(receivedResponse)
881 receivedQuery.id = query.id
882 self.assertEquals(query, receivedQuery)
883 self.assertEquals(response, receivedResponse)
884
885 class TestAdvancedRestoreFlagsOnSelfResponse(DNSDistTest):
886
887 _config_template = """
888 addAction(AllRule(), DisableValidationAction())
889 addAction(AllRule(), SpoofAction("192.0.2.1"))
890 newServer{address="127.0.0.1:%s"}
891 """
892
893 def testAdvancedRestoreFlagsOnSpoofResponse(self):
894 """
895 Advanced: Restore flags on spoofed response
896
897 Send a query with CD flag cleared, dnsdist is
898 instructed to set it, then to spoof the response,
899 check that response has the flag cleared.
900 """
901 name = 'spoofed.restoreflags.advanced.tests.powerdns.com.'
902 query = dns.message.make_query(name, 'A', 'IN')
903 # dnsdist set RA = RD for spoofed responses
904 query.flags &= ~dns.flags.RD
905
906 response = dns.message.make_response(query)
907 rrset = dns.rrset.from_text(name,
908 60,
909 dns.rdataclass.IN,
910 dns.rdatatype.A,
911 '192.0.2.1')
912 response.answer.append(rrset)
913
914 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
915 self.assertTrue(receivedResponse)
916 self.assertEquals(response, receivedResponse)
917
918 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
919 self.assertTrue(receivedResponse)
920 self.assertEquals(response, receivedResponse)
921
922 class TestAdvancedQPS(DNSDistTest):
923
924 _config_template = """
925 addAction("qps.advanced.tests.powerdns.com", QPSAction(10))
926 newServer{address="127.0.0.1:%s"}
927 """
928
929 def testAdvancedQPSLimit(self):
930 """
931 Advanced: QPS Limit
932
933 Send queries to "qps.advanced.tests.powerdns.com."
934 check that dnsdist drops queries when the max QPS has been reached.
935 """
936 maxQPS = 10
937 name = 'qps.advanced.tests.powerdns.com.'
938 query = dns.message.make_query(name, 'A', 'IN')
939 response = dns.message.make_response(query)
940 rrset = dns.rrset.from_text(name,
941 60,
942 dns.rdataclass.IN,
943 dns.rdatatype.A,
944 '192.0.2.1')
945 response.answer.append(rrset)
946
947 for _ in range(maxQPS):
948 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
949 receivedQuery.id = query.id
950 self.assertEquals(query, receivedQuery)
951 self.assertEquals(response, receivedResponse)
952
953 # we should now be dropped
954 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
955 self.assertEquals(receivedResponse, None)
956
957 time.sleep(1)
958
959 # again, over TCP this time
960 for _ in range(maxQPS):
961 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
962 receivedQuery.id = query.id
963 self.assertEquals(query, receivedQuery)
964 self.assertEquals(response, receivedResponse)
965
966
967 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
968 self.assertEquals(receivedResponse, None)
969
970 class TestAdvancedQPSNone(DNSDistTest):
971
972 _config_template = """
973 addAction("qpsnone.advanced.tests.powerdns.com", QPSAction(100))
974 addAction(AllRule(), RCodeAction(dnsdist.REFUSED))
975 newServer{address="127.0.0.1:%s"}
976 """
977
978 def testAdvancedQPSNone(self):
979 """
980 Advanced: Not matching QPS returns None, not Allow
981
982 Send queries to "qps.advanced.tests.powerdns.com."
983 check that the rule returns None when the QPS has not been
984 reached, not Allow.
985 """
986 name = 'qpsnone.advanced.tests.powerdns.com.'
987 query = dns.message.make_query(name, 'A', 'IN')
988 expectedResponse = dns.message.make_response(query)
989 expectedResponse.set_rcode(dns.rcode.REFUSED)
990
991 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
992 self.assertEquals(receivedResponse, expectedResponse)
993
994 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
995 self.assertEquals(receivedResponse, expectedResponse)
996
997 class TestAdvancedNMGRule(DNSDistTest):
998
999 _config_template = """
1000 allowed = newNMG()
1001 allowed:addMask("192.0.2.1/32")
1002 addAction(NotRule(NetmaskGroupRule(allowed)), RCodeAction(dnsdist.REFUSED))
1003 newServer{address="127.0.0.1:%s"}
1004 """
1005
1006 def testAdvancedNMGRule(self):
1007 """
1008 Advanced: NMGRule should refuse our queries
1009
1010 Send queries to "nmgrule.advanced.tests.powerdns.com.",
1011 check that we are getting a REFUSED response.
1012 """
1013 name = 'nmgrule.advanced.tests.powerdns.com.'
1014 query = dns.message.make_query(name, 'A', 'IN')
1015 expectedResponse = dns.message.make_response(query)
1016 expectedResponse.set_rcode(dns.rcode.REFUSED)
1017
1018 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1019 self.assertEquals(receivedResponse, expectedResponse)
1020
1021 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
1022 self.assertEquals(receivedResponse, expectedResponse)
1023
1024 class TestDSTPortRule(DNSDistTest):
1025
1026 _config_params = ['_dnsDistPort', '_testServerPort']
1027 _config_template = """
1028 addAction(DSTPortRule(%d), RCodeAction(dnsdist.REFUSED))
1029 newServer{address="127.0.0.1:%s"}
1030 """
1031
1032 def testDSTPortRule(self):
1033 """
1034 Advanced: DSTPortRule should capture our queries
1035
1036 Send queries to "dstportrule.advanced.tests.powerdns.com.",
1037 check that we are getting a REFUSED response.
1038 """
1039
1040 name = 'dstportrule.advanced.tests.powerdns.com.'
1041 query = dns.message.make_query(name, 'A', 'IN')
1042 expectedResponse = dns.message.make_response(query)
1043 expectedResponse.set_rcode(dns.rcode.REFUSED)
1044
1045 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1046 self.assertEquals(receivedResponse, expectedResponse)
1047
1048 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
1049 self.assertEquals(receivedResponse, expectedResponse)
1050
1051 class TestAdvancedLabelsCountRule(DNSDistTest):
1052
1053 _config_template = """
1054 addAction(QNameLabelsCountRule(5,6), RCodeAction(dnsdist.REFUSED))
1055 newServer{address="127.0.0.1:%s"}
1056 """
1057
1058 def testAdvancedLabelsCountRule(self):
1059 """
1060 Advanced: QNameLabelsCountRule(5,6)
1061 """
1062 # 6 labels, we should be fine
1063 name = 'ok.labelscount.advanced.tests.powerdns.com.'
1064 query = dns.message.make_query(name, 'A', 'IN')
1065 response = dns.message.make_response(query)
1066 rrset = dns.rrset.from_text(name,
1067 3600,
1068 dns.rdataclass.IN,
1069 dns.rdatatype.A,
1070 '192.0.2.1')
1071 response.answer.append(rrset)
1072
1073 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
1074 self.assertTrue(receivedQuery)
1075 self.assertTrue(receivedResponse)
1076 receivedQuery.id = query.id
1077 self.assertEquals(query, receivedQuery)
1078 self.assertEquals(response, receivedResponse)
1079
1080 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
1081 self.assertTrue(receivedQuery)
1082 self.assertTrue(receivedResponse)
1083 receivedQuery.id = query.id
1084 self.assertEquals(query, receivedQuery)
1085 self.assertEquals(response, receivedResponse)
1086
1087 # more than 6 labels, the query should be refused
1088 name = 'not.ok.labelscount.advanced.tests.powerdns.com.'
1089 query = dns.message.make_query(name, 'A', 'IN')
1090 expectedResponse = dns.message.make_response(query)
1091 expectedResponse.set_rcode(dns.rcode.REFUSED)
1092
1093 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1094 self.assertEquals(receivedResponse, expectedResponse)
1095
1096 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
1097 self.assertEquals(receivedResponse, expectedResponse)
1098
1099 # less than 5 labels, the query should be refused
1100 name = 'labelscountadvanced.tests.powerdns.com.'
1101 query = dns.message.make_query(name, 'A', 'IN')
1102 expectedResponse = dns.message.make_response(query)
1103 expectedResponse.set_rcode(dns.rcode.REFUSED)
1104
1105 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1106 self.assertEquals(receivedResponse, expectedResponse)
1107
1108 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
1109 self.assertEquals(receivedResponse, expectedResponse)
1110
1111 class TestAdvancedWireLengthRule(DNSDistTest):
1112
1113 _config_template = """
1114 addAction(QNameWireLengthRule(54,56), RCodeAction(dnsdist.REFUSED))
1115 newServer{address="127.0.0.1:%s"}
1116 """
1117
1118 def testAdvancedWireLengthRule(self):
1119 """
1120 Advanced: QNameWireLengthRule(54,56)
1121 """
1122 name = 'longenough.qnamewirelength.advanced.tests.powerdns.com.'
1123 query = dns.message.make_query(name, 'A', 'IN')
1124 response = dns.message.make_response(query)
1125 rrset = dns.rrset.from_text(name,
1126 3600,
1127 dns.rdataclass.IN,
1128 dns.rdatatype.A,
1129 '192.0.2.1')
1130 response.answer.append(rrset)
1131
1132 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
1133 self.assertTrue(receivedQuery)
1134 self.assertTrue(receivedResponse)
1135 receivedQuery.id = query.id
1136 self.assertEquals(query, receivedQuery)
1137 self.assertEquals(response, receivedResponse)
1138
1139 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
1140 self.assertTrue(receivedQuery)
1141 self.assertTrue(receivedResponse)
1142 receivedQuery.id = query.id
1143 self.assertEquals(query, receivedQuery)
1144 self.assertEquals(response, receivedResponse)
1145
1146 # too short, the query should be refused
1147 name = 'short.qnamewirelength.advanced.tests.powerdns.com.'
1148 query = dns.message.make_query(name, 'A', 'IN')
1149 expectedResponse = dns.message.make_response(query)
1150 expectedResponse.set_rcode(dns.rcode.REFUSED)
1151
1152 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1153 self.assertEquals(receivedResponse, expectedResponse)
1154
1155 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
1156 self.assertEquals(receivedResponse, expectedResponse)
1157
1158 # too long, the query should be refused
1159 name = 'toolongtobevalid.qnamewirelength.advanced.tests.powerdns.com.'
1160 query = dns.message.make_query(name, 'A', 'IN')
1161 expectedResponse = dns.message.make_response(query)
1162 expectedResponse.set_rcode(dns.rcode.REFUSED)
1163
1164 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1165 self.assertEquals(receivedResponse, expectedResponse)
1166
1167 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
1168 self.assertEquals(receivedResponse, expectedResponse)
1169
1170 class TestAdvancedIncludeDir(DNSDistTest):
1171
1172 _config_template = """
1173 -- this directory contains a file allowing includedir.advanced.tests.powerdns.com.
1174 includeDirectory('test-include-dir')
1175 newServer{address="127.0.0.1:%s"}
1176 """
1177
1178 def testAdvancedIncludeDirAllowed(self):
1179 """
1180 Advanced: includeDirectory()
1181 """
1182 name = 'includedir.advanced.tests.powerdns.com.'
1183 query = dns.message.make_query(name, 'A', 'IN')
1184 response = dns.message.make_response(query)
1185 rrset = dns.rrset.from_text(name,
1186 3600,
1187 dns.rdataclass.IN,
1188 dns.rdatatype.A,
1189 '192.0.2.1')
1190 response.answer.append(rrset)
1191
1192 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
1193 self.assertTrue(receivedQuery)
1194 self.assertTrue(receivedResponse)
1195 receivedQuery.id = query.id
1196 self.assertEquals(query, receivedQuery)
1197 self.assertEquals(response, receivedResponse)
1198
1199 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
1200 self.assertTrue(receivedQuery)
1201 self.assertTrue(receivedResponse)
1202 receivedQuery.id = query.id
1203 self.assertEquals(query, receivedQuery)
1204 self.assertEquals(response, receivedResponse)
1205
1206 # this one should be refused
1207 name = 'notincludedir.advanced.tests.powerdns.com.'
1208 query = dns.message.make_query(name, 'A', 'IN')
1209 expectedResponse = dns.message.make_response(query)
1210 expectedResponse.set_rcode(dns.rcode.REFUSED)
1211
1212 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1213 self.assertEquals(receivedResponse, expectedResponse)
1214
1215 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
1216 self.assertEquals(receivedResponse, expectedResponse)
1217
1218 class TestAdvancedLuaDO(DNSDistTest):
1219
1220 _config_template = """
1221 function nxDOLua(dq)
1222 if dq:getDO() then
1223 return DNSAction.Nxdomain, ""
1224 end
1225 return DNSAction.None, ""
1226 end
1227 addAction(AllRule(), LuaAction(nxDOLua))
1228 newServer{address="127.0.0.1:%s"}
1229 """
1230
1231 def testNxDOViaLua(self):
1232 """
1233 Advanced: Nx DO queries via Lua
1234 """
1235 name = 'nxdo.advanced.tests.powerdns.com.'
1236 query = dns.message.make_query(name, 'A', 'IN')
1237 response = dns.message.make_response(query)
1238 rrset = dns.rrset.from_text(name,
1239 3600,
1240 dns.rdataclass.IN,
1241 dns.rdatatype.AAAA,
1242 '::1')
1243 response.answer.append(rrset)
1244 queryWithDO = dns.message.make_query(name, 'A', 'IN', want_dnssec=True)
1245 doResponse = dns.message.make_response(queryWithDO)
1246 doResponse.set_rcode(dns.rcode.NXDOMAIN)
1247
1248 # without DO
1249 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
1250 self.assertTrue(receivedQuery)
1251 self.assertTrue(receivedResponse)
1252 receivedQuery.id = query.id
1253 self.assertEquals(query, receivedQuery)
1254 self.assertEquals(receivedResponse, response)
1255
1256 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
1257 self.assertTrue(receivedQuery)
1258 self.assertTrue(receivedResponse)
1259 receivedQuery.id = query.id
1260 self.assertEquals(query, receivedQuery)
1261 self.assertEquals(receivedResponse, response)
1262
1263 # with DO
1264 (_, receivedResponse) = self.sendUDPQuery(queryWithDO, response=None, useQueue=False)
1265 self.assertTrue(receivedResponse)
1266 doResponse.id = receivedResponse.id
1267 self.assertEquals(receivedResponse, doResponse)
1268
1269 (_, receivedResponse) = self.sendTCPQuery(queryWithDO, response=None, useQueue=False)
1270 self.assertTrue(receivedResponse)
1271 doResponse.id = receivedResponse.id
1272 self.assertEquals(receivedResponse, doResponse)
1273
1274 class TestAdvancedLuaRefused(DNSDistTest):
1275
1276 _config_template = """
1277 function refuse(dq)
1278 return DNSAction.Refused, ""
1279 end
1280 addAction(AllRule(), LuaAction(refuse))
1281 newServer{address="127.0.0.1:%s"}
1282 """
1283
1284 def testRefusedViaLua(self):
1285 """
1286 Advanced: Refused via Lua
1287 """
1288 name = 'refused.advanced.tests.powerdns.com.'
1289 query = dns.message.make_query(name, 'A', 'IN')
1290 response = dns.message.make_response(query)
1291 rrset = dns.rrset.from_text(name,
1292 3600,
1293 dns.rdataclass.IN,
1294 dns.rdatatype.AAAA,
1295 '::1')
1296 response.answer.append(rrset)
1297 refusedResponse = dns.message.make_response(query)
1298 refusedResponse.set_rcode(dns.rcode.REFUSED)
1299
1300 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1301 self.assertTrue(receivedResponse)
1302 refusedResponse.id = receivedResponse.id
1303 self.assertEquals(receivedResponse, refusedResponse)
1304
1305 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
1306 self.assertTrue(receivedResponse)
1307 refusedResponse.id = receivedResponse.id
1308 self.assertEquals(receivedResponse, refusedResponse)
1309
1310 class TestAdvancedLuaActionReturnSyntax(DNSDistTest):
1311
1312 _config_template = """
1313 function refuse(dq)
1314 return DNSAction.Refused
1315 end
1316 addAction(AllRule(), LuaAction(refuse))
1317 newServer{address="127.0.0.1:%s"}
1318 """
1319
1320 def testRefusedWithEmptyRule(self):
1321 """
1322 Advanced: Short syntax for LuaAction return values
1323 """
1324 name = 'short.refused.advanced.tests.powerdns.com.'
1325 query = dns.message.make_query(name, 'A', 'IN')
1326 response = dns.message.make_response(query)
1327 rrset = dns.rrset.from_text(name,
1328 3600,
1329 dns.rdataclass.IN,
1330 dns.rdatatype.AAAA,
1331 '::1')
1332 response.answer.append(rrset)
1333 refusedResponse = dns.message.make_response(query)
1334 refusedResponse.set_rcode(dns.rcode.REFUSED)
1335
1336 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1337 self.assertTrue(receivedResponse)
1338 refusedResponse.id = receivedResponse.id
1339 self.assertEquals(receivedResponse, refusedResponse)
1340
1341 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
1342 self.assertTrue(receivedResponse)
1343 refusedResponse.id = receivedResponse.id
1344 self.assertEquals(receivedResponse, refusedResponse)
1345
1346 class TestAdvancedLuaTruncated(DNSDistTest):
1347
1348 _config_template = """
1349 function trunc(dq)
1350 if not dq.tcp then
1351 return DNSAction.Truncate, ""
1352 end
1353 return DNSAction.None, ""
1354 end
1355 addAction(AllRule(), LuaAction(trunc))
1356 newServer{address="127.0.0.1:%s"}
1357 """
1358
1359 def testTCViaLua(self):
1360 """
1361 Advanced: TC via Lua
1362 """
1363 name = 'tc.advanced.tests.powerdns.com.'
1364 query = dns.message.make_query(name, 'A', 'IN')
1365 response = dns.message.make_response(query)
1366 rrset = dns.rrset.from_text(name,
1367 3600,
1368 dns.rdataclass.IN,
1369 dns.rdatatype.AAAA,
1370 '::1')
1371 response.answer.append(rrset)
1372
1373 truncatedResponse = dns.message.make_response(query)
1374 truncatedResponse.flags |= dns.flags.TC
1375
1376 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1377 self.assertTrue(receivedResponse)
1378 truncatedResponse.id = receivedResponse.id
1379 self.assertEquals(receivedResponse, truncatedResponse)
1380
1381 # no truncation over TCP
1382 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
1383 self.assertTrue(receivedQuery)
1384 self.assertTrue(receivedResponse)
1385 receivedQuery.id = query.id
1386 self.assertEquals(query, receivedQuery)
1387 self.assertEquals(receivedResponse, response)
1388
1389 class TestStatNodeRespRingSince(DNSDistTest):
1390
1391 _consoleKey = DNSDistTest.generateConsoleKey()
1392 _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii')
1393 _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort']
1394 _config_template = """
1395 setKey("%s")
1396 controlSocket("127.0.0.1:%s")
1397 s1 = newServer{address="127.0.0.1:%s"}
1398 s1:setUp()
1399 function visitor(node, self, childstat)
1400 table.insert(nodesSeen, node.fullname)
1401 end
1402 """
1403
1404 def testStatNodeRespRingSince(self):
1405 """
1406 Advanced: StatNodeRespRing with optional since parameter
1407
1408 """
1409 name = 'statnodesince.advanced.tests.powerdns.com.'
1410 query = dns.message.make_query(name, 'A', 'IN')
1411 response = dns.message.make_response(query)
1412 rrset = dns.rrset.from_text(name,
1413 1,
1414 dns.rdataclass.IN,
1415 dns.rdatatype.A,
1416 '127.0.0.1')
1417 response.answer.append(rrset)
1418
1419 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
1420 self.assertTrue(receivedQuery)
1421 self.assertTrue(receivedResponse)
1422 receivedQuery.id = query.id
1423 self.assertEquals(query, receivedQuery)
1424 self.assertEquals(response, receivedResponse)
1425
1426 self.sendConsoleCommand("nodesSeen = {}")
1427 self.sendConsoleCommand("statNodeRespRing(visitor)")
1428 nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1429 nodes = nodes.strip("\n")
1430 self.assertEquals(nodes, """statnodesince.advanced.tests.powerdns.com.
1431 advanced.tests.powerdns.com.
1432 tests.powerdns.com.
1433 powerdns.com.
1434 com.""")
1435
1436 self.sendConsoleCommand("nodesSeen = {}")
1437 self.sendConsoleCommand("statNodeRespRing(visitor, 0)")
1438 nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1439 nodes = nodes.strip("\n")
1440 self.assertEquals(nodes, """statnodesince.advanced.tests.powerdns.com.
1441 advanced.tests.powerdns.com.
1442 tests.powerdns.com.
1443 powerdns.com.
1444 com.""")
1445
1446 time.sleep(5)
1447
1448 self.sendConsoleCommand("nodesSeen = {}")
1449 self.sendConsoleCommand("statNodeRespRing(visitor)")
1450 nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1451 nodes = nodes.strip("\n")
1452 self.assertEquals(nodes, """statnodesince.advanced.tests.powerdns.com.
1453 advanced.tests.powerdns.com.
1454 tests.powerdns.com.
1455 powerdns.com.
1456 com.""")
1457
1458 self.sendConsoleCommand("nodesSeen = {}")
1459 self.sendConsoleCommand("statNodeRespRing(visitor, 5)")
1460 nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1461 nodes = nodes.strip("\n")
1462 self.assertEquals(nodes, """""")
1463
1464 self.sendConsoleCommand("nodesSeen = {}")
1465 self.sendConsoleCommand("statNodeRespRing(visitor, 10)")
1466 nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1467 nodes = nodes.strip("\n")
1468 self.assertEquals(nodes, """statnodesince.advanced.tests.powerdns.com.
1469 advanced.tests.powerdns.com.
1470 tests.powerdns.com.
1471 powerdns.com.
1472 com.""")
1473
1474 class TestAdvancedRD(DNSDistTest):
1475
1476 _config_template = """
1477 addAction(RDRule(), RCodeAction(dnsdist.REFUSED))
1478 newServer{address="127.0.0.1:%s"}
1479 """
1480
1481 def testAdvancedRDRefused(self):
1482 """
1483 Advanced: RD query is refused
1484 """
1485 name = 'rd.advanced.tests.powerdns.com.'
1486 query = dns.message.make_query(name, 'A', 'IN')
1487 expectedResponse = dns.message.make_response(query)
1488 expectedResponse.set_rcode(dns.rcode.REFUSED)
1489
1490 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1491 self.assertEquals(receivedResponse, expectedResponse)
1492
1493 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
1494 self.assertEquals(receivedResponse, expectedResponse)
1495
1496 def testAdvancedNoRDAllowed(self):
1497 """
1498 Advanced: No-RD query is allowed
1499 """
1500 name = 'no-rd.advanced.tests.powerdns.com.'
1501 query = dns.message.make_query(name, 'A', 'IN')
1502 query.flags &= ~dns.flags.RD
1503 response = dns.message.make_response(query)
1504
1505 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
1506 receivedQuery.id = query.id
1507 self.assertEquals(receivedQuery, query)
1508 self.assertEquals(receivedResponse, response)
1509
1510 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
1511 receivedQuery.id = query.id
1512 self.assertEquals(receivedQuery, query)
1513 self.assertEquals(receivedResponse, response)
1514
1515 class TestAdvancedGetLocalPort(DNSDistTest):
1516
1517 _config_template = """
1518 function answerBasedOnLocalPort(dq)
1519 local port = dq.localaddr:getPort()
1520 return DNSAction.Spoof, "port-was-"..port..".local-port.advanced.tests.powerdns.com."
1521 end
1522 addAction("local-port.advanced.tests.powerdns.com.", LuaAction(answerBasedOnLocalPort))
1523 newServer{address="127.0.0.1:%s"}
1524 """
1525
1526 def testAdvancedGetLocalPort(self):
1527 """
1528 Advanced: Return CNAME containing the local port
1529 """
1530 name = 'local-port.advanced.tests.powerdns.com.'
1531 query = dns.message.make_query(name, 'A', 'IN')
1532 # dnsdist set RA = RD for spoofed responses
1533 query.flags &= ~dns.flags.RD
1534
1535 response = dns.message.make_response(query)
1536 rrset = dns.rrset.from_text(name,
1537 60,
1538 dns.rdataclass.IN,
1539 dns.rdatatype.CNAME,
1540 'port-was-{}.local-port.advanced.tests.powerdns.com.'.format(self._dnsDistPort))
1541 response.answer.append(rrset)
1542
1543 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1544 self.assertEquals(receivedResponse, response)
1545
1546 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
1547 self.assertEquals(receivedResponse, response)
1548
1549 class TestAdvancedGetLocalPortOnAnyBind(DNSDistTest):
1550
1551 _config_template = """
1552 function answerBasedOnLocalPort(dq)
1553 local port = dq.localaddr:getPort()
1554 return DNSAction.Spoof, "port-was-"..port..".local-port-any.advanced.tests.powerdns.com."
1555 end
1556 addAction("local-port-any.advanced.tests.powerdns.com.", LuaAction(answerBasedOnLocalPort))
1557 newServer{address="127.0.0.1:%s"}
1558 """
1559 _dnsDistListeningAddr = "0.0.0.0"
1560
1561 def testAdvancedGetLocalPortOnAnyBind(self):
1562 """
1563 Advanced: Return CNAME containing the local port for an ANY bind
1564 """
1565 name = 'local-port-any.advanced.tests.powerdns.com.'
1566 query = dns.message.make_query(name, 'A', 'IN')
1567 # dnsdist set RA = RD for spoofed responses
1568 query.flags &= ~dns.flags.RD
1569
1570 response = dns.message.make_response(query)
1571 rrset = dns.rrset.from_text(name,
1572 60,
1573 dns.rdataclass.IN,
1574 dns.rdatatype.CNAME,
1575 'port-was-{}.local-port-any.advanced.tests.powerdns.com.'.format(self._dnsDistPort))
1576 response.answer.append(rrset)
1577
1578 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
1579 self.assertEquals(receivedResponse, response)
1580
1581 (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
1582 self.assertEquals(receivedResponse, response)
1583
1584 class TestAdvancedLuaTempFailureTTL(DNSDistTest):
1585
1586 _config_template = """
1587 function testAction(dq)
1588 if dq.tempFailureTTL ~= nil then
1589 return DNSAction.Spoof, "initially.not.nil.but." + dq.tempFailureTTL + ".tests.powerdns.com."
1590 end
1591 dq.tempFailureTTL = 30
1592 if dq.tempFailureTTL ~= 30 then
1593 return DNSAction.Spoof, "after.set.not.expected.value.but." + dq.tempFailureTTL + ".tests.powerdns.com."
1594 end
1595 dq.tempFailureTTL = nil
1596 if dq.tempFailureTTL ~= nil then
1597 return DNSAction.Spoof, "after.unset.not.nil.but." + dq.tempFailureTTL + ".tests.powerdns.com."
1598 end
1599 return DNSAction.None, ""
1600 end
1601 addAction(AllRule(), LuaAction(testAction))
1602 newServer{address="127.0.0.1:%s"}
1603 """
1604
1605 def testTempFailureTTLBinding(self):
1606 """
1607 Exercise dq.tempFailureTTL Lua binding
1608 """
1609 name = 'tempfailurettlbinding.advanced.tests.powerdns.com.'
1610 query = dns.message.make_query(name, 'A', 'IN')
1611 response = dns.message.make_response(query)
1612 rrset = dns.rrset.from_text(name,
1613 3600,
1614 dns.rdataclass.IN,
1615 dns.rdatatype.AAAA,
1616 '::1')
1617 response.answer.append(rrset)
1618
1619 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
1620 self.assertTrue(receivedQuery)
1621 self.assertTrue(receivedResponse)
1622 receivedQuery.id = query.id
1623 self.assertEquals(query, receivedQuery)
1624 self.assertEquals(receivedResponse, response)