]>
git.ipfire.org Git - thirdparty/pdns.git/blob - regression-tests.dnsdist/test_Advanced.py
3 from datetime
import datetime
, timedelta
8 import clientsubnetoption
9 from dnsdisttests
import DNSDistTest
11 class TestAdvancedAllow(DNSDistTest
):
13 _config_template
= """
14 addAction(AllRule(), NoneAction())
15 addAction(makeRule("allowed.advanced.tests.powerdns.com."), AllowAction())
16 addAction(AllRule(), DropAction())
17 newServer{address="127.0.0.1:%s"}
20 def testAdvancedAllow(self
):
22 Advanced: Allowed qname is not dropped
24 A query for allowed.advanced.tests.powerdns.com. should be allowed
25 while others should be dropped.
27 name
= 'allowed.advanced.tests.powerdns.com.'
28 query
= dns
.message
.make_query(name
, 'A', 'IN')
29 response
= dns
.message
.make_response(query
)
30 rrset
= dns
.rrset
.from_text(name
,
35 response
.answer
.append(rrset
)
37 for method
in ("sendUDPQuery", "sendTCPQuery"):
38 sender
= getattr(self
, method
)
39 (receivedQuery
, receivedResponse
) = sender(query
, response
)
40 self
.assertTrue(receivedQuery
)
41 self
.assertTrue(receivedResponse
)
42 receivedQuery
.id = query
.id
43 self
.assertEquals(query
, receivedQuery
)
44 self
.assertEquals(response
, receivedResponse
)
46 def testAdvancedAllowDropped(self
):
48 Advanced: Not allowed qname is dropped
50 A query for notallowed.advanced.tests.powerdns.com. should be dropped.
52 name
= 'notallowed.advanced.tests.powerdns.com.'
53 query
= dns
.message
.make_query(name
, 'A', 'IN')
55 for method
in ("sendUDPQuery", "sendTCPQuery"):
56 sender
= getattr(self
, method
)
57 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
59 class TestAdvancedFixupCase(DNSDistTest
):
61 _config_template
= """
64 newServer{address="127.0.0.1:%s"}
67 def testAdvancedFixupCase(self
):
71 Send a query with lower and upper chars,
72 make the backend return a lowercase version,
73 check that dnsdist fixes the response.
75 name
= 'fiXuPCasE.advanced.tests.powerdns.com.'
76 query
= dns
.message
.make_query(name
, 'A', 'IN')
77 lowercasequery
= dns
.message
.make_query(name
.lower(), 'A', 'IN')
78 response
= dns
.message
.make_response(lowercasequery
)
79 expectedResponse
= dns
.message
.make_response(query
)
80 rrset
= dns
.rrset
.from_text(name
,
85 response
.answer
.append(rrset
)
86 expectedResponse
.answer
.append(rrset
)
88 for method
in ("sendUDPQuery", "sendTCPQuery"):
89 sender
= getattr(self
, method
)
90 (receivedQuery
, receivedResponse
) = sender(query
, response
)
91 self
.assertTrue(receivedQuery
)
92 self
.assertTrue(receivedResponse
)
93 receivedQuery
.id = query
.id
94 self
.assertEquals(query
, receivedQuery
)
95 self
.assertEquals(expectedResponse
, receivedResponse
)
97 class TestAdvancedRemoveRD(DNSDistTest
):
99 _config_template
= """
100 addAction("norecurse.advanced.tests.powerdns.com.", NoRecurseAction())
101 newServer{address="127.0.0.1:%s"}
104 def testAdvancedNoRD(self
):
108 Send a query with RD,
109 check that dnsdist clears the RD flag.
111 name
= 'norecurse.advanced.tests.powerdns.com.'
112 query
= dns
.message
.make_query(name
, 'A', 'IN')
113 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
114 expectedQuery
.flags
&= ~dns
.flags
.RD
116 response
= dns
.message
.make_response(query
)
117 rrset
= dns
.rrset
.from_text(name
,
122 response
.answer
.append(rrset
)
124 for method
in ("sendUDPQuery", "sendTCPQuery"):
125 sender
= getattr(self
, method
)
126 (receivedQuery
, receivedResponse
) = sender(query
, response
)
127 self
.assertTrue(receivedQuery
)
128 self
.assertTrue(receivedResponse
)
129 receivedQuery
.id = expectedQuery
.id
130 self
.assertEquals(expectedQuery
, receivedQuery
)
131 self
.assertEquals(response
, receivedResponse
)
133 def testAdvancedKeepRD(self
):
135 Advanced: No RD canary
137 Send a query with RD for a canary domain,
138 check that dnsdist does not clear the RD flag.
140 name
= 'keeprecurse.advanced.tests.powerdns.com.'
141 query
= dns
.message
.make_query(name
, 'A', 'IN')
143 response
= dns
.message
.make_response(query
)
144 rrset
= dns
.rrset
.from_text(name
,
149 response
.answer
.append(rrset
)
151 for method
in ("sendUDPQuery", "sendTCPQuery"):
152 sender
= getattr(self
, method
)
153 (receivedQuery
, receivedResponse
) = sender(query
, response
)
154 self
.assertTrue(receivedQuery
)
155 self
.assertTrue(receivedResponse
)
156 receivedQuery
.id = query
.id
157 self
.assertEquals(query
, receivedQuery
)
158 self
.assertEquals(response
, receivedResponse
)
160 class TestAdvancedAddCD(DNSDistTest
):
162 _config_template
= """
163 addAction("setcd.advanced.tests.powerdns.com.", DisableValidationAction())
164 addAction(makeRule("setcdviaaction.advanced.tests.powerdns.com."), DisableValidationAction())
165 newServer{address="127.0.0.1:%s"}
168 def testAdvancedSetCD(self
):
172 Send a query with CD cleared,
173 check that dnsdist set the CD flag.
175 name
= 'setcd.advanced.tests.powerdns.com.'
176 query
= dns
.message
.make_query(name
, 'A', 'IN')
177 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
178 expectedQuery
.flags |
= dns
.flags
.CD
180 response
= dns
.message
.make_response(query
)
181 rrset
= dns
.rrset
.from_text(name
,
186 response
.answer
.append(rrset
)
188 for method
in ("sendUDPQuery", "sendTCPQuery"):
189 sender
= getattr(self
, method
)
190 (receivedQuery
, receivedResponse
) = sender(query
, response
)
191 self
.assertTrue(receivedQuery
)
192 self
.assertTrue(receivedResponse
)
193 receivedQuery
.id = expectedQuery
.id
194 self
.assertEquals(expectedQuery
, receivedQuery
)
195 self
.assertEquals(response
, receivedResponse
)
197 def testAdvancedSetCDViaAction(self
):
199 Advanced: Set CD via Action
201 Send a query with CD cleared,
202 check that dnsdist set the CD flag.
204 name
= 'setcdviaaction.advanced.tests.powerdns.com.'
205 query
= dns
.message
.make_query(name
, 'A', 'IN')
206 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
207 expectedQuery
.flags |
= dns
.flags
.CD
209 response
= dns
.message
.make_response(query
)
210 rrset
= dns
.rrset
.from_text(name
,
215 response
.answer
.append(rrset
)
217 for method
in ("sendUDPQuery", "sendTCPQuery"):
218 sender
= getattr(self
, method
)
219 (receivedQuery
, receivedResponse
) = sender(query
, response
)
220 self
.assertTrue(receivedQuery
)
221 self
.assertTrue(receivedResponse
)
222 receivedQuery
.id = expectedQuery
.id
223 self
.assertEquals(expectedQuery
, receivedQuery
)
224 self
.assertEquals(response
, receivedResponse
)
226 def testAdvancedKeepNoCD(self
):
228 Advanced: Preserve CD canary
230 Send a query without CD for a canary domain,
231 check that dnsdist does not set the CD flag.
233 name
= 'keepnocd.advanced.tests.powerdns.com.'
234 query
= dns
.message
.make_query(name
, 'A', 'IN')
236 response
= dns
.message
.make_response(query
)
237 rrset
= dns
.rrset
.from_text(name
,
242 response
.answer
.append(rrset
)
244 for method
in ("sendUDPQuery", "sendTCPQuery"):
245 sender
= getattr(self
, method
)
246 (receivedQuery
, receivedResponse
) = sender(query
, response
)
247 self
.assertTrue(receivedQuery
)
248 self
.assertTrue(receivedResponse
)
249 receivedQuery
.id = query
.id
250 self
.assertEquals(query
, receivedQuery
)
251 self
.assertEquals(response
, receivedResponse
)
253 class TestAdvancedClearRD(DNSDistTest
):
255 _config_template
= """
256 addAction("clearrd.advanced.tests.powerdns.com.", NoRecurseAction())
257 addAction(makeRule("clearrdviaaction.advanced.tests.powerdns.com."), NoRecurseAction())
258 newServer{address="127.0.0.1:%s"}
261 def testAdvancedClearRD(self
):
265 Send a query with RD set,
266 check that dnsdist clears the RD flag.
268 name
= 'clearrd.advanced.tests.powerdns.com.'
269 query
= dns
.message
.make_query(name
, 'A', 'IN')
270 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
271 expectedQuery
.flags
&= ~dns
.flags
.RD
273 response
= dns
.message
.make_response(query
)
274 rrset
= dns
.rrset
.from_text(name
,
279 response
.answer
.append(rrset
)
281 for method
in ("sendUDPQuery", "sendTCPQuery"):
282 sender
= getattr(self
, method
)
283 (receivedQuery
, receivedResponse
) = sender(query
, response
)
284 self
.assertTrue(receivedQuery
)
285 self
.assertTrue(receivedResponse
)
286 receivedQuery
.id = expectedQuery
.id
287 self
.assertEquals(expectedQuery
, receivedQuery
)
288 self
.assertEquals(response
, receivedResponse
)
290 def testAdvancedClearRDViaAction(self
):
292 Advanced: Clear RD via Action
294 Send a query with RD set,
295 check that dnsdist clears the RD flag.
297 name
= 'clearrdviaaction.advanced.tests.powerdns.com.'
298 query
= dns
.message
.make_query(name
, 'A', 'IN')
299 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
300 expectedQuery
.flags
&= ~dns
.flags
.RD
302 response
= dns
.message
.make_response(query
)
303 rrset
= dns
.rrset
.from_text(name
,
308 response
.answer
.append(rrset
)
310 for method
in ("sendUDPQuery", "sendTCPQuery"):
311 sender
= getattr(self
, method
)
312 (receivedQuery
, receivedResponse
) = sender(query
, response
)
313 self
.assertTrue(receivedQuery
)
314 self
.assertTrue(receivedResponse
)
315 receivedQuery
.id = expectedQuery
.id
316 self
.assertEquals(expectedQuery
, receivedQuery
)
317 self
.assertEquals(response
, receivedResponse
)
319 def testAdvancedKeepRD(self
):
321 Advanced: Preserve RD canary
323 Send a query with RD for a canary domain,
324 check that dnsdist does not clear the RD flag.
326 name
= 'keeprd.advanced.tests.powerdns.com.'
327 query
= dns
.message
.make_query(name
, 'A', 'IN')
329 response
= dns
.message
.make_response(query
)
330 rrset
= dns
.rrset
.from_text(name
,
335 response
.answer
.append(rrset
)
337 for method
in ("sendUDPQuery", "sendTCPQuery"):
338 sender
= getattr(self
, method
)
339 (receivedQuery
, receivedResponse
) = sender(query
, response
)
340 self
.assertTrue(receivedQuery
)
341 self
.assertTrue(receivedResponse
)
342 receivedQuery
.id = query
.id
343 self
.assertEquals(query
, receivedQuery
)
344 self
.assertEquals(response
, receivedResponse
)
347 class TestAdvancedACL(DNSDistTest
):
349 _config_template
= """
350 newServer{address="127.0.0.1:%s"}
352 _acl
= ['192.0.2.1/32']
354 def testACLBlocked(self
):
356 Advanced: ACL blocked
358 Send an A query to "tests.powerdns.com.",
359 we expect no response since 127.0.0.1 is not on the
362 name
= 'tests.powerdns.com.'
363 query
= dns
.message
.make_query(name
, 'A', 'IN')
365 for method
in ("sendUDPQuery", "sendTCPQuery"):
366 sender
= getattr(self
, method
)
367 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
368 self
.assertEquals(receivedResponse
, None)
370 class TestAdvancedDelay(DNSDistTest
):
372 _config_template
= """
373 addAction(AllRule(), DelayAction(1000))
374 newServer{address="127.0.0.1:%s"}
377 def testDelayed(self
):
381 Send an A query to "tests.powerdns.com.",
382 check that the response delay is longer than 1000 ms
383 over UDP, less than that over TCP.
385 name
= 'tests.powerdns.com.'
386 query
= dns
.message
.make_query(name
, 'A', 'IN')
387 response
= dns
.message
.make_response(query
)
388 rrset
= dns
.rrset
.from_text(name
,
393 response
.answer
.append(rrset
)
395 begin
= datetime
.now()
396 (receivedQuery
, receivedResponse
) = self
.sendUDPQuery(query
, response
)
398 receivedQuery
.id = query
.id
399 self
.assertEquals(query
, receivedQuery
)
400 self
.assertEquals(response
, receivedResponse
)
401 self
.assertTrue((end
- begin
) > timedelta(0, 1))
403 begin
= datetime
.now()
404 (receivedQuery
, receivedResponse
) = self
.sendTCPQuery(query
, response
)
406 receivedQuery
.id = query
.id
407 self
.assertEquals(query
, receivedQuery
)
408 self
.assertEquals(response
, receivedResponse
)
409 self
.assertTrue((end
- begin
) < timedelta(0, 1))
412 class TestAdvancedTruncateAnyAndTCP(DNSDistTest
):
414 _config_template
= """
416 addAction(AndRule({QTypeRule("ANY"), TCPRule(true)}), TCAction())
417 newServer{address="127.0.0.1:%s"}
419 def testTruncateAnyOverTCP(self
):
421 Advanced: Truncate ANY over TCP
423 Send an ANY query to "anytruncatetcp.advanced.tests.powerdns.com.",
424 should be truncated over TCP, not over UDP (yes, it makes no sense,
427 name
= 'anytruncatetcp.advanced.tests.powerdns.com.'
428 query
= dns
.message
.make_query(name
, 'ANY', 'IN')
429 # dnsdist sets RA = RD for TC responses
430 query
.flags
&= ~dns
.flags
.RD
432 response
= dns
.message
.make_response(query
)
433 rrset
= dns
.rrset
.from_text(name
,
439 response
.answer
.append(rrset
)
441 (receivedQuery
, receivedResponse
) = self
.sendUDPQuery(query
, response
)
442 self
.assertTrue(receivedQuery
)
443 self
.assertTrue(receivedResponse
)
444 receivedQuery
.id = query
.id
445 self
.assertEquals(query
, receivedQuery
)
446 self
.assertEquals(receivedResponse
, response
)
448 expectedResponse
= dns
.message
.make_response(query
)
449 expectedResponse
.flags |
= dns
.flags
.TC
451 (_
, receivedResponse
) = self
.sendTCPQuery(query
, response
=None, useQueue
=False)
452 self
.assertEquals(receivedResponse
, expectedResponse
)
454 class TestAdvancedAndNot(DNSDistTest
):
456 _config_template
= """
457 addAction(AndRule({NotRule(QTypeRule("A")), TCPRule(false)}), RCodeAction(DNSRCode.NOTIMP))
458 newServer{address="127.0.0.1:%s"}
460 def testAOverUDPReturnsNotImplementedCanary(self
):
462 Advanced: !A && UDP canary
464 dnsdist is configured to reply 'not implemented' for query
465 over UDP AND !qtype A.
466 We send an A query over UDP and TCP, and check that the
469 name
= 'andnot.advanced.tests.powerdns.com.'
470 query
= dns
.message
.make_query(name
, 'A', 'IN')
471 response
= dns
.message
.make_response(query
)
472 rrset
= dns
.rrset
.from_text(name
,
477 response
.answer
.append(rrset
)
479 for method
in ("sendUDPQuery", "sendTCPQuery"):
480 sender
= getattr(self
, method
)
481 (receivedQuery
, receivedResponse
) = sender(query
, response
)
482 self
.assertTrue(receivedQuery
)
483 self
.assertTrue(receivedResponse
)
484 receivedQuery
.id = query
.id
485 self
.assertEquals(query
, receivedQuery
)
486 self
.assertEquals(receivedResponse
, response
)
488 def testAOverUDPReturnsNotImplemented(self
):
492 dnsdist is configured to reply 'not implemented' for query
493 over UDP AND !qtype A.
494 We send a TXT query over UDP and TCP, and check that the
495 response is OK for TCP and 'not implemented' for UDP.
497 name
= 'andnot.advanced.tests.powerdns.com.'
498 query
= dns
.message
.make_query(name
, 'TXT', 'IN')
500 expectedResponse
= dns
.message
.make_response(query
)
501 expectedResponse
.set_rcode(dns
.rcode
.NOTIMP
)
503 (_
, receivedResponse
) = self
.sendUDPQuery(query
, response
=None, useQueue
=False)
504 self
.assertEquals(receivedResponse
, expectedResponse
)
506 response
= dns
.message
.make_response(query
)
507 rrset
= dns
.rrset
.from_text(name
,
511 'nothing to see here')
512 response
.answer
.append(rrset
)
514 (receivedQuery
, receivedResponse
) = self
.sendTCPQuery(query
, response
)
515 self
.assertTrue(receivedQuery
)
516 self
.assertTrue(receivedResponse
)
517 receivedQuery
.id = query
.id
518 self
.assertEquals(query
, receivedQuery
)
519 self
.assertEquals(receivedResponse
, response
)
521 class TestAdvancedOr(DNSDistTest
):
523 _config_template
= """
524 addAction(OrRule({QTypeRule("A"), TCPRule(false)}), RCodeAction(DNSRCode.NOTIMP))
525 newServer{address="127.0.0.1:%s"}
527 def testAAAAOverUDPReturnsNotImplemented(self
):
529 Advanced: A || UDP: AAAA
531 dnsdist is configured to reply 'not implemented' for query
533 We send an AAAA query over UDP and TCP, and check that the
534 response is 'not implemented' for UDP and OK for TCP.
536 name
= 'aorudp.advanced.tests.powerdns.com.'
537 query
= dns
.message
.make_query(name
, 'AAAA', 'IN')
538 response
= dns
.message
.make_response(query
)
539 rrset
= dns
.rrset
.from_text(name
,
544 response
.answer
.append(rrset
)
546 expectedResponse
= dns
.message
.make_response(query
)
547 expectedResponse
.set_rcode(dns
.rcode
.NOTIMP
)
549 (_
, receivedResponse
) = self
.sendUDPQuery(query
, response
=None, useQueue
=False)
550 self
.assertEquals(receivedResponse
, expectedResponse
)
552 (receivedQuery
, receivedResponse
) = self
.sendTCPQuery(query
, response
)
553 self
.assertTrue(receivedQuery
)
554 self
.assertTrue(receivedResponse
)
555 receivedQuery
.id = query
.id
556 self
.assertEquals(query
, receivedQuery
)
557 self
.assertEquals(receivedResponse
, response
)
559 def testAOverUDPReturnsNotImplemented(self
):
561 Advanced: A || UDP: A
563 dnsdist is configured to reply 'not implemented' for query
565 We send an A query over UDP and TCP, and check that the
566 response is 'not implemented' for both.
568 name
= 'aorudp.advanced.tests.powerdns.com.'
569 query
= dns
.message
.make_query(name
, 'A', 'IN')
571 expectedResponse
= dns
.message
.make_response(query
)
572 expectedResponse
.set_rcode(dns
.rcode
.NOTIMP
)
574 for method
in ("sendUDPQuery", "sendTCPQuery"):
575 sender
= getattr(self
, method
)
576 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
577 self
.assertEquals(receivedResponse
, expectedResponse
)
580 class TestAdvancedLogAction(DNSDistTest
):
582 _config_template
= """
583 newServer{address="127.0.0.1:%s"}
584 addAction(AllRule(), LogAction("dnsdist.log", false))
586 def testAdvancedLogAction(self
):
588 Advanced: Log all queries
592 name
= 'logaction.advanced.tests.powerdns.com.'
593 query
= dns
.message
.make_query(name
, 'A', 'IN')
594 response
= dns
.message
.make_response(query
)
595 rrset
= dns
.rrset
.from_text(name
,
600 response
.answer
.append(rrset
)
602 for _
in range(count
):
603 (receivedQuery
, receivedResponse
) = self
.sendUDPQuery(query
, response
)
604 self
.assertTrue(receivedQuery
)
605 self
.assertTrue(receivedResponse
)
606 receivedQuery
.id = query
.id
607 self
.assertEquals(query
, receivedQuery
)
608 self
.assertEquals(response
, receivedResponse
)
610 self
.assertTrue(os
.path
.isfile('dnsdist.log'))
611 self
.assertTrue(os
.stat('dnsdist.log').st_size
> 0)
613 class TestAdvancedDNSSEC(DNSDistTest
):
615 _config_template
= """
616 newServer{address="127.0.0.1:%s"}
617 addAction(DNSSECRule(), DropAction())
619 def testAdvancedDNSSECDrop(self
):
621 Advanced: DNSSEC Rule
624 name
= 'dnssec.advanced.tests.powerdns.com.'
625 query
= dns
.message
.make_query(name
, 'A', 'IN')
626 doquery
= dns
.message
.make_query(name
, 'A', 'IN', want_dnssec
=True)
627 response
= dns
.message
.make_response(query
)
628 rrset
= dns
.rrset
.from_text(name
,
633 response
.answer
.append(rrset
)
635 for method
in ("sendUDPQuery", "sendTCPQuery"):
636 sender
= getattr(self
, method
)
637 (receivedQuery
, receivedResponse
) = sender(query
, response
)
638 self
.assertTrue(receivedQuery
)
639 self
.assertTrue(receivedResponse
)
640 receivedQuery
.id = query
.id
641 self
.assertEquals(query
, receivedQuery
)
642 self
.assertEquals(response
, receivedResponse
)
644 for method
in ("sendUDPQuery", "sendTCPQuery"):
645 sender
= getattr(self
, method
)
646 (_
, receivedResponse
) = sender(doquery
, response
)
647 self
.assertEquals(receivedResponse
, None)
649 class TestAdvancedQClass(DNSDistTest
):
651 _config_template
= """
652 newServer{address="127.0.0.1:%s"}
653 addAction(QClassRule(DNSClass.CHAOS), DropAction())
655 def testAdvancedQClassChaosDrop(self
):
657 Advanced: Drop QClass CHAOS
660 name
= 'qclasschaos.advanced.tests.powerdns.com.'
661 query
= dns
.message
.make_query(name
, 'TXT', 'CHAOS')
663 for method
in ("sendUDPQuery", "sendTCPQuery"):
664 sender
= getattr(self
, method
)
665 (_
, receivedResponse
) = sender(query
, response
=None)
666 self
.assertEquals(receivedResponse
, None)
668 def testAdvancedQClassINAllow(self
):
670 Advanced: Allow QClass IN
673 name
= 'qclassin.advanced.tests.powerdns.com.'
674 query
= dns
.message
.make_query(name
, 'A', 'IN')
675 response
= dns
.message
.make_response(query
)
676 rrset
= dns
.rrset
.from_text(name
,
681 response
.answer
.append(rrset
)
683 for method
in ("sendUDPQuery", "sendTCPQuery"):
684 sender
= getattr(self
, method
)
685 (receivedQuery
, receivedResponse
) = sender(query
, response
)
686 self
.assertTrue(receivedQuery
)
687 self
.assertTrue(receivedResponse
)
688 receivedQuery
.id = query
.id
689 self
.assertEquals(query
, receivedQuery
)
690 self
.assertEquals(response
, receivedResponse
)
692 class TestAdvancedOpcode(DNSDistTest
):
694 _config_template
= """
695 newServer{address="127.0.0.1:%s"}
696 addAction(OpcodeRule(DNSOpcode.Notify), DropAction())
698 def testAdvancedOpcodeNotifyDrop(self
):
700 Advanced: Drop Opcode NOTIFY
703 name
= 'opcodenotify.advanced.tests.powerdns.com.'
704 query
= dns
.message
.make_query(name
, 'A', 'IN')
705 query
.set_opcode(dns
.opcode
.NOTIFY
)
707 for method
in ("sendUDPQuery", "sendTCPQuery"):
708 sender
= getattr(self
, method
)
709 (_
, receivedResponse
) = sender(query
, response
=None)
710 self
.assertEquals(receivedResponse
, None)
712 def testAdvancedOpcodeUpdateINAllow(self
):
714 Advanced: Allow Opcode UPDATE
717 name
= 'opcodeupdate.advanced.tests.powerdns.com.'
718 query
= dns
.message
.make_query(name
, 'A', 'IN')
719 query
.set_opcode(dns
.opcode
.UPDATE
)
720 response
= dns
.message
.make_response(query
)
721 rrset
= dns
.rrset
.from_text(name
,
726 response
.answer
.append(rrset
)
728 for method
in ("sendUDPQuery", "sendTCPQuery"):
729 sender
= getattr(self
, method
)
730 (receivedQuery
, receivedResponse
) = sender(query
, response
)
731 self
.assertTrue(receivedQuery
)
732 self
.assertTrue(receivedResponse
)
733 receivedQuery
.id = query
.id
734 self
.assertEquals(query
, receivedQuery
)
735 self
.assertEquals(response
, receivedResponse
)
737 class TestAdvancedNonTerminalRule(DNSDistTest
):
739 _config_template
= """
740 newServer{address="127.0.0.1:%s", pool="real"}
741 addAction(AllRule(), DisableValidationAction())
742 addAction(AllRule(), PoolAction("real"))
743 addAction(AllRule(), DropAction())
745 def testAdvancedNonTerminalRules(self
):
747 Advanced: Non terminal rules
749 We check that DisableValidationAction() is applied
750 but does not stop the processing, then that
751 PoolAction() is applied _and_ stop the processing.
753 name
= 'nonterminal.advanced.tests.powerdns.com.'
754 query
= dns
.message
.make_query(name
, 'A', 'IN')
755 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
756 expectedQuery
.flags |
= dns
.flags
.CD
757 response
= dns
.message
.make_response(query
)
758 rrset
= dns
.rrset
.from_text(name
,
763 response
.answer
.append(rrset
)
765 for method
in ("sendUDPQuery", "sendTCPQuery"):
766 sender
= getattr(self
, method
)
767 (receivedQuery
, receivedResponse
) = sender(query
, response
)
768 self
.assertTrue(receivedQuery
)
769 self
.assertTrue(receivedResponse
)
770 receivedQuery
.id = expectedQuery
.id
771 self
.assertEquals(expectedQuery
, receivedQuery
)
772 self
.assertEquals(response
, receivedResponse
)
774 class TestAdvancedStringOnlyServer(DNSDistTest
):
776 _config_template
= """
777 newServer("127.0.0.1:%s")
780 def testAdvancedStringOnlyServer(self
):
782 Advanced: "string-only" server is placed in the default pool
784 name
= 'string-only-server.advanced.tests.powerdns.com.'
785 query
= dns
.message
.make_query(name
, 'A', 'IN')
786 response
= dns
.message
.make_response(query
)
787 rrset
= dns
.rrset
.from_text(name
,
792 response
.answer
.append(rrset
)
794 for method
in ("sendUDPQuery", "sendTCPQuery"):
795 sender
= getattr(self
, method
)
796 (receivedQuery
, receivedResponse
) = sender(query
, response
)
797 self
.assertTrue(receivedQuery
)
798 self
.assertTrue(receivedResponse
)
799 receivedQuery
.id = query
.id
800 self
.assertEquals(query
, receivedQuery
)
801 self
.assertEquals(response
, receivedResponse
)
803 class TestAdvancedRestoreFlagsOnSelfResponse(DNSDistTest
):
805 _config_template
= """
806 addAction(AllRule(), DisableValidationAction())
807 addAction(AllRule(), SpoofAction("192.0.2.1"))
808 newServer{address="127.0.0.1:%s"}
811 def testAdvancedRestoreFlagsOnSpoofResponse(self
):
813 Advanced: Restore flags on spoofed response
815 Send a query with CD flag cleared, dnsdist is
816 instructed to set it, then to spoof the response,
817 check that response has the flag cleared.
819 name
= 'spoofed.restoreflags.advanced.tests.powerdns.com.'
820 query
= dns
.message
.make_query(name
, 'A', 'IN')
821 # dnsdist set RA = RD for spoofed responses
822 query
.flags
&= ~dns
.flags
.RD
824 response
= dns
.message
.make_response(query
)
825 rrset
= dns
.rrset
.from_text(name
,
830 response
.answer
.append(rrset
)
832 for method
in ("sendUDPQuery", "sendTCPQuery"):
833 sender
= getattr(self
, method
)
834 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
835 self
.assertTrue(receivedResponse
)
836 self
.assertEquals(response
, receivedResponse
)
838 class TestAdvancedQPS(DNSDistTest
):
840 _config_template
= """
841 addAction("qps.advanced.tests.powerdns.com", QPSAction(10))
842 newServer{address="127.0.0.1:%s"}
845 def testAdvancedQPSLimit(self
):
849 Send queries to "qps.advanced.tests.powerdns.com."
850 check that dnsdist drops queries when the max QPS has been reached.
853 name
= 'qps.advanced.tests.powerdns.com.'
854 query
= dns
.message
.make_query(name
, 'A', 'IN')
855 response
= dns
.message
.make_response(query
)
856 rrset
= dns
.rrset
.from_text(name
,
861 response
.answer
.append(rrset
)
863 for _
in range(maxQPS
):
864 (receivedQuery
, receivedResponse
) = self
.sendUDPQuery(query
, response
)
865 receivedQuery
.id = query
.id
866 self
.assertEquals(query
, receivedQuery
)
867 self
.assertEquals(response
, receivedResponse
)
869 # we should now be dropped
870 (_
, receivedResponse
) = self
.sendUDPQuery(query
, response
=None, useQueue
=False)
871 self
.assertEquals(receivedResponse
, None)
875 # again, over TCP this time
876 for _
in range(maxQPS
):
877 (receivedQuery
, receivedResponse
) = self
.sendTCPQuery(query
, response
)
878 receivedQuery
.id = query
.id
879 self
.assertEquals(query
, receivedQuery
)
880 self
.assertEquals(response
, receivedResponse
)
883 (_
, receivedResponse
) = self
.sendTCPQuery(query
, response
=None, useQueue
=False)
884 self
.assertEquals(receivedResponse
, None)
886 class TestAdvancedQPSNone(DNSDistTest
):
888 _config_template
= """
889 addAction("qpsnone.advanced.tests.powerdns.com", QPSAction(100))
890 addAction(AllRule(), RCodeAction(DNSRCode.REFUSED))
891 newServer{address="127.0.0.1:%s"}
894 def testAdvancedQPSNone(self
):
896 Advanced: Not matching QPS returns None, not Allow
898 Send queries to "qps.advanced.tests.powerdns.com."
899 check that the rule returns None when the QPS has not been
902 name
= 'qpsnone.advanced.tests.powerdns.com.'
903 query
= dns
.message
.make_query(name
, 'A', 'IN')
904 expectedResponse
= dns
.message
.make_response(query
)
905 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
907 for method
in ("sendUDPQuery", "sendTCPQuery"):
908 sender
= getattr(self
, method
)
909 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
910 self
.assertEquals(receivedResponse
, expectedResponse
)
912 class TestAdvancedNMGRule(DNSDistTest
):
914 _config_template
= """
916 allowed:addMask("192.0.2.1/32")
917 addAction(NotRule(NetmaskGroupRule(allowed)), RCodeAction(DNSRCode.REFUSED))
918 newServer{address="127.0.0.1:%s"}
921 def testAdvancedNMGRule(self
):
923 Advanced: NMGRule should refuse our queries
925 Send queries to "nmgrule.advanced.tests.powerdns.com.",
926 check that we are getting a REFUSED response.
928 name
= 'nmgrule.advanced.tests.powerdns.com.'
929 query
= dns
.message
.make_query(name
, 'A', 'IN')
930 expectedResponse
= dns
.message
.make_response(query
)
931 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
933 for method
in ("sendUDPQuery", "sendTCPQuery"):
934 sender
= getattr(self
, method
)
935 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
936 self
.assertEquals(receivedResponse
, expectedResponse
)
938 class TestDSTPortRule(DNSDistTest
):
940 _config_params
= ['_dnsDistPort', '_testServerPort']
941 _config_template
= """
942 addAction(DSTPortRule(%d), RCodeAction(DNSRCode.REFUSED))
943 newServer{address="127.0.0.1:%s"}
946 def testDSTPortRule(self
):
948 Advanced: DSTPortRule should capture our queries
950 Send queries to "dstportrule.advanced.tests.powerdns.com.",
951 check that we are getting a REFUSED response.
954 name
= 'dstportrule.advanced.tests.powerdns.com.'
955 query
= dns
.message
.make_query(name
, 'A', 'IN')
956 expectedResponse
= dns
.message
.make_response(query
)
957 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
959 for method
in ("sendUDPQuery", "sendTCPQuery"):
960 sender
= getattr(self
, method
)
961 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
962 self
.assertEquals(receivedResponse
, expectedResponse
)
964 class TestAdvancedLabelsCountRule(DNSDistTest
):
966 _config_template
= """
967 addAction(QNameLabelsCountRule(5,6), RCodeAction(DNSRCode.REFUSED))
968 newServer{address="127.0.0.1:%s"}
971 def testAdvancedLabelsCountRule(self
):
973 Advanced: QNameLabelsCountRule(5,6)
975 # 6 labels, we should be fine
976 name
= 'ok.labelscount.advanced.tests.powerdns.com.'
977 query
= dns
.message
.make_query(name
, 'A', 'IN')
978 response
= dns
.message
.make_response(query
)
979 rrset
= dns
.rrset
.from_text(name
,
984 response
.answer
.append(rrset
)
986 for method
in ("sendUDPQuery", "sendTCPQuery"):
987 sender
= getattr(self
, method
)
988 (receivedQuery
, receivedResponse
) = sender(query
, response
)
989 self
.assertTrue(receivedQuery
)
990 self
.assertTrue(receivedResponse
)
991 receivedQuery
.id = query
.id
992 self
.assertEquals(query
, receivedQuery
)
993 self
.assertEquals(response
, receivedResponse
)
995 # more than 6 labels, the query should be refused
996 name
= 'not.ok.labelscount.advanced.tests.powerdns.com.'
997 query
= dns
.message
.make_query(name
, 'A', 'IN')
998 expectedResponse
= dns
.message
.make_response(query
)
999 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1001 for method
in ("sendUDPQuery", "sendTCPQuery"):
1002 sender
= getattr(self
, method
)
1003 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1004 self
.assertEquals(receivedResponse
, expectedResponse
)
1006 # less than 5 labels, the query should be refused
1007 name
= 'labelscountadvanced.tests.powerdns.com.'
1008 query
= dns
.message
.make_query(name
, 'A', 'IN')
1009 expectedResponse
= dns
.message
.make_response(query
)
1010 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1012 for method
in ("sendUDPQuery", "sendTCPQuery"):
1013 sender
= getattr(self
, method
)
1014 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1015 self
.assertEquals(receivedResponse
, expectedResponse
)
1017 class TestAdvancedWireLengthRule(DNSDistTest
):
1019 _config_template
= """
1020 addAction(QNameWireLengthRule(54,56), RCodeAction(DNSRCode.REFUSED))
1021 newServer{address="127.0.0.1:%s"}
1024 def testAdvancedWireLengthRule(self
):
1026 Advanced: QNameWireLengthRule(54,56)
1028 name
= 'longenough.qnamewirelength.advanced.tests.powerdns.com.'
1029 query
= dns
.message
.make_query(name
, 'A', 'IN')
1030 response
= dns
.message
.make_response(query
)
1031 rrset
= dns
.rrset
.from_text(name
,
1036 response
.answer
.append(rrset
)
1038 for method
in ("sendUDPQuery", "sendTCPQuery"):
1039 sender
= getattr(self
, method
)
1040 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1041 self
.assertTrue(receivedQuery
)
1042 self
.assertTrue(receivedResponse
)
1043 receivedQuery
.id = query
.id
1044 self
.assertEquals(query
, receivedQuery
)
1045 self
.assertEquals(response
, receivedResponse
)
1047 # too short, the query should be refused
1048 name
= 'short.qnamewirelength.advanced.tests.powerdns.com.'
1049 query
= dns
.message
.make_query(name
, 'A', 'IN')
1050 expectedResponse
= dns
.message
.make_response(query
)
1051 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1053 for method
in ("sendUDPQuery", "sendTCPQuery"):
1054 sender
= getattr(self
, method
)
1055 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1056 self
.assertEquals(receivedResponse
, expectedResponse
)
1058 # too long, the query should be refused
1059 name
= 'toolongtobevalid.qnamewirelength.advanced.tests.powerdns.com.'
1060 query
= dns
.message
.make_query(name
, 'A', 'IN')
1061 expectedResponse
= dns
.message
.make_response(query
)
1062 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1064 for method
in ("sendUDPQuery", "sendTCPQuery"):
1065 sender
= getattr(self
, method
)
1066 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1067 self
.assertEquals(receivedResponse
, expectedResponse
)
1069 class TestAdvancedIncludeDir(DNSDistTest
):
1071 _config_template
= """
1072 -- this directory contains a file allowing includedir.advanced.tests.powerdns.com.
1073 includeDirectory('test-include-dir')
1074 newServer{address="127.0.0.1:%s"}
1077 def testAdvancedIncludeDirAllowed(self
):
1079 Advanced: includeDirectory()
1081 name
= 'includedir.advanced.tests.powerdns.com.'
1082 query
= dns
.message
.make_query(name
, 'A', 'IN')
1083 response
= dns
.message
.make_response(query
)
1084 rrset
= dns
.rrset
.from_text(name
,
1089 response
.answer
.append(rrset
)
1091 for method
in ("sendUDPQuery", "sendTCPQuery"):
1092 sender
= getattr(self
, method
)
1093 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1094 self
.assertTrue(receivedQuery
)
1095 self
.assertTrue(receivedResponse
)
1096 receivedQuery
.id = query
.id
1097 self
.assertEquals(query
, receivedQuery
)
1098 self
.assertEquals(response
, receivedResponse
)
1100 # this one should be refused
1101 name
= 'notincludedir.advanced.tests.powerdns.com.'
1102 query
= dns
.message
.make_query(name
, 'A', 'IN')
1103 expectedResponse
= dns
.message
.make_response(query
)
1104 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1106 for method
in ("sendUDPQuery", "sendTCPQuery"):
1107 sender
= getattr(self
, method
)
1108 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1109 self
.assertEquals(receivedResponse
, expectedResponse
)
1111 class TestAdvancedLuaDO(DNSDistTest
):
1113 _config_template
= """
1114 function nxDOLua(dq)
1116 return DNSAction.Nxdomain, ""
1118 return DNSAction.None, ""
1120 addAction(AllRule(), LuaAction(nxDOLua))
1121 newServer{address="127.0.0.1:%s"}
1124 def testNxDOViaLua(self
):
1126 Advanced: Nx DO queries via Lua
1128 name
= 'nxdo.advanced.tests.powerdns.com.'
1129 query
= dns
.message
.make_query(name
, 'A', 'IN')
1130 response
= dns
.message
.make_response(query
)
1131 rrset
= dns
.rrset
.from_text(name
,
1136 response
.answer
.append(rrset
)
1137 queryWithDO
= dns
.message
.make_query(name
, 'A', 'IN', want_dnssec
=True)
1138 doResponse
= dns
.message
.make_response(queryWithDO
)
1139 doResponse
.set_rcode(dns
.rcode
.NXDOMAIN
)
1142 for method
in ("sendUDPQuery", "sendTCPQuery"):
1143 sender
= getattr(self
, method
)
1144 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1145 self
.assertTrue(receivedQuery
)
1146 self
.assertTrue(receivedResponse
)
1147 receivedQuery
.id = query
.id
1148 self
.assertEquals(query
, receivedQuery
)
1149 self
.assertEquals(receivedResponse
, response
)
1152 for method
in ("sendUDPQuery", "sendTCPQuery"):
1153 sender
= getattr(self
, method
)
1154 (_
, receivedResponse
) = sender(queryWithDO
, response
=None, useQueue
=False)
1155 self
.assertTrue(receivedResponse
)
1156 doResponse
.id = receivedResponse
.id
1157 self
.assertEquals(receivedResponse
, doResponse
)
1159 class TestAdvancedLuaRefused(DNSDistTest
):
1161 _config_template
= """
1163 return DNSAction.Refused, ""
1165 addAction(AllRule(), LuaAction(refuse))
1166 newServer{address="127.0.0.1:%s"}
1169 def testRefusedViaLua(self
):
1171 Advanced: Refused via Lua
1173 name
= 'refused.advanced.tests.powerdns.com.'
1174 query
= dns
.message
.make_query(name
, 'A', 'IN')
1175 response
= dns
.message
.make_response(query
)
1176 rrset
= dns
.rrset
.from_text(name
,
1181 response
.answer
.append(rrset
)
1182 refusedResponse
= dns
.message
.make_response(query
)
1183 refusedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1185 for method
in ("sendUDPQuery", "sendTCPQuery"):
1186 sender
= getattr(self
, method
)
1187 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1188 self
.assertTrue(receivedResponse
)
1189 refusedResponse
.id = receivedResponse
.id
1190 self
.assertEquals(receivedResponse
, refusedResponse
)
1192 class TestAdvancedLuaActionReturnSyntax(DNSDistTest
):
1194 _config_template
= """
1196 return DNSAction.Refused
1198 addAction(AllRule(), LuaAction(refuse))
1199 newServer{address="127.0.0.1:%s"}
1202 def testRefusedWithEmptyRule(self
):
1204 Advanced: Short syntax for LuaAction return values
1206 name
= 'short.refused.advanced.tests.powerdns.com.'
1207 query
= dns
.message
.make_query(name
, 'A', 'IN')
1208 response
= dns
.message
.make_response(query
)
1209 rrset
= dns
.rrset
.from_text(name
,
1214 response
.answer
.append(rrset
)
1215 refusedResponse
= dns
.message
.make_response(query
)
1216 refusedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1218 for method
in ("sendUDPQuery", "sendTCPQuery"):
1219 sender
= getattr(self
, method
)
1220 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1221 self
.assertTrue(receivedResponse
)
1222 refusedResponse
.id = receivedResponse
.id
1223 self
.assertEquals(receivedResponse
, refusedResponse
)
1225 class TestAdvancedLuaTruncated(DNSDistTest
):
1227 _config_template
= """
1230 return DNSAction.Truncate, ""
1232 return DNSAction.None, ""
1234 addAction(AllRule(), LuaAction(trunc))
1235 newServer{address="127.0.0.1:%s"}
1238 def testTCViaLua(self
):
1240 Advanced: TC via Lua
1242 name
= 'tc.advanced.tests.powerdns.com.'
1243 query
= dns
.message
.make_query(name
, 'A', 'IN')
1244 # dnsdist sets RA = RD for TC responses
1245 query
.flags
&= ~dns
.flags
.RD
1246 response
= dns
.message
.make_response(query
)
1247 rrset
= dns
.rrset
.from_text(name
,
1252 response
.answer
.append(rrset
)
1254 truncatedResponse
= dns
.message
.make_response(query
)
1255 truncatedResponse
.flags |
= dns
.flags
.TC
1257 (_
, receivedResponse
) = self
.sendUDPQuery(query
, response
=None, useQueue
=False)
1258 self
.assertTrue(receivedResponse
)
1259 truncatedResponse
.id = receivedResponse
.id
1260 self
.assertEquals(receivedResponse
, truncatedResponse
)
1262 # no truncation over TCP
1263 (receivedQuery
, receivedResponse
) = self
.sendTCPQuery(query
, response
)
1264 self
.assertTrue(receivedQuery
)
1265 self
.assertTrue(receivedResponse
)
1266 receivedQuery
.id = query
.id
1267 self
.assertEquals(query
, receivedQuery
)
1268 self
.assertEquals(receivedResponse
, response
)
1270 class TestStatNodeRespRingSince(DNSDistTest
):
1272 _consoleKey
= DNSDistTest
.generateConsoleKey()
1273 _consoleKeyB64
= base64
.b64encode(_consoleKey
).decode('ascii')
1274 _config_params
= ['_consoleKeyB64', '_consolePort', '_testServerPort']
1275 _config_template
= """
1277 controlSocket("127.0.0.1:%s")
1278 s1 = newServer{address="127.0.0.1:%s"}
1280 function visitor(node, self, childstat)
1281 table.insert(nodesSeen, node.fullname)
1285 def testStatNodeRespRingSince(self
):
1287 Advanced: StatNodeRespRing with optional since parameter
1290 name
= 'statnodesince.advanced.tests.powerdns.com.'
1291 query
= dns
.message
.make_query(name
, 'A', 'IN')
1292 response
= dns
.message
.make_response(query
)
1293 rrset
= dns
.rrset
.from_text(name
,
1298 response
.answer
.append(rrset
)
1300 (receivedQuery
, receivedResponse
) = self
.sendUDPQuery(query
, response
)
1301 self
.assertTrue(receivedQuery
)
1302 self
.assertTrue(receivedResponse
)
1303 receivedQuery
.id = query
.id
1304 self
.assertEquals(query
, receivedQuery
)
1305 self
.assertEquals(response
, receivedResponse
)
1307 self
.sendConsoleCommand("nodesSeen = {}")
1308 self
.sendConsoleCommand("statNodeRespRing(visitor)")
1309 nodes
= self
.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1310 nodes
= nodes
.strip("\n")
1311 self
.assertEquals(nodes
, """statnodesince.advanced.tests.powerdns.com.
1312 advanced.tests.powerdns.com.
1317 self
.sendConsoleCommand("nodesSeen = {}")
1318 self
.sendConsoleCommand("statNodeRespRing(visitor, 0)")
1319 nodes
= self
.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1320 nodes
= nodes
.strip("\n")
1321 self
.assertEquals(nodes
, """statnodesince.advanced.tests.powerdns.com.
1322 advanced.tests.powerdns.com.
1329 self
.sendConsoleCommand("nodesSeen = {}")
1330 self
.sendConsoleCommand("statNodeRespRing(visitor)")
1331 nodes
= self
.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1332 nodes
= nodes
.strip("\n")
1333 self
.assertEquals(nodes
, """statnodesince.advanced.tests.powerdns.com.
1334 advanced.tests.powerdns.com.
1339 self
.sendConsoleCommand("nodesSeen = {}")
1340 self
.sendConsoleCommand("statNodeRespRing(visitor, 5)")
1341 nodes
= self
.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1342 nodes
= nodes
.strip("\n")
1343 self
.assertEquals(nodes
, """""")
1345 self
.sendConsoleCommand("nodesSeen = {}")
1346 self
.sendConsoleCommand("statNodeRespRing(visitor, 10)")
1347 nodes
= self
.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1348 nodes
= nodes
.strip("\n")
1349 self
.assertEquals(nodes
, """statnodesince.advanced.tests.powerdns.com.
1350 advanced.tests.powerdns.com.
1355 class TestAdvancedRD(DNSDistTest
):
1357 _config_template
= """
1358 addAction(RDRule(), RCodeAction(DNSRCode.REFUSED))
1359 newServer{address="127.0.0.1:%s"}
1362 def testAdvancedRDRefused(self
):
1364 Advanced: RD query is refused
1366 name
= 'rd.advanced.tests.powerdns.com.'
1367 query
= dns
.message
.make_query(name
, 'A', 'IN')
1368 expectedResponse
= dns
.message
.make_response(query
)
1369 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1371 for method
in ("sendUDPQuery", "sendTCPQuery"):
1372 sender
= getattr(self
, method
)
1373 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1374 self
.assertEquals(receivedResponse
, expectedResponse
)
1376 def testAdvancedNoRDAllowed(self
):
1378 Advanced: No-RD query is allowed
1380 name
= 'no-rd.advanced.tests.powerdns.com.'
1381 query
= dns
.message
.make_query(name
, 'A', 'IN')
1382 query
.flags
&= ~dns
.flags
.RD
1383 response
= dns
.message
.make_response(query
)
1385 for method
in ("sendUDPQuery", "sendTCPQuery"):
1386 sender
= getattr(self
, method
)
1387 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1388 receivedQuery
.id = query
.id
1389 self
.assertEquals(receivedQuery
, query
)
1390 self
.assertEquals(receivedResponse
, response
)
1392 class TestAdvancedGetLocalPort(DNSDistTest
):
1394 _config_template
= """
1395 function answerBasedOnLocalPort(dq)
1396 local port = dq.localaddr:getPort()
1397 return DNSAction.Spoof, "port-was-"..port..".local-port.advanced.tests.powerdns.com."
1399 addAction("local-port.advanced.tests.powerdns.com.", LuaAction(answerBasedOnLocalPort))
1400 newServer{address="127.0.0.1:%s"}
1403 def testAdvancedGetLocalPort(self
):
1405 Advanced: Return CNAME containing the local port
1407 name
= 'local-port.advanced.tests.powerdns.com.'
1408 query
= dns
.message
.make_query(name
, 'A', 'IN')
1409 # dnsdist set RA = RD for spoofed responses
1410 query
.flags
&= ~dns
.flags
.RD
1412 response
= dns
.message
.make_response(query
)
1413 rrset
= dns
.rrset
.from_text(name
,
1416 dns
.rdatatype
.CNAME
,
1417 'port-was-{}.local-port.advanced.tests.powerdns.com.'.format(self
._dnsDistPort
))
1418 response
.answer
.append(rrset
)
1420 for method
in ("sendUDPQuery", "sendTCPQuery"):
1421 sender
= getattr(self
, method
)
1422 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1423 self
.assertEquals(receivedResponse
, response
)
1425 class TestAdvancedGetLocalPortOnAnyBind(DNSDistTest
):
1427 _config_template
= """
1428 function answerBasedOnLocalPort(dq)
1429 local port = dq.localaddr:getPort()
1430 return DNSAction.Spoof, "port-was-"..port..".local-port-any.advanced.tests.powerdns.com."
1432 addAction("local-port-any.advanced.tests.powerdns.com.", LuaAction(answerBasedOnLocalPort))
1433 newServer{address="127.0.0.1:%s"}
1435 _dnsDistListeningAddr
= "0.0.0.0"
1437 def testAdvancedGetLocalPortOnAnyBind(self
):
1439 Advanced: Return CNAME containing the local port for an ANY bind
1441 name
= 'local-port-any.advanced.tests.powerdns.com.'
1442 query
= dns
.message
.make_query(name
, 'A', 'IN')
1443 # dnsdist set RA = RD for spoofed responses
1444 query
.flags
&= ~dns
.flags
.RD
1446 response
= dns
.message
.make_response(query
)
1447 rrset
= dns
.rrset
.from_text(name
,
1450 dns
.rdatatype
.CNAME
,
1451 'port-was-{}.local-port-any.advanced.tests.powerdns.com.'.format(self
._dnsDistPort
))
1452 response
.answer
.append(rrset
)
1454 for method
in ("sendUDPQuery", "sendTCPQuery"):
1455 sender
= getattr(self
, method
)
1456 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1457 self
.assertEquals(receivedResponse
, response
)
1459 class TestAdvancedGetLocalAddressOnAnyBind(DNSDistTest
):
1461 _config_template
= """
1462 function answerBasedOnLocalAddress(dq)
1463 local dest = dq.localaddr:toString()
1464 local i, j = string.find(dest, "[0-9.]+")
1465 local addr = string.sub(dest, i, j)
1466 local dashAddr = string.gsub(addr, "[.]", "-")
1467 return DNSAction.Spoof, "address-was-"..dashAddr..".local-address-any.advanced.tests.powerdns.com."
1469 addAction("local-address-any.advanced.tests.powerdns.com.", LuaAction(answerBasedOnLocalAddress))
1470 newServer{address="127.0.0.1:%s"}
1472 _dnsDistListeningAddr
= "0.0.0.0"
1474 def testAdvancedGetLocalAddressOnAnyBind(self
):
1476 Advanced: Return CNAME containing the local address for an ANY bind
1478 name
= 'local-address-any.advanced.tests.powerdns.com.'
1479 query
= dns
.message
.make_query(name
, 'A', 'IN')
1480 # dnsdist set RA = RD for spoofed responses
1481 query
.flags
&= ~dns
.flags
.RD
1483 response
= dns
.message
.make_response(query
)
1484 rrset
= dns
.rrset
.from_text(name
,
1487 dns
.rdatatype
.CNAME
,
1488 'address-was-127-0-0-1.local-address-any.advanced.tests.powerdns.com.')
1489 response
.answer
.append(rrset
)
1491 for method
in ("sendUDPQuery", "sendTCPQuery"):
1492 sender
= getattr(self
, method
)
1493 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1494 self
.assertEquals(receivedResponse
, response
)
1496 class TestAdvancedLuaTempFailureTTL(DNSDistTest
):
1498 _config_template
= """
1499 function testAction(dq)
1500 if dq.tempFailureTTL ~= nil then
1501 return DNSAction.Spoof, "initially.not.nil.but." + dq.tempFailureTTL + ".tests.powerdns.com."
1503 dq.tempFailureTTL = 30
1504 if dq.tempFailureTTL ~= 30 then
1505 return DNSAction.Spoof, "after.set.not.expected.value.but." + dq.tempFailureTTL + ".tests.powerdns.com."
1507 dq.tempFailureTTL = nil
1508 if dq.tempFailureTTL ~= nil then
1509 return DNSAction.Spoof, "after.unset.not.nil.but." + dq.tempFailureTTL + ".tests.powerdns.com."
1511 return DNSAction.None, ""
1513 addAction(AllRule(), LuaAction(testAction))
1514 newServer{address="127.0.0.1:%s"}
1517 def testTempFailureTTLBinding(self
):
1519 Advanced: Exercise dq.tempFailureTTL Lua binding
1521 name
= 'tempfailurettlbinding.advanced.tests.powerdns.com.'
1522 query
= dns
.message
.make_query(name
, 'A', 'IN')
1523 response
= dns
.message
.make_response(query
)
1524 rrset
= dns
.rrset
.from_text(name
,
1529 response
.answer
.append(rrset
)
1531 for method
in ("sendUDPQuery", "sendTCPQuery"):
1532 sender
= getattr(self
, method
)
1533 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1534 self
.assertTrue(receivedQuery
)
1535 self
.assertTrue(receivedResponse
)
1536 receivedQuery
.id = query
.id
1537 self
.assertEquals(query
, receivedQuery
)
1538 self
.assertEquals(receivedResponse
, response
)
1540 class TestAdvancedEDNSOptionRule(DNSDistTest
):
1542 _config_template
= """
1543 newServer{address="127.0.0.1:%s"}
1544 addAction(EDNSOptionRule(EDNSOptionCode.ECS), DropAction())
1547 def testDropped(self
):
1549 Advanced: A question with ECS is dropped
1552 name
= 'ednsoptionrule.advanced.tests.powerdns.com.'
1554 ecso
= clientsubnetoption
.ClientSubnetOption('127.0.0.1', 24)
1555 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=True, options
=[ecso
], payload
=512)
1557 for method
in ("sendUDPQuery", "sendTCPQuery"):
1558 sender
= getattr(self
, method
)
1559 (_
, receivedResponse
) = sender(query
, response
=None)
1560 self
.assertEquals(receivedResponse
, None)
1562 def testReplied(self
):
1564 Advanced: A question without ECS is answered
1567 name
= 'ednsoptionrule.advanced.tests.powerdns.com.'
1570 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=True, options
=[], payload
=512)
1571 response
= dns
.message
.make_response(query
)
1573 for method
in ("sendUDPQuery", "sendTCPQuery"):
1574 sender
= getattr(self
, method
)
1575 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1576 self
.assertTrue(receivedQuery
)
1577 self
.assertTrue(receivedResponse
)
1579 receivedQuery
.id = query
.id
1580 self
.assertEquals(query
, receivedQuery
)
1581 self
.assertEquals(receivedResponse
, response
)
1583 # and with no EDNS at all
1584 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=False)
1585 response
= dns
.message
.make_response(query
)
1587 for method
in ("sendUDPQuery", "sendTCPQuery"):
1588 sender
= getattr(self
, method
)
1589 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1590 self
.assertTrue(receivedQuery
)
1591 self
.assertTrue(receivedResponse
)
1593 receivedQuery
.id = query
.id
1594 self
.assertEquals(query
, receivedQuery
)
1595 self
.assertEquals(receivedResponse
, response
)
1597 class TestAdvancedAllowHeaderOnly(DNSDistTest
):
1599 _config_template
= """
1600 newServer{address="127.0.0.1:%s"}
1601 setAllowEmptyResponse(true)
1604 def testHeaderOnlyRefused(self
):
1606 Advanced: Header-only refused response
1608 name
= 'header-only-refused-response.advanced.tests.powerdns.com.'
1609 query
= dns
.message
.make_query(name
, 'A', 'IN')
1610 response
= dns
.message
.make_response(query
)
1611 response
.set_rcode(dns
.rcode
.REFUSED
)
1612 response
.question
= []
1614 for method
in ("sendUDPQuery", "sendTCPQuery"):
1615 sender
= getattr(self
, method
)
1616 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1617 self
.assertTrue(receivedQuery
)
1618 receivedQuery
.id = query
.id
1619 self
.assertEquals(query
, receivedQuery
)
1620 self
.assertEquals(receivedResponse
, response
)
1622 def testHeaderOnlyNoErrorResponse(self
):
1624 Advanced: Header-only NoError response should be allowed
1626 name
= 'header-only-noerror-response.advanced.tests.powerdns.com.'
1627 query
= dns
.message
.make_query(name
, 'A', 'IN')
1628 response
= dns
.message
.make_response(query
)
1629 response
.question
= []
1631 for method
in ("sendUDPQuery", "sendTCPQuery"):
1632 sender
= getattr(self
, method
)
1633 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1634 self
.assertTrue(receivedQuery
)
1635 receivedQuery
.id = query
.id
1636 self
.assertEquals(query
, receivedQuery
)
1637 self
.assertEquals(receivedResponse
, response
)
1639 def testHeaderOnlyNXDResponse(self
):
1641 Advanced: Header-only NXD response should be allowed
1643 name
= 'header-only-nxd-response.advanced.tests.powerdns.com.'
1644 query
= dns
.message
.make_query(name
, 'A', 'IN')
1645 response
= dns
.message
.make_response(query
)
1646 response
.set_rcode(dns
.rcode
.NXDOMAIN
)
1647 response
.question
= []
1649 for method
in ("sendUDPQuery", "sendTCPQuery"):
1650 sender
= getattr(self
, method
)
1651 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1652 self
.assertTrue(receivedQuery
)
1653 receivedQuery
.id = query
.id
1654 self
.assertEquals(query
, receivedQuery
)
1655 self
.assertEquals(receivedResponse
, response
)
1657 class TestAdvancedEDNSVersionRule(DNSDistTest
):
1659 _config_template
= """
1660 newServer{address="127.0.0.1:%s"}
1661 addAction(EDNSVersionRule(0), ERCodeAction(DNSRCode.BADVERS))
1664 def testDropped(self
):
1666 Advanced: A question with ECS version larger than 0 is dropped
1669 name
= 'ednsversionrule.advanced.tests.powerdns.com.'
1671 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=1)
1672 expectedResponse
= dns
.message
.make_response(query
)
1673 expectedResponse
.set_rcode(dns
.rcode
.BADVERS
)
1675 for method
in ("sendUDPQuery", "sendTCPQuery"):
1676 sender
= getattr(self
, method
)
1677 (_
, receivedResponse
) = sender(query
, response
=None)
1678 self
.assertEquals(receivedResponse
, expectedResponse
)
1680 def testNoEDNS0Pass(self
):
1682 Advanced: A question with ECS version 0 goes through
1685 name
= 'ednsversionrule.advanced.tests.powerdns.com.'
1687 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=True)
1688 response
= dns
.message
.make_response(query
)
1690 for method
in ("sendUDPQuery", "sendTCPQuery"):
1691 sender
= getattr(self
, method
)
1692 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1693 receivedQuery
.id = query
.id
1694 self
.assertEquals(query
, receivedQuery
)
1695 self
.assertEquals(receivedResponse
, response
)
1697 def testReplied(self
):
1699 Advanced: A question without ECS goes through
1702 name
= 'ednsoptionrule.advanced.tests.powerdns.com.'
1704 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=False)
1705 response
= dns
.message
.make_response(query
)
1707 for method
in ("sendUDPQuery", "sendTCPQuery"):
1708 sender
= getattr(self
, method
)
1709 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1710 receivedQuery
.id = query
.id
1711 self
.assertEquals(query
, receivedQuery
)
1712 self
.assertEquals(receivedResponse
, response
)
1714 class TestSetRules(DNSDistTest
):
1716 _consoleKey
= DNSDistTest
.generateConsoleKey()
1717 _consoleKeyB64
= base64
.b64encode(_consoleKey
).decode('ascii')
1718 _config_params
= ['_consoleKeyB64', '_consolePort', '_testServerPort']
1719 _config_template
= """
1721 controlSocket("127.0.0.1:%s")
1722 newServer{address="127.0.0.1:%s"}
1723 addAction(AllRule(), SpoofAction("192.0.2.1"))
1726 def testClearThenSetRules(self
):
1728 Advanced: Clear rules, set rules
1731 name
= 'clearthensetrules.advanced.tests.powerdns.com.'
1732 query
= dns
.message
.make_query(name
, 'A', 'IN')
1733 # dnsdist set RA = RD for spoofed responses
1734 query
.flags
&= ~dns
.flags
.RD
1735 expectedResponse
= dns
.message
.make_response(query
)
1736 rrset
= dns
.rrset
.from_text(name
,
1741 expectedResponse
.answer
.append(rrset
)
1743 for method
in ("sendUDPQuery", "sendTCPQuery"):
1744 sender
= getattr(self
, method
)
1746 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1747 self
.assertTrue(receivedResponse
)
1748 self
.assertEquals(expectedResponse
, receivedResponse
)
1750 # clear all the rules, we should not be spoofing and get a SERVFAIL from the responder instead
1751 self
.sendConsoleCommand("clearRules()")
1753 expectedResponse
= dns
.message
.make_response(query
)
1754 expectedResponse
.set_rcode(dns
.rcode
.SERVFAIL
)
1756 for method
in ("sendUDPQuery", "sendTCPQuery"):
1757 sender
= getattr(self
, method
)
1759 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1760 self
.assertTrue(receivedResponse
)
1761 self
.assertEquals(expectedResponse
, receivedResponse
)
1763 # insert a new spoofing rule
1764 self
.sendConsoleCommand("setRules({ newRuleAction(AllRule(), SpoofAction(\"192.0.2.2\")) })")
1766 expectedResponse
= dns
.message
.make_response(query
)
1767 rrset
= dns
.rrset
.from_text(name
,
1772 expectedResponse
.answer
.append(rrset
)
1774 for method
in ("sendUDPQuery", "sendTCPQuery"):
1775 sender
= getattr(self
, method
)
1777 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1778 self
.assertTrue(receivedResponse
)
1779 self
.assertEquals(expectedResponse
, receivedResponse
)
1781 class TestAdvancedContinueAction(DNSDistTest
):
1783 _config_template
= """
1784 newServer{address="127.0.0.1:%s", pool="mypool"}
1785 addAction("nocontinue.continue-action.advanced.tests.powerdns.com.", PoolAction("mypool"))
1786 addAction("continue.continue-action.advanced.tests.powerdns.com.", ContinueAction(PoolAction("mypool")))
1787 addAction(AllRule(), DisableValidationAction())
1790 def testNoContinue(self
):
1792 Advanced: Query routed to pool, PoolAction should be terminal
1795 name
= 'nocontinue.continue-action.advanced.tests.powerdns.com.'
1797 query
= dns
.message
.make_query(name
, 'A', 'IN')
1798 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
1800 response
= dns
.message
.make_response(query
)
1801 expectedResponse
= dns
.message
.make_response(query
)
1803 for method
in ("sendUDPQuery", "sendTCPQuery"):
1804 sender
= getattr(self
, method
)
1805 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1806 self
.assertEquals(receivedQuery
, expectedQuery
)
1807 self
.assertEquals(receivedResponse
, expectedResponse
)
1809 def testNoContinue(self
):
1811 Advanced: Query routed to pool, ContinueAction() should not stop the processing
1814 name
= 'continue.continue-action.advanced.tests.powerdns.com.'
1816 query
= dns
.message
.make_query(name
, 'A', 'IN')
1817 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
1818 expectedQuery
.flags |
= dns
.flags
.CD
1820 response
= dns
.message
.make_response(query
)
1821 expectedResponse
= dns
.message
.make_response(query
)
1823 for method
in ("sendUDPQuery", "sendTCPQuery"):
1824 sender
= getattr(self
, method
)
1825 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1826 expectedQuery
.id = receivedQuery
.id
1827 self
.assertEquals(receivedQuery
, expectedQuery
)
1828 print(receivedResponse
)
1829 print(expectedResponse
)
1830 self
.assertEquals(receivedResponse
, expectedResponse
)