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
.assertEqual(query
, receivedQuery
)
44 self
.assertEqual(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)
58 self
.assertEqual(receivedResponse
, None)
60 class TestAdvancedFixupCase(DNSDistTest
):
62 _config_template
= """
65 newServer{address="127.0.0.1:%s"}
68 def testAdvancedFixupCase(self
):
72 Send a query with lower and upper chars,
73 make the backend return a lowercase version,
74 check that dnsdist fixes the response.
76 name
= 'fiXuPCasE.advanced.tests.powerdns.com.'
77 query
= dns
.message
.make_query(name
, 'A', 'IN')
78 lowercasequery
= dns
.message
.make_query(name
.lower(), 'A', 'IN')
79 response
= dns
.message
.make_response(lowercasequery
)
80 expectedResponse
= dns
.message
.make_response(query
)
81 rrset
= dns
.rrset
.from_text(name
,
86 response
.answer
.append(rrset
)
87 expectedResponse
.answer
.append(rrset
)
89 for method
in ("sendUDPQuery", "sendTCPQuery"):
90 sender
= getattr(self
, method
)
91 (receivedQuery
, receivedResponse
) = sender(query
, response
)
92 self
.assertTrue(receivedQuery
)
93 self
.assertTrue(receivedResponse
)
94 receivedQuery
.id = query
.id
95 self
.assertEqual(query
, receivedQuery
)
96 self
.assertEqual(expectedResponse
, receivedResponse
)
98 class TestAdvancedRemoveRD(DNSDistTest
):
100 _config_template
= """
101 addAction("norecurse.advanced.tests.powerdns.com.", SetNoRecurseAction())
102 newServer{address="127.0.0.1:%s"}
105 def testAdvancedNoRD(self
):
109 Send a query with RD,
110 check that dnsdist clears the RD flag.
112 name
= 'norecurse.advanced.tests.powerdns.com.'
113 query
= dns
.message
.make_query(name
, 'A', 'IN')
114 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
115 expectedQuery
.flags
&= ~dns
.flags
.RD
117 response
= dns
.message
.make_response(query
)
118 rrset
= dns
.rrset
.from_text(name
,
123 response
.answer
.append(rrset
)
125 for method
in ("sendUDPQuery", "sendTCPQuery"):
126 sender
= getattr(self
, method
)
127 (receivedQuery
, receivedResponse
) = sender(query
, response
)
128 self
.assertTrue(receivedQuery
)
129 self
.assertTrue(receivedResponse
)
130 receivedQuery
.id = expectedQuery
.id
131 self
.assertEqual(expectedQuery
, receivedQuery
)
132 self
.assertEqual(response
, receivedResponse
)
134 def testAdvancedKeepRD(self
):
136 Advanced: No RD canary
138 Send a query with RD for a canary domain,
139 check that dnsdist does not clear the RD flag.
141 name
= 'keeprecurse.advanced.tests.powerdns.com.'
142 query
= dns
.message
.make_query(name
, 'A', 'IN')
144 response
= dns
.message
.make_response(query
)
145 rrset
= dns
.rrset
.from_text(name
,
150 response
.answer
.append(rrset
)
152 for method
in ("sendUDPQuery", "sendTCPQuery"):
153 sender
= getattr(self
, method
)
154 (receivedQuery
, receivedResponse
) = sender(query
, response
)
155 self
.assertTrue(receivedQuery
)
156 self
.assertTrue(receivedResponse
)
157 receivedQuery
.id = query
.id
158 self
.assertEqual(query
, receivedQuery
)
159 self
.assertEqual(response
, receivedResponse
)
161 class TestAdvancedAddCD(DNSDistTest
):
163 _config_template
= """
164 addAction("setcd.advanced.tests.powerdns.com.", SetDisableValidationAction())
165 addAction(makeRule("setcdviaaction.advanced.tests.powerdns.com."), SetDisableValidationAction())
166 newServer{address="127.0.0.1:%s"}
169 def testAdvancedSetCD(self
):
173 Send a query with CD cleared,
174 check that dnsdist set the CD flag.
176 name
= 'setcd.advanced.tests.powerdns.com.'
177 query
= dns
.message
.make_query(name
, 'A', 'IN')
178 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
179 expectedQuery
.flags |
= dns
.flags
.CD
181 response
= dns
.message
.make_response(query
)
182 rrset
= dns
.rrset
.from_text(name
,
187 response
.answer
.append(rrset
)
189 for method
in ("sendUDPQuery", "sendTCPQuery"):
190 sender
= getattr(self
, method
)
191 (receivedQuery
, receivedResponse
) = sender(query
, response
)
192 self
.assertTrue(receivedQuery
)
193 self
.assertTrue(receivedResponse
)
194 receivedQuery
.id = expectedQuery
.id
195 self
.assertEqual(expectedQuery
, receivedQuery
)
196 self
.assertEqual(response
, receivedResponse
)
198 def testAdvancedSetCDViaAction(self
):
200 Advanced: Set CD via Action
202 Send a query with CD cleared,
203 check that dnsdist set the CD flag.
205 name
= 'setcdviaaction.advanced.tests.powerdns.com.'
206 query
= dns
.message
.make_query(name
, 'A', 'IN')
207 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
208 expectedQuery
.flags |
= dns
.flags
.CD
210 response
= dns
.message
.make_response(query
)
211 rrset
= dns
.rrset
.from_text(name
,
216 response
.answer
.append(rrset
)
218 for method
in ("sendUDPQuery", "sendTCPQuery"):
219 sender
= getattr(self
, method
)
220 (receivedQuery
, receivedResponse
) = sender(query
, response
)
221 self
.assertTrue(receivedQuery
)
222 self
.assertTrue(receivedResponse
)
223 receivedQuery
.id = expectedQuery
.id
224 self
.assertEqual(expectedQuery
, receivedQuery
)
225 self
.assertEqual(response
, receivedResponse
)
227 def testAdvancedKeepNoCD(self
):
229 Advanced: Preserve CD canary
231 Send a query without CD for a canary domain,
232 check that dnsdist does not set the CD flag.
234 name
= 'keepnocd.advanced.tests.powerdns.com.'
235 query
= dns
.message
.make_query(name
, 'A', 'IN')
237 response
= dns
.message
.make_response(query
)
238 rrset
= dns
.rrset
.from_text(name
,
243 response
.answer
.append(rrset
)
245 for method
in ("sendUDPQuery", "sendTCPQuery"):
246 sender
= getattr(self
, method
)
247 (receivedQuery
, receivedResponse
) = sender(query
, response
)
248 self
.assertTrue(receivedQuery
)
249 self
.assertTrue(receivedResponse
)
250 receivedQuery
.id = query
.id
251 self
.assertEqual(query
, receivedQuery
)
252 self
.assertEqual(response
, receivedResponse
)
254 class TestAdvancedClearRD(DNSDistTest
):
256 _config_template
= """
257 addAction("clearrd.advanced.tests.powerdns.com.", SetNoRecurseAction())
258 addAction(makeRule("clearrdviaaction.advanced.tests.powerdns.com."), SetNoRecurseAction())
259 newServer{address="127.0.0.1:%s"}
262 def testAdvancedClearRD(self
):
266 Send a query with RD set,
267 check that dnsdist clears the RD flag.
269 name
= 'clearrd.advanced.tests.powerdns.com.'
270 query
= dns
.message
.make_query(name
, 'A', 'IN')
271 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
272 expectedQuery
.flags
&= ~dns
.flags
.RD
274 response
= dns
.message
.make_response(query
)
275 rrset
= dns
.rrset
.from_text(name
,
280 response
.answer
.append(rrset
)
282 for method
in ("sendUDPQuery", "sendTCPQuery"):
283 sender
= getattr(self
, method
)
284 (receivedQuery
, receivedResponse
) = sender(query
, response
)
285 self
.assertTrue(receivedQuery
)
286 self
.assertTrue(receivedResponse
)
287 receivedQuery
.id = expectedQuery
.id
288 self
.assertEqual(expectedQuery
, receivedQuery
)
289 self
.assertEqual(response
, receivedResponse
)
291 def testAdvancedClearRDViaAction(self
):
293 Advanced: Clear RD via Action
295 Send a query with RD set,
296 check that dnsdist clears the RD flag.
298 name
= 'clearrdviaaction.advanced.tests.powerdns.com.'
299 query
= dns
.message
.make_query(name
, 'A', 'IN')
300 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
301 expectedQuery
.flags
&= ~dns
.flags
.RD
303 response
= dns
.message
.make_response(query
)
304 rrset
= dns
.rrset
.from_text(name
,
309 response
.answer
.append(rrset
)
311 for method
in ("sendUDPQuery", "sendTCPQuery"):
312 sender
= getattr(self
, method
)
313 (receivedQuery
, receivedResponse
) = sender(query
, response
)
314 self
.assertTrue(receivedQuery
)
315 self
.assertTrue(receivedResponse
)
316 receivedQuery
.id = expectedQuery
.id
317 self
.assertEqual(expectedQuery
, receivedQuery
)
318 self
.assertEqual(response
, receivedResponse
)
320 def testAdvancedKeepRD(self
):
322 Advanced: Preserve RD canary
324 Send a query with RD for a canary domain,
325 check that dnsdist does not clear the RD flag.
327 name
= 'keeprd.advanced.tests.powerdns.com.'
328 query
= dns
.message
.make_query(name
, 'A', 'IN')
330 response
= dns
.message
.make_response(query
)
331 rrset
= dns
.rrset
.from_text(name
,
336 response
.answer
.append(rrset
)
338 for method
in ("sendUDPQuery", "sendTCPQuery"):
339 sender
= getattr(self
, method
)
340 (receivedQuery
, receivedResponse
) = sender(query
, response
)
341 self
.assertTrue(receivedQuery
)
342 self
.assertTrue(receivedResponse
)
343 receivedQuery
.id = query
.id
344 self
.assertEqual(query
, receivedQuery
)
345 self
.assertEqual(response
, receivedResponse
)
348 class TestAdvancedACL(DNSDistTest
):
350 _config_template
= """
351 newServer{address="127.0.0.1:%s"}
353 _acl
= ['192.0.2.1/32']
355 def testACLBlocked(self
):
357 Advanced: ACL blocked
359 Send an A query to "tests.powerdns.com.",
360 we expect no response since 127.0.0.1 is not on the
363 name
= 'tests.powerdns.com.'
364 query
= dns
.message
.make_query(name
, 'A', 'IN')
366 for method
in ("sendUDPQuery", "sendTCPQuery"):
367 sender
= getattr(self
, method
)
368 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
369 self
.assertEqual(receivedResponse
, None)
371 class TestAdvancedDelay(DNSDistTest
):
373 _config_template
= """
374 addAction(AllRule(), DelayAction(1000))
375 newServer{address="127.0.0.1:%s"}
378 def testDelayed(self
):
382 Send an A query to "tests.powerdns.com.",
383 check that the response delay is longer than 1000 ms
384 over UDP, less than that over TCP.
386 name
= 'tests.powerdns.com.'
387 query
= dns
.message
.make_query(name
, 'A', 'IN')
388 response
= dns
.message
.make_response(query
)
389 rrset
= dns
.rrset
.from_text(name
,
394 response
.answer
.append(rrset
)
396 begin
= datetime
.now()
397 (receivedQuery
, receivedResponse
) = self
.sendUDPQuery(query
, response
)
399 receivedQuery
.id = query
.id
400 self
.assertEqual(query
, receivedQuery
)
401 self
.assertEqual(response
, receivedResponse
)
402 self
.assertTrue((end
- begin
) > timedelta(0, 1))
404 begin
= datetime
.now()
405 (receivedQuery
, receivedResponse
) = self
.sendTCPQuery(query
, response
)
407 receivedQuery
.id = query
.id
408 self
.assertEqual(query
, receivedQuery
)
409 self
.assertEqual(response
, receivedResponse
)
410 self
.assertTrue((end
- begin
) < timedelta(0, 1))
413 class TestAdvancedTruncateAnyAndTCP(DNSDistTest
):
415 _config_template
= """
417 addAction(AndRule({QTypeRule("ANY"), TCPRule(true)}), TCAction())
418 newServer{address="127.0.0.1:%s"}
420 def testTruncateAnyOverTCP(self
):
422 Advanced: Truncate ANY over TCP
424 Send an ANY query to "anytruncatetcp.advanced.tests.powerdns.com.",
425 should be truncated over TCP, not over UDP (yes, it makes no sense,
428 name
= 'anytruncatetcp.advanced.tests.powerdns.com.'
429 query
= dns
.message
.make_query(name
, 'ANY', 'IN')
430 # dnsdist sets RA = RD for TC responses
431 query
.flags
&= ~dns
.flags
.RD
433 response
= dns
.message
.make_response(query
)
434 rrset
= dns
.rrset
.from_text(name
,
440 response
.answer
.append(rrset
)
442 (receivedQuery
, receivedResponse
) = self
.sendUDPQuery(query
, response
)
443 self
.assertTrue(receivedQuery
)
444 self
.assertTrue(receivedResponse
)
445 receivedQuery
.id = query
.id
446 self
.assertEqual(query
, receivedQuery
)
447 self
.assertEqual(receivedResponse
, response
)
449 expectedResponse
= dns
.message
.make_response(query
)
450 expectedResponse
.flags |
= dns
.flags
.TC
452 (_
, receivedResponse
) = self
.sendTCPQuery(query
, response
=None, useQueue
=False)
453 self
.assertEqual(receivedResponse
, expectedResponse
)
455 class TestAdvancedAndNot(DNSDistTest
):
457 _config_template
= """
458 addAction(AndRule({NotRule(QTypeRule("A")), TCPRule(false)}), RCodeAction(DNSRCode.NOTIMP))
459 newServer{address="127.0.0.1:%s"}
461 def testAOverUDPReturnsNotImplementedCanary(self
):
463 Advanced: !A && UDP canary
465 dnsdist is configured to reply 'not implemented' for query
466 over UDP AND !qtype A.
467 We send an A query over UDP and TCP, and check that the
470 name
= 'andnot.advanced.tests.powerdns.com.'
471 query
= dns
.message
.make_query(name
, 'A', 'IN')
472 response
= dns
.message
.make_response(query
)
473 rrset
= dns
.rrset
.from_text(name
,
478 response
.answer
.append(rrset
)
480 for method
in ("sendUDPQuery", "sendTCPQuery"):
481 sender
= getattr(self
, method
)
482 (receivedQuery
, receivedResponse
) = sender(query
, response
)
483 self
.assertTrue(receivedQuery
)
484 self
.assertTrue(receivedResponse
)
485 receivedQuery
.id = query
.id
486 self
.assertEqual(query
, receivedQuery
)
487 self
.assertEqual(receivedResponse
, response
)
489 def testAOverUDPReturnsNotImplemented(self
):
493 dnsdist is configured to reply 'not implemented' for query
494 over UDP AND !qtype A.
495 We send a TXT query over UDP and TCP, and check that the
496 response is OK for TCP and 'not implemented' for UDP.
498 name
= 'andnot.advanced.tests.powerdns.com.'
499 query
= dns
.message
.make_query(name
, 'TXT', 'IN')
500 # dnsdist sets RA = RD for TC responses
501 query
.flags
&= ~dns
.flags
.RD
503 expectedResponse
= dns
.message
.make_response(query
)
504 expectedResponse
.set_rcode(dns
.rcode
.NOTIMP
)
506 (_
, receivedResponse
) = self
.sendUDPQuery(query
, response
=None, useQueue
=False)
507 self
.assertEqual(receivedResponse
, expectedResponse
)
509 response
= dns
.message
.make_response(query
)
510 rrset
= dns
.rrset
.from_text(name
,
514 'nothing to see here')
515 response
.answer
.append(rrset
)
517 (receivedQuery
, receivedResponse
) = self
.sendTCPQuery(query
, response
)
518 self
.assertTrue(receivedQuery
)
519 self
.assertTrue(receivedResponse
)
520 receivedQuery
.id = query
.id
521 self
.assertEqual(query
, receivedQuery
)
522 self
.assertEqual(receivedResponse
, response
)
524 class TestAdvancedOr(DNSDistTest
):
526 _config_template
= """
527 addAction(OrRule({QTypeRule("A"), TCPRule(false)}), RCodeAction(DNSRCode.NOTIMP))
528 newServer{address="127.0.0.1:%s"}
530 def testAAAAOverUDPReturnsNotImplemented(self
):
532 Advanced: A || UDP: AAAA
534 dnsdist is configured to reply 'not implemented' for query
536 We send an AAAA query over UDP and TCP, and check that the
537 response is 'not implemented' for UDP and OK for TCP.
539 name
= 'aorudp.advanced.tests.powerdns.com.'
540 query
= dns
.message
.make_query(name
, 'AAAA', 'IN')
541 query
.flags
&= ~dns
.flags
.RD
542 response
= dns
.message
.make_response(query
)
543 rrset
= dns
.rrset
.from_text(name
,
548 response
.answer
.append(rrset
)
550 expectedResponse
= dns
.message
.make_response(query
)
551 expectedResponse
.set_rcode(dns
.rcode
.NOTIMP
)
553 (_
, receivedResponse
) = self
.sendUDPQuery(query
, response
=None, useQueue
=False)
554 self
.assertEqual(receivedResponse
, expectedResponse
)
556 (receivedQuery
, receivedResponse
) = self
.sendTCPQuery(query
, response
)
557 self
.assertTrue(receivedQuery
)
558 self
.assertTrue(receivedResponse
)
559 receivedQuery
.id = query
.id
560 self
.assertEqual(query
, receivedQuery
)
561 self
.assertEqual(receivedResponse
, response
)
563 def testAOverUDPReturnsNotImplemented(self
):
565 Advanced: A || UDP: A
567 dnsdist is configured to reply 'not implemented' for query
569 We send an A query over UDP and TCP, and check that the
570 response is 'not implemented' for both.
572 name
= 'aorudp.advanced.tests.powerdns.com.'
573 query
= dns
.message
.make_query(name
, 'A', 'IN')
574 query
.flags
&= ~dns
.flags
.RD
576 expectedResponse
= dns
.message
.make_response(query
)
577 expectedResponse
.set_rcode(dns
.rcode
.NOTIMP
)
579 for method
in ("sendUDPQuery", "sendTCPQuery"):
580 sender
= getattr(self
, method
)
581 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
582 self
.assertEqual(receivedResponse
, expectedResponse
)
585 class TestAdvancedLogAction(DNSDistTest
):
587 _config_template
= """
588 newServer{address="127.0.0.1:%s"}
589 addAction(AllRule(), LogAction("dnsdist.log", false))
591 def testAdvancedLogAction(self
):
593 Advanced: Log all queries
597 name
= 'logaction.advanced.tests.powerdns.com.'
598 query
= dns
.message
.make_query(name
, 'A', 'IN')
599 response
= dns
.message
.make_response(query
)
600 rrset
= dns
.rrset
.from_text(name
,
605 response
.answer
.append(rrset
)
607 for _
in range(count
):
608 (receivedQuery
, receivedResponse
) = self
.sendUDPQuery(query
, response
)
609 self
.assertTrue(receivedQuery
)
610 self
.assertTrue(receivedResponse
)
611 receivedQuery
.id = query
.id
612 self
.assertEqual(query
, receivedQuery
)
613 self
.assertEqual(response
, receivedResponse
)
615 self
.assertTrue(os
.path
.isfile('dnsdist.log'))
616 self
.assertTrue(os
.stat('dnsdist.log').st_size
> 0)
618 class TestAdvancedDNSSEC(DNSDistTest
):
620 _config_template
= """
621 newServer{address="127.0.0.1:%s"}
622 addAction(DNSSECRule(), DropAction())
624 def testAdvancedDNSSECDrop(self
):
626 Advanced: DNSSEC Rule
629 name
= 'dnssec.advanced.tests.powerdns.com.'
630 query
= dns
.message
.make_query(name
, 'A', 'IN')
631 doquery
= dns
.message
.make_query(name
, 'A', 'IN', want_dnssec
=True)
632 response
= dns
.message
.make_response(query
)
633 rrset
= dns
.rrset
.from_text(name
,
638 response
.answer
.append(rrset
)
640 for method
in ("sendUDPQuery", "sendTCPQuery"):
641 sender
= getattr(self
, method
)
642 (receivedQuery
, receivedResponse
) = sender(query
, response
)
643 self
.assertTrue(receivedQuery
)
644 self
.assertTrue(receivedResponse
)
645 receivedQuery
.id = query
.id
646 self
.assertEqual(query
, receivedQuery
)
647 self
.assertEqual(response
, receivedResponse
)
649 for method
in ("sendUDPQuery", "sendTCPQuery"):
650 sender
= getattr(self
, method
)
651 (_
, receivedResponse
) = sender(doquery
, response
=None, useQueue
=False)
652 self
.assertEqual(receivedResponse
, None)
654 class TestAdvancedQClass(DNSDistTest
):
656 _config_template
= """
657 newServer{address="127.0.0.1:%s"}
658 addAction(QClassRule(DNSClass.CHAOS), DropAction())
660 def testAdvancedQClassChaosDrop(self
):
662 Advanced: Drop QClass CHAOS
665 name
= 'qclasschaos.advanced.tests.powerdns.com.'
666 query
= dns
.message
.make_query(name
, 'TXT', 'CHAOS')
668 for method
in ("sendUDPQuery", "sendTCPQuery"):
669 sender
= getattr(self
, method
)
670 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
671 self
.assertEqual(receivedResponse
, None)
673 def testAdvancedQClassINAllow(self
):
675 Advanced: Allow QClass IN
678 name
= 'qclassin.advanced.tests.powerdns.com.'
679 query
= dns
.message
.make_query(name
, 'A', 'IN')
680 response
= dns
.message
.make_response(query
)
681 rrset
= dns
.rrset
.from_text(name
,
686 response
.answer
.append(rrset
)
688 for method
in ("sendUDPQuery", "sendTCPQuery"):
689 sender
= getattr(self
, method
)
690 (receivedQuery
, receivedResponse
) = sender(query
, response
)
691 self
.assertTrue(receivedQuery
)
692 self
.assertTrue(receivedResponse
)
693 receivedQuery
.id = query
.id
694 self
.assertEqual(query
, receivedQuery
)
695 self
.assertEqual(response
, receivedResponse
)
697 class TestAdvancedOpcode(DNSDistTest
):
699 _config_template
= """
700 newServer{address="127.0.0.1:%s"}
701 addAction(OpcodeRule(DNSOpcode.Notify), DropAction())
703 def testAdvancedOpcodeNotifyDrop(self
):
705 Advanced: Drop Opcode NOTIFY
708 name
= 'opcodenotify.advanced.tests.powerdns.com.'
709 query
= dns
.message
.make_query(name
, 'A', 'IN')
710 query
.set_opcode(dns
.opcode
.NOTIFY
)
712 for method
in ("sendUDPQuery", "sendTCPQuery"):
713 sender
= getattr(self
, method
)
714 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
715 self
.assertEqual(receivedResponse
, None)
717 def testAdvancedOpcodeUpdateINAllow(self
):
719 Advanced: Allow Opcode UPDATE
722 name
= 'opcodeupdate.advanced.tests.powerdns.com.'
723 query
= dns
.message
.make_query(name
, 'SOA', 'IN')
724 query
.set_opcode(dns
.opcode
.UPDATE
)
725 response
= dns
.message
.make_response(query
)
726 rrset
= dns
.rrset
.from_text(name
,
731 response
.answer
.append(rrset
)
733 for method
in ("sendUDPQuery", "sendTCPQuery"):
734 sender
= getattr(self
, method
)
735 (receivedQuery
, receivedResponse
) = sender(query
, response
)
736 self
.assertTrue(receivedQuery
)
737 self
.assertTrue(receivedResponse
)
738 receivedQuery
.id = query
.id
739 self
.assertEqual(query
, receivedQuery
)
740 self
.assertEqual(response
, receivedResponse
)
742 class TestAdvancedNonTerminalRule(DNSDistTest
):
744 _config_template
= """
745 newServer{address="127.0.0.1:%s", pool="real"}
746 addAction(AllRule(), SetDisableValidationAction())
747 addAction(AllRule(), PoolAction("real"))
748 addAction(AllRule(), DropAction())
750 def testAdvancedNonTerminalRules(self
):
752 Advanced: Non terminal rules
754 We check that SetDisableValidationAction() is applied
755 but does not stop the processing, then that
756 PoolAction() is applied _and_ stop the processing.
758 name
= 'nonterminal.advanced.tests.powerdns.com.'
759 query
= dns
.message
.make_query(name
, 'A', 'IN')
760 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
761 expectedQuery
.flags |
= dns
.flags
.CD
762 response
= dns
.message
.make_response(query
)
763 rrset
= dns
.rrset
.from_text(name
,
768 response
.answer
.append(rrset
)
770 for method
in ("sendUDPQuery", "sendTCPQuery"):
771 sender
= getattr(self
, method
)
772 (receivedQuery
, receivedResponse
) = sender(query
, response
)
773 self
.assertTrue(receivedQuery
)
774 self
.assertTrue(receivedResponse
)
775 receivedQuery
.id = expectedQuery
.id
776 self
.assertEqual(expectedQuery
, receivedQuery
)
777 self
.assertEqual(response
, receivedResponse
)
779 class TestAdvancedStringOnlyServer(DNSDistTest
):
781 _config_template
= """
782 newServer("127.0.0.1:%s")
785 def testAdvancedStringOnlyServer(self
):
787 Advanced: "string-only" server is placed in the default pool
789 name
= 'string-only-server.advanced.tests.powerdns.com.'
790 query
= dns
.message
.make_query(name
, 'A', 'IN')
791 response
= dns
.message
.make_response(query
)
792 rrset
= dns
.rrset
.from_text(name
,
797 response
.answer
.append(rrset
)
799 for method
in ("sendUDPQuery", "sendTCPQuery"):
800 sender
= getattr(self
, method
)
801 (receivedQuery
, receivedResponse
) = sender(query
, response
)
802 self
.assertTrue(receivedQuery
)
803 self
.assertTrue(receivedResponse
)
804 receivedQuery
.id = query
.id
805 self
.assertEqual(query
, receivedQuery
)
806 self
.assertEqual(response
, receivedResponse
)
808 class TestAdvancedRestoreFlagsOnSelfResponse(DNSDistTest
):
810 _config_template
= """
811 addAction(AllRule(), SetDisableValidationAction())
812 addAction(AllRule(), SpoofAction("192.0.2.1"))
813 newServer{address="127.0.0.1:%s"}
816 def testAdvancedRestoreFlagsOnSpoofResponse(self
):
818 Advanced: Restore flags on spoofed response
820 Send a query with CD flag cleared, dnsdist is
821 instructed to set it, then to spoof the response,
822 check that response has the flag cleared.
824 name
= 'spoofed.restoreflags.advanced.tests.powerdns.com.'
825 query
= dns
.message
.make_query(name
, 'A', 'IN')
826 # dnsdist set RA = RD for spoofed responses
827 query
.flags
&= ~dns
.flags
.RD
829 response
= dns
.message
.make_response(query
)
830 rrset
= dns
.rrset
.from_text(name
,
835 response
.answer
.append(rrset
)
837 for method
in ("sendUDPQuery", "sendTCPQuery"):
838 sender
= getattr(self
, method
)
839 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
840 self
.assertTrue(receivedResponse
)
841 self
.assertEqual(response
, receivedResponse
)
843 class TestAdvancedQPS(DNSDistTest
):
845 _config_template
= """
846 addAction("qps.advanced.tests.powerdns.com", QPSAction(10))
847 newServer{address="127.0.0.1:%s"}
850 def testAdvancedQPSLimit(self
):
854 Send queries to "qps.advanced.tests.powerdns.com."
855 check that dnsdist drops queries when the max QPS has been reached.
858 name
= 'qps.advanced.tests.powerdns.com.'
859 query
= dns
.message
.make_query(name
, 'A', 'IN')
860 response
= dns
.message
.make_response(query
)
861 rrset
= dns
.rrset
.from_text(name
,
866 response
.answer
.append(rrset
)
868 for _
in range(maxQPS
):
869 (receivedQuery
, receivedResponse
) = self
.sendUDPQuery(query
, response
)
870 receivedQuery
.id = query
.id
871 self
.assertEqual(query
, receivedQuery
)
872 self
.assertEqual(response
, receivedResponse
)
874 # we should now be dropped
875 (_
, receivedResponse
) = self
.sendUDPQuery(query
, response
=None, useQueue
=False)
876 self
.assertEqual(receivedResponse
, None)
880 # again, over TCP this time
881 for _
in range(maxQPS
):
882 (receivedQuery
, receivedResponse
) = self
.sendTCPQuery(query
, response
)
883 receivedQuery
.id = query
.id
884 self
.assertEqual(query
, receivedQuery
)
885 self
.assertEqual(response
, receivedResponse
)
888 (_
, receivedResponse
) = self
.sendTCPQuery(query
, response
=None, useQueue
=False)
889 self
.assertEqual(receivedResponse
, None)
891 class TestAdvancedQPSNone(DNSDistTest
):
893 _config_template
= """
894 addAction("qpsnone.advanced.tests.powerdns.com", QPSAction(100))
895 addAction(AllRule(), RCodeAction(DNSRCode.REFUSED))
896 newServer{address="127.0.0.1:%s"}
899 def testAdvancedQPSNone(self
):
901 Advanced: Not matching QPS returns None, not Allow
903 Send queries to "qps.advanced.tests.powerdns.com."
904 check that the rule returns None when the QPS has not been
907 name
= 'qpsnone.advanced.tests.powerdns.com.'
908 query
= dns
.message
.make_query(name
, 'A', 'IN')
909 query
.flags
&= ~dns
.flags
.RD
910 expectedResponse
= dns
.message
.make_response(query
)
911 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
913 for method
in ("sendUDPQuery", "sendTCPQuery"):
914 sender
= getattr(self
, method
)
915 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
916 self
.assertEqual(receivedResponse
, expectedResponse
)
918 class TestAdvancedNMGRule(DNSDistTest
):
920 _config_template
= """
922 allowed:addMask("192.0.2.1/32")
923 addAction(NotRule(NetmaskGroupRule(allowed)), RCodeAction(DNSRCode.REFUSED))
924 newServer{address="127.0.0.1:%s"}
927 def testAdvancedNMGRule(self
):
929 Advanced: NMGRule should refuse our queries
931 Send queries to "nmgrule.advanced.tests.powerdns.com.",
932 check that we are getting a REFUSED response.
934 name
= 'nmgrule.advanced.tests.powerdns.com.'
935 query
= dns
.message
.make_query(name
, 'A', 'IN')
936 query
.flags
&= ~dns
.flags
.RD
937 expectedResponse
= dns
.message
.make_response(query
)
938 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
940 for method
in ("sendUDPQuery", "sendTCPQuery"):
941 sender
= getattr(self
, method
)
942 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
943 self
.assertEqual(receivedResponse
, expectedResponse
)
945 class TestDSTPortRule(DNSDistTest
):
947 _config_params
= ['_dnsDistPort', '_testServerPort']
948 _config_template
= """
949 addAction(DSTPortRule(%d), RCodeAction(DNSRCode.REFUSED))
950 newServer{address="127.0.0.1:%s"}
953 def testDSTPortRule(self
):
955 Advanced: DSTPortRule should capture our queries
957 Send queries to "dstportrule.advanced.tests.powerdns.com.",
958 check that we are getting a REFUSED response.
961 name
= 'dstportrule.advanced.tests.powerdns.com.'
962 query
= dns
.message
.make_query(name
, 'A', 'IN')
963 query
.flags
&= ~dns
.flags
.RD
964 expectedResponse
= dns
.message
.make_response(query
)
965 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
967 for method
in ("sendUDPQuery", "sendTCPQuery"):
968 sender
= getattr(self
, method
)
969 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
970 self
.assertEqual(receivedResponse
, expectedResponse
)
972 class TestAdvancedLabelsCountRule(DNSDistTest
):
974 _config_template
= """
975 addAction(QNameLabelsCountRule(5,6), RCodeAction(DNSRCode.REFUSED))
976 newServer{address="127.0.0.1:%s"}
979 def testAdvancedLabelsCountRule(self
):
981 Advanced: QNameLabelsCountRule(5,6)
983 # 6 labels, we should be fine
984 name
= 'ok.labelscount.advanced.tests.powerdns.com.'
985 query
= dns
.message
.make_query(name
, 'A', 'IN')
986 response
= dns
.message
.make_response(query
)
987 rrset
= dns
.rrset
.from_text(name
,
992 response
.answer
.append(rrset
)
994 for method
in ("sendUDPQuery", "sendTCPQuery"):
995 sender
= getattr(self
, method
)
996 (receivedQuery
, receivedResponse
) = sender(query
, response
)
997 self
.assertTrue(receivedQuery
)
998 self
.assertTrue(receivedResponse
)
999 receivedQuery
.id = query
.id
1000 self
.assertEqual(query
, receivedQuery
)
1001 self
.assertEqual(response
, receivedResponse
)
1003 # more than 6 labels, the query should be refused
1004 name
= 'not.ok.labelscount.advanced.tests.powerdns.com.'
1005 query
= dns
.message
.make_query(name
, 'A', 'IN')
1006 query
.flags
&= ~dns
.flags
.RD
1007 expectedResponse
= dns
.message
.make_response(query
)
1008 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1010 for method
in ("sendUDPQuery", "sendTCPQuery"):
1011 sender
= getattr(self
, method
)
1012 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1013 self
.assertEqual(receivedResponse
, expectedResponse
)
1015 # less than 5 labels, the query should be refused
1016 name
= 'labelscountadvanced.tests.powerdns.com.'
1017 query
= dns
.message
.make_query(name
, 'A', 'IN')
1018 query
.flags
&= ~dns
.flags
.RD
1019 expectedResponse
= dns
.message
.make_response(query
)
1020 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1022 for method
in ("sendUDPQuery", "sendTCPQuery"):
1023 sender
= getattr(self
, method
)
1024 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1025 self
.assertEqual(receivedResponse
, expectedResponse
)
1027 class TestAdvancedWireLengthRule(DNSDistTest
):
1029 _config_template
= """
1030 addAction(QNameWireLengthRule(54,56), RCodeAction(DNSRCode.REFUSED))
1031 newServer{address="127.0.0.1:%s"}
1034 def testAdvancedWireLengthRule(self
):
1036 Advanced: QNameWireLengthRule(54,56)
1038 name
= 'longenough.qnamewirelength.advanced.tests.powerdns.com.'
1039 query
= dns
.message
.make_query(name
, 'A', 'IN')
1040 response
= dns
.message
.make_response(query
)
1041 rrset
= dns
.rrset
.from_text(name
,
1046 response
.answer
.append(rrset
)
1048 for method
in ("sendUDPQuery", "sendTCPQuery"):
1049 sender
= getattr(self
, method
)
1050 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1051 self
.assertTrue(receivedQuery
)
1052 self
.assertTrue(receivedResponse
)
1053 receivedQuery
.id = query
.id
1054 self
.assertEqual(query
, receivedQuery
)
1055 self
.assertEqual(response
, receivedResponse
)
1057 # too short, the query should be refused
1058 name
= 'short.qnamewirelength.advanced.tests.powerdns.com.'
1059 query
= dns
.message
.make_query(name
, 'A', 'IN')
1060 query
.flags
&= ~dns
.flags
.RD
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
.assertEqual(receivedResponse
, expectedResponse
)
1069 # too long, the query should be refused
1070 name
= 'toolongtobevalid.qnamewirelength.advanced.tests.powerdns.com.'
1071 query
= dns
.message
.make_query(name
, 'A', 'IN')
1072 query
.flags
&= ~dns
.flags
.RD
1073 expectedResponse
= dns
.message
.make_response(query
)
1074 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1076 for method
in ("sendUDPQuery", "sendTCPQuery"):
1077 sender
= getattr(self
, method
)
1078 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1079 self
.assertEqual(receivedResponse
, expectedResponse
)
1081 class TestAdvancedIncludeDir(DNSDistTest
):
1083 _config_template
= """
1084 -- this directory contains a file allowing includedir.advanced.tests.powerdns.com.
1085 includeDirectory('test-include-dir')
1086 newServer{address="127.0.0.1:%s"}
1089 def testAdvancedIncludeDirAllowed(self
):
1091 Advanced: includeDirectory()
1093 name
= 'includedir.advanced.tests.powerdns.com.'
1094 query
= dns
.message
.make_query(name
, 'A', 'IN')
1095 response
= dns
.message
.make_response(query
)
1096 rrset
= dns
.rrset
.from_text(name
,
1101 response
.answer
.append(rrset
)
1103 for method
in ("sendUDPQuery", "sendTCPQuery"):
1104 sender
= getattr(self
, method
)
1105 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1106 self
.assertTrue(receivedQuery
)
1107 self
.assertTrue(receivedResponse
)
1108 receivedQuery
.id = query
.id
1109 self
.assertEqual(query
, receivedQuery
)
1110 self
.assertEqual(response
, receivedResponse
)
1112 # this one should be refused
1113 name
= 'notincludedir.advanced.tests.powerdns.com.'
1114 query
= dns
.message
.make_query(name
, 'A', 'IN')
1115 query
.flags
&= ~dns
.flags
.RD
1116 expectedResponse
= dns
.message
.make_response(query
)
1117 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1119 for method
in ("sendUDPQuery", "sendTCPQuery"):
1120 sender
= getattr(self
, method
)
1121 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1122 self
.assertEqual(receivedResponse
, expectedResponse
)
1124 class TestAdvancedLuaDO(DNSDistTest
):
1126 _config_template
= """
1127 function nxDOLua(dq)
1129 return DNSAction.Nxdomain, ""
1131 return DNSAction.None, ""
1133 addAction(AllRule(), LuaAction(nxDOLua))
1134 newServer{address="127.0.0.1:%s"}
1137 def testNxDOViaLua(self
):
1139 Advanced: Nx DO queries via Lua
1141 name
= 'nxdo.advanced.tests.powerdns.com.'
1142 query
= dns
.message
.make_query(name
, 'A', 'IN')
1143 response
= dns
.message
.make_response(query
)
1144 rrset
= dns
.rrset
.from_text(name
,
1149 response
.answer
.append(rrset
)
1150 queryWithDO
= dns
.message
.make_query(name
, 'A', 'IN', want_dnssec
=True)
1151 doResponse
= dns
.message
.make_response(queryWithDO
)
1152 doResponse
.set_rcode(dns
.rcode
.NXDOMAIN
)
1155 for method
in ("sendUDPQuery", "sendTCPQuery"):
1156 sender
= getattr(self
, method
)
1157 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1158 self
.assertTrue(receivedQuery
)
1159 self
.assertTrue(receivedResponse
)
1160 receivedQuery
.id = query
.id
1161 self
.assertEqual(query
, receivedQuery
)
1162 self
.assertEqual(receivedResponse
, response
)
1165 for method
in ("sendUDPQuery", "sendTCPQuery"):
1166 sender
= getattr(self
, method
)
1167 (_
, receivedResponse
) = sender(queryWithDO
, response
=None, useQueue
=False)
1168 self
.assertTrue(receivedResponse
)
1169 doResponse
.id = receivedResponse
.id
1170 self
.assertEqual(receivedResponse
, doResponse
)
1172 class TestAdvancedLuaRefused(DNSDistTest
):
1174 _config_template
= """
1176 return DNSAction.Refused, ""
1178 addAction(AllRule(), LuaAction(refuse))
1179 newServer{address="127.0.0.1:%s"}
1182 def testRefusedViaLua(self
):
1184 Advanced: Refused via Lua
1186 name
= 'refused.advanced.tests.powerdns.com.'
1187 query
= dns
.message
.make_query(name
, 'A', 'IN')
1188 response
= dns
.message
.make_response(query
)
1189 rrset
= dns
.rrset
.from_text(name
,
1194 response
.answer
.append(rrset
)
1195 refusedResponse
= dns
.message
.make_response(query
)
1196 refusedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1198 for method
in ("sendUDPQuery", "sendTCPQuery"):
1199 sender
= getattr(self
, method
)
1200 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1201 self
.assertTrue(receivedResponse
)
1202 refusedResponse
.id = receivedResponse
.id
1203 self
.assertEqual(receivedResponse
, refusedResponse
)
1205 class TestAdvancedLuaActionReturnSyntax(DNSDistTest
):
1207 _config_template
= """
1209 return DNSAction.Refused
1211 addAction(AllRule(), LuaAction(refuse))
1212 newServer{address="127.0.0.1:%s"}
1215 def testRefusedWithEmptyRule(self
):
1217 Advanced: Short syntax for LuaAction return values
1219 name
= 'short.refused.advanced.tests.powerdns.com.'
1220 query
= dns
.message
.make_query(name
, 'A', 'IN')
1221 response
= dns
.message
.make_response(query
)
1222 rrset
= dns
.rrset
.from_text(name
,
1227 response
.answer
.append(rrset
)
1228 refusedResponse
= dns
.message
.make_response(query
)
1229 refusedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1231 for method
in ("sendUDPQuery", "sendTCPQuery"):
1232 sender
= getattr(self
, method
)
1233 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1234 self
.assertTrue(receivedResponse
)
1235 refusedResponse
.id = receivedResponse
.id
1236 self
.assertEqual(receivedResponse
, refusedResponse
)
1238 class TestAdvancedLuaTruncated(DNSDistTest
):
1240 _config_template
= """
1243 return DNSAction.Truncate, ""
1245 return DNSAction.None, ""
1247 addAction(AllRule(), LuaAction(trunc))
1248 newServer{address="127.0.0.1:%s"}
1251 def testTCViaLua(self
):
1253 Advanced: TC via Lua
1255 name
= 'tc.advanced.tests.powerdns.com.'
1256 query
= dns
.message
.make_query(name
, 'A', 'IN')
1257 # dnsdist sets RA = RD for TC responses
1258 query
.flags
&= ~dns
.flags
.RD
1259 response
= dns
.message
.make_response(query
)
1260 rrset
= dns
.rrset
.from_text(name
,
1265 response
.answer
.append(rrset
)
1267 truncatedResponse
= dns
.message
.make_response(query
)
1268 truncatedResponse
.flags |
= dns
.flags
.TC
1270 (_
, receivedResponse
) = self
.sendUDPQuery(query
, response
=None, useQueue
=False)
1271 self
.assertTrue(receivedResponse
)
1272 truncatedResponse
.id = receivedResponse
.id
1273 self
.assertEqual(receivedResponse
, truncatedResponse
)
1275 # no truncation over TCP
1276 (receivedQuery
, receivedResponse
) = self
.sendTCPQuery(query
, response
)
1277 self
.assertTrue(receivedQuery
)
1278 self
.assertTrue(receivedResponse
)
1279 receivedQuery
.id = query
.id
1280 self
.assertEqual(query
, receivedQuery
)
1281 self
.assertEqual(receivedResponse
, response
)
1283 class TestStatNodeRespRingSince(DNSDistTest
):
1285 _consoleKey
= DNSDistTest
.generateConsoleKey()
1286 _consoleKeyB64
= base64
.b64encode(_consoleKey
).decode('ascii')
1287 _config_params
= ['_consoleKeyB64', '_consolePort', '_testServerPort']
1288 _config_template
= """
1290 controlSocket("127.0.0.1:%s")
1291 s1 = newServer{address="127.0.0.1:%s"}
1293 function visitor(node, self, childstat)
1294 table.insert(nodesSeen, node.fullname)
1298 def testStatNodeRespRingSince(self
):
1300 Advanced: StatNodeRespRing with optional since parameter
1303 name
= 'statnodesince.advanced.tests.powerdns.com.'
1304 query
= dns
.message
.make_query(name
, 'A', 'IN')
1305 response
= dns
.message
.make_response(query
)
1306 rrset
= dns
.rrset
.from_text(name
,
1311 response
.answer
.append(rrset
)
1313 (receivedQuery
, receivedResponse
) = self
.sendUDPQuery(query
, response
)
1314 self
.assertTrue(receivedQuery
)
1315 self
.assertTrue(receivedResponse
)
1316 receivedQuery
.id = query
.id
1317 self
.assertEqual(query
, receivedQuery
)
1318 self
.assertEqual(response
, receivedResponse
)
1320 self
.sendConsoleCommand("nodesSeen = {}")
1321 self
.sendConsoleCommand("statNodeRespRing(visitor)")
1322 nodes
= self
.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1323 nodes
= nodes
.strip("\n")
1324 self
.assertEqual(nodes
, """statnodesince.advanced.tests.powerdns.com.
1325 advanced.tests.powerdns.com.
1330 self
.sendConsoleCommand("nodesSeen = {}")
1331 self
.sendConsoleCommand("statNodeRespRing(visitor, 0)")
1332 nodes
= self
.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1333 nodes
= nodes
.strip("\n")
1334 self
.assertEqual(nodes
, """statnodesince.advanced.tests.powerdns.com.
1335 advanced.tests.powerdns.com.
1342 self
.sendConsoleCommand("nodesSeen = {}")
1343 self
.sendConsoleCommand("statNodeRespRing(visitor)")
1344 nodes
= self
.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1345 nodes
= nodes
.strip("\n")
1346 self
.assertEqual(nodes
, """statnodesince.advanced.tests.powerdns.com.
1347 advanced.tests.powerdns.com.
1352 self
.sendConsoleCommand("nodesSeen = {}")
1353 self
.sendConsoleCommand("statNodeRespRing(visitor, 5)")
1354 nodes
= self
.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1355 nodes
= nodes
.strip("\n")
1356 self
.assertEqual(nodes
, """""")
1358 self
.sendConsoleCommand("nodesSeen = {}")
1359 self
.sendConsoleCommand("statNodeRespRing(visitor, 10)")
1360 nodes
= self
.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str")
1361 nodes
= nodes
.strip("\n")
1362 self
.assertEqual(nodes
, """statnodesince.advanced.tests.powerdns.com.
1363 advanced.tests.powerdns.com.
1368 class TestAdvancedRD(DNSDistTest
):
1370 _config_template
= """
1371 addAction(RDRule(), RCodeAction(DNSRCode.REFUSED))
1372 newServer{address="127.0.0.1:%s"}
1375 def testAdvancedRDRefused(self
):
1377 Advanced: RD query is refused
1379 name
= 'rd.advanced.tests.powerdns.com.'
1380 query
= dns
.message
.make_query(name
, 'A', 'IN')
1381 expectedResponse
= dns
.message
.make_response(query
)
1382 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1383 expectedResponse
.flags |
= dns
.flags
.RA
1385 for method
in ("sendUDPQuery", "sendTCPQuery"):
1386 sender
= getattr(self
, method
)
1387 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1388 self
.assertEqual(receivedResponse
, expectedResponse
)
1390 def testAdvancedNoRDAllowed(self
):
1392 Advanced: No-RD query is allowed
1394 name
= 'no-rd.advanced.tests.powerdns.com.'
1395 query
= dns
.message
.make_query(name
, 'A', 'IN')
1396 query
.flags
&= ~dns
.flags
.RD
1397 response
= dns
.message
.make_response(query
)
1399 for method
in ("sendUDPQuery", "sendTCPQuery"):
1400 sender
= getattr(self
, method
)
1401 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1402 receivedQuery
.id = query
.id
1403 self
.assertEqual(receivedQuery
, query
)
1404 self
.assertEqual(receivedResponse
, response
)
1406 class TestAdvancedGetLocalPort(DNSDistTest
):
1408 _config_template
= """
1409 function answerBasedOnLocalPort(dq)
1410 local port = dq.localaddr:getPort()
1411 return DNSAction.Spoof, "port-was-"..port..".local-port.advanced.tests.powerdns.com."
1413 addAction("local-port.advanced.tests.powerdns.com.", LuaAction(answerBasedOnLocalPort))
1414 newServer{address="127.0.0.1:%s"}
1417 def testAdvancedGetLocalPort(self
):
1419 Advanced: Return CNAME containing the local port
1421 name
= 'local-port.advanced.tests.powerdns.com.'
1422 query
= dns
.message
.make_query(name
, 'A', 'IN')
1423 # dnsdist set RA = RD for spoofed responses
1424 query
.flags
&= ~dns
.flags
.RD
1426 response
= dns
.message
.make_response(query
)
1427 rrset
= dns
.rrset
.from_text(name
,
1430 dns
.rdatatype
.CNAME
,
1431 'port-was-{}.local-port.advanced.tests.powerdns.com.'.format(self
._dnsDistPort
))
1432 response
.answer
.append(rrset
)
1434 for method
in ("sendUDPQuery", "sendTCPQuery"):
1435 sender
= getattr(self
, method
)
1436 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1437 self
.assertEqual(receivedResponse
, response
)
1439 class TestAdvancedGetLocalPortOnAnyBind(DNSDistTest
):
1441 _config_template
= """
1442 function answerBasedOnLocalPort(dq)
1443 local port = dq.localaddr:getPort()
1444 return DNSAction.Spoof, "port-was-"..port..".local-port-any.advanced.tests.powerdns.com."
1446 addAction("local-port-any.advanced.tests.powerdns.com.", LuaAction(answerBasedOnLocalPort))
1447 newServer{address="127.0.0.1:%s"}
1449 _dnsDistListeningAddr
= "0.0.0.0"
1451 def testAdvancedGetLocalPortOnAnyBind(self
):
1453 Advanced: Return CNAME containing the local port for an ANY bind
1455 name
= 'local-port-any.advanced.tests.powerdns.com.'
1456 query
= dns
.message
.make_query(name
, 'A', 'IN')
1457 # dnsdist set RA = RD for spoofed responses
1458 query
.flags
&= ~dns
.flags
.RD
1460 response
= dns
.message
.make_response(query
)
1461 rrset
= dns
.rrset
.from_text(name
,
1464 dns
.rdatatype
.CNAME
,
1465 'port-was-{}.local-port-any.advanced.tests.powerdns.com.'.format(self
._dnsDistPort
))
1466 response
.answer
.append(rrset
)
1468 for method
in ("sendUDPQuery", "sendTCPQuery"):
1469 sender
= getattr(self
, method
)
1470 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1471 self
.assertEqual(receivedResponse
, response
)
1473 class TestAdvancedGetLocalAddressOnAnyBind(DNSDistTest
):
1475 _config_template
= """
1476 function answerBasedOnLocalAddress(dq)
1477 local dest = tostring(dq.localaddr)
1478 local i, j = string.find(dest, "[0-9.]+")
1479 local addr = string.sub(dest, i, j)
1480 local dashAddr = string.gsub(addr, "[.]", "-")
1481 return DNSAction.Spoof, "address-was-"..dashAddr..".local-address-any.advanced.tests.powerdns.com."
1483 addAction("local-address-any.advanced.tests.powerdns.com.", LuaAction(answerBasedOnLocalAddress))
1484 newServer{address="127.0.0.1:%s"}
1486 _dnsDistListeningAddr
= "0.0.0.0"
1488 def testAdvancedGetLocalAddressOnAnyBind(self
):
1490 Advanced: Return CNAME containing the local address for an ANY bind
1492 name
= 'local-address-any.advanced.tests.powerdns.com.'
1493 query
= dns
.message
.make_query(name
, 'A', 'IN')
1494 # dnsdist set RA = RD for spoofed responses
1495 query
.flags
&= ~dns
.flags
.RD
1497 response
= dns
.message
.make_response(query
)
1498 rrset
= dns
.rrset
.from_text(name
,
1501 dns
.rdatatype
.CNAME
,
1502 'address-was-127-0-0-1.local-address-any.advanced.tests.powerdns.com.')
1503 response
.answer
.append(rrset
)
1505 for method
in ("sendUDPQuery", "sendTCPQuery"):
1506 sender
= getattr(self
, method
)
1507 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1508 self
.assertEqual(receivedResponse
, response
)
1510 class TestAdvancedLuaTempFailureTTL(DNSDistTest
):
1512 _config_template
= """
1513 function testAction(dq)
1514 if dq.tempFailureTTL ~= nil then
1515 return DNSAction.Spoof, "initially.not.nil.but." + dq.tempFailureTTL + ".tests.powerdns.com."
1517 dq.tempFailureTTL = 30
1518 if dq.tempFailureTTL ~= 30 then
1519 return DNSAction.Spoof, "after.set.not.expected.value.but." + dq.tempFailureTTL + ".tests.powerdns.com."
1521 dq.tempFailureTTL = nil
1522 if dq.tempFailureTTL ~= nil then
1523 return DNSAction.Spoof, "after.unset.not.nil.but." + dq.tempFailureTTL + ".tests.powerdns.com."
1525 return DNSAction.None, ""
1527 addAction(AllRule(), LuaAction(testAction))
1528 newServer{address="127.0.0.1:%s"}
1531 def testTempFailureTTLBinding(self
):
1533 Advanced: Exercise dq.tempFailureTTL Lua binding
1535 name
= 'tempfailurettlbinding.advanced.tests.powerdns.com.'
1536 query
= dns
.message
.make_query(name
, 'A', 'IN')
1537 response
= dns
.message
.make_response(query
)
1538 rrset
= dns
.rrset
.from_text(name
,
1543 response
.answer
.append(rrset
)
1545 for method
in ("sendUDPQuery", "sendTCPQuery"):
1546 sender
= getattr(self
, method
)
1547 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1548 self
.assertTrue(receivedQuery
)
1549 self
.assertTrue(receivedResponse
)
1550 receivedQuery
.id = query
.id
1551 self
.assertEqual(query
, receivedQuery
)
1552 self
.assertEqual(receivedResponse
, response
)
1554 class TestAdvancedEDNSOptionRule(DNSDistTest
):
1556 _config_template
= """
1557 newServer{address="127.0.0.1:%s"}
1558 addAction(EDNSOptionRule(EDNSOptionCode.ECS), DropAction())
1561 def testDropped(self
):
1563 Advanced: A question with ECS is dropped
1566 name
= 'ednsoptionrule.advanced.tests.powerdns.com.'
1568 ecso
= clientsubnetoption
.ClientSubnetOption('127.0.0.1', 24)
1569 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=True, options
=[ecso
], payload
=512)
1571 for method
in ("sendUDPQuery", "sendTCPQuery"):
1572 sender
= getattr(self
, method
)
1573 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1574 self
.assertEqual(receivedResponse
, None)
1576 def testReplied(self
):
1578 Advanced: A question without ECS is answered
1581 name
= 'ednsoptionrule.advanced.tests.powerdns.com.'
1584 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=True, options
=[], payload
=512)
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
.assertEqual(query
, receivedQuery
)
1595 self
.assertEqual(receivedResponse
, response
)
1597 # and with no EDNS at all
1598 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=False)
1599 response
= dns
.message
.make_response(query
)
1601 for method
in ("sendUDPQuery", "sendTCPQuery"):
1602 sender
= getattr(self
, method
)
1603 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1604 self
.assertTrue(receivedQuery
)
1605 self
.assertTrue(receivedResponse
)
1607 receivedQuery
.id = query
.id
1608 self
.assertEqual(query
, receivedQuery
)
1609 self
.assertEqual(receivedResponse
, response
)
1611 class TestAdvancedAllowHeaderOnly(DNSDistTest
):
1613 _config_template
= """
1614 newServer{address="127.0.0.1:%s"}
1615 setAllowEmptyResponse(true)
1618 def testHeaderOnlyRefused(self
):
1620 Advanced: Header-only refused response
1622 name
= 'header-only-refused-response.advanced.tests.powerdns.com.'
1623 query
= dns
.message
.make_query(name
, 'A', 'IN')
1624 response
= dns
.message
.make_response(query
)
1625 response
.set_rcode(dns
.rcode
.REFUSED
)
1626 response
.question
= []
1628 for method
in ("sendUDPQuery", "sendTCPQuery"):
1629 sender
= getattr(self
, method
)
1630 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1631 self
.assertTrue(receivedQuery
)
1632 receivedQuery
.id = query
.id
1633 self
.assertEqual(query
, receivedQuery
)
1634 self
.assertEqual(receivedResponse
, response
)
1636 def testHeaderOnlyNoErrorResponse(self
):
1638 Advanced: Header-only NoError response should be allowed
1640 name
= 'header-only-noerror-response.advanced.tests.powerdns.com.'
1641 query
= dns
.message
.make_query(name
, 'A', 'IN')
1642 response
= dns
.message
.make_response(query
)
1643 response
.question
= []
1645 for method
in ("sendUDPQuery", "sendTCPQuery"):
1646 sender
= getattr(self
, method
)
1647 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1648 self
.assertTrue(receivedQuery
)
1649 receivedQuery
.id = query
.id
1650 self
.assertEqual(query
, receivedQuery
)
1651 self
.assertEqual(receivedResponse
, response
)
1653 def testHeaderOnlyNXDResponse(self
):
1655 Advanced: Header-only NXD response should be allowed
1657 name
= 'header-only-nxd-response.advanced.tests.powerdns.com.'
1658 query
= dns
.message
.make_query(name
, 'A', 'IN')
1659 response
= dns
.message
.make_response(query
)
1660 response
.set_rcode(dns
.rcode
.NXDOMAIN
)
1661 response
.question
= []
1663 for method
in ("sendUDPQuery", "sendTCPQuery"):
1664 sender
= getattr(self
, method
)
1665 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1666 self
.assertTrue(receivedQuery
)
1667 receivedQuery
.id = query
.id
1668 self
.assertEqual(query
, receivedQuery
)
1669 self
.assertEqual(receivedResponse
, response
)
1671 class TestAdvancedEDNSVersionRule(DNSDistTest
):
1673 _config_template
= """
1674 newServer{address="127.0.0.1:%s"}
1675 addAction(EDNSVersionRule(0), ERCodeAction(DNSRCode.BADVERS))
1678 def testBadVers(self
):
1680 Advanced: A question with ECS version larger than 0 yields BADVERS
1683 name
= 'ednsversionrule.advanced.tests.powerdns.com.'
1685 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=1)
1686 query
.flags
&= ~dns
.flags
.RD
1687 expectedResponse
= dns
.message
.make_response(query
)
1688 expectedResponse
.set_rcode(dns
.rcode
.BADVERS
)
1690 for method
in ("sendUDPQuery", "sendTCPQuery"):
1691 sender
= getattr(self
, method
)
1692 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1693 self
.assertEqual(receivedResponse
, expectedResponse
)
1695 def testNoEDNS0Pass(self
):
1697 Advanced: A question with ECS version 0 goes through
1700 name
= 'ednsversionrule.advanced.tests.powerdns.com.'
1702 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=True)
1703 response
= dns
.message
.make_response(query
)
1705 for method
in ("sendUDPQuery", "sendTCPQuery"):
1706 sender
= getattr(self
, method
)
1707 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1708 receivedQuery
.id = query
.id
1709 self
.assertEqual(query
, receivedQuery
)
1710 self
.assertEqual(receivedResponse
, response
)
1712 def testReplied(self
):
1714 Advanced: A question without ECS goes through
1717 name
= 'ednsoptionrule.advanced.tests.powerdns.com.'
1719 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=False)
1720 response
= dns
.message
.make_response(query
)
1722 for method
in ("sendUDPQuery", "sendTCPQuery"):
1723 sender
= getattr(self
, method
)
1724 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1725 receivedQuery
.id = query
.id
1726 self
.assertEqual(query
, receivedQuery
)
1727 self
.assertEqual(receivedResponse
, response
)
1729 class TestSetRules(DNSDistTest
):
1731 _consoleKey
= DNSDistTest
.generateConsoleKey()
1732 _consoleKeyB64
= base64
.b64encode(_consoleKey
).decode('ascii')
1733 _config_params
= ['_consoleKeyB64', '_consolePort', '_testServerPort']
1734 _config_template
= """
1736 controlSocket("127.0.0.1:%s")
1737 newServer{address="127.0.0.1:%s"}
1738 addAction(AllRule(), SpoofAction("192.0.2.1"))
1741 def testClearThenSetRules(self
):
1743 Advanced: Clear rules, set rules
1746 name
= 'clearthensetrules.advanced.tests.powerdns.com.'
1747 query
= dns
.message
.make_query(name
, 'A', 'IN')
1748 # dnsdist set RA = RD for spoofed responses
1749 query
.flags
&= ~dns
.flags
.RD
1750 expectedResponse
= dns
.message
.make_response(query
)
1751 rrset
= dns
.rrset
.from_text(name
,
1756 expectedResponse
.answer
.append(rrset
)
1758 for method
in ("sendUDPQuery", "sendTCPQuery"):
1759 sender
= getattr(self
, method
)
1761 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1762 self
.assertTrue(receivedResponse
)
1763 self
.assertEqual(expectedResponse
, receivedResponse
)
1765 # clear all the rules, we should not be spoofing and get a SERVFAIL from the responder instead
1766 self
.sendConsoleCommand("clearRules()")
1768 expectedResponse
= dns
.message
.make_response(query
)
1769 expectedResponse
.set_rcode(dns
.rcode
.SERVFAIL
)
1771 for method
in ("sendUDPQuery", "sendTCPQuery"):
1772 sender
= getattr(self
, method
)
1774 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1775 self
.assertTrue(receivedResponse
)
1776 self
.assertEqual(expectedResponse
, receivedResponse
)
1778 # insert a new spoofing rule
1779 self
.sendConsoleCommand("setRules({ newRuleAction(AllRule(), SpoofAction(\"192.0.2.2\")) })")
1781 expectedResponse
= dns
.message
.make_response(query
)
1782 rrset
= dns
.rrset
.from_text(name
,
1787 expectedResponse
.answer
.append(rrset
)
1789 for method
in ("sendUDPQuery", "sendTCPQuery"):
1790 sender
= getattr(self
, method
)
1792 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1793 self
.assertTrue(receivedResponse
)
1794 self
.assertEqual(expectedResponse
, receivedResponse
)
1796 class TestAdvancedContinueAction(DNSDistTest
):
1798 _config_template
= """
1799 newServer{address="127.0.0.1:%s", pool="mypool"}
1800 addAction("nocontinue.continue-action.advanced.tests.powerdns.com.", PoolAction("mypool"))
1801 addAction("continue.continue-action.advanced.tests.powerdns.com.", ContinueAction(PoolAction("mypool")))
1802 addAction(AllRule(), SetDisableValidationAction())
1805 def testNoContinue(self
):
1807 Advanced: Query routed to pool, PoolAction should be terminal
1810 name
= 'nocontinue.continue-action.advanced.tests.powerdns.com.'
1812 query
= dns
.message
.make_query(name
, 'A', 'IN')
1813 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
1815 response
= dns
.message
.make_response(query
)
1816 expectedResponse
= dns
.message
.make_response(query
)
1818 for method
in ("sendUDPQuery", "sendTCPQuery"):
1819 sender
= getattr(self
, method
)
1820 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1821 self
.assertEqual(receivedQuery
, expectedQuery
)
1822 self
.assertEqual(receivedResponse
, expectedResponse
)
1824 def testNoContinue(self
):
1826 Advanced: Query routed to pool, ContinueAction() should not stop the processing
1829 name
= 'continue.continue-action.advanced.tests.powerdns.com.'
1831 query
= dns
.message
.make_query(name
, 'A', 'IN')
1832 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN')
1833 expectedQuery
.flags |
= dns
.flags
.CD
1835 response
= dns
.message
.make_response(query
)
1836 expectedResponse
= dns
.message
.make_response(query
)
1838 for method
in ("sendUDPQuery", "sendTCPQuery"):
1839 sender
= getattr(self
, method
)
1840 (receivedQuery
, receivedResponse
) = sender(query
, response
)
1841 expectedQuery
.id = receivedQuery
.id
1842 self
.assertEqual(receivedQuery
, expectedQuery
)
1843 self
.assertEqual(receivedResponse
, expectedResponse
)
1845 class TestAdvancedNegativeAndSOA(DNSDistTest
):
1847 _selfGeneratedPayloadSize
= 1232
1848 _config_template
= """
1849 addAction("nxd.negativeandsoa.advanced.tests.powerdns.com.", NegativeAndSOAAction(true, "auth.", 42, "mname", "rname", 5, 4, 3, 2, 1))
1850 addAction("nodata.negativeandsoa.advanced.tests.powerdns.com.", NegativeAndSOAAction(false, "another-auth.", 42, "mname", "rname", 1, 2, 3, 4, 5))
1851 setPayloadSizeOnSelfGeneratedAnswers(%d)
1852 newServer{address="127.0.0.1:%s"}
1854 _config_params
= ['_selfGeneratedPayloadSize', '_testServerPort']
1857 def testAdvancedNegativeAndSOANXD(self
):
1859 Advanced: NegativeAndSOAAction NXD
1861 name
= 'nxd.negativeandsoa.advanced.tests.powerdns.com.'
1863 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=False)
1864 query
.flags
&= ~dns
.flags
.RD
1865 expectedResponse
= dns
.message
.make_response(query
)
1866 expectedResponse
.set_rcode(dns
.rcode
.NXDOMAIN
)
1867 soa
= dns
.rrset
.from_text("auth.",
1871 'mname. rname. 5 4 3 2 1')
1872 expectedResponse
.additional
.append(soa
)
1874 for method
in ("sendUDPQuery", "sendTCPQuery"):
1875 sender
= getattr(self
, method
)
1876 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1877 self
.checkMessageNoEDNS(expectedResponse
, receivedResponse
)
1880 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=True)
1881 query
.flags
&= ~dns
.flags
.RD
1882 expectedResponse
= dns
.message
.make_response(query
, our_payload
=self
._selfGeneratedPayloadSize
)
1883 expectedResponse
.set_rcode(dns
.rcode
.NXDOMAIN
)
1884 soa
= dns
.rrset
.from_text("auth.",
1888 'mname. rname. 5 4 3 2 1')
1889 expectedResponse
.additional
.append(soa
)
1891 for method
in ("sendUDPQuery", "sendTCPQuery"):
1892 sender
= getattr(self
, method
)
1893 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1894 self
.checkMessageEDNSWithoutOptions(expectedResponse
, receivedResponse
)
1896 def testAdvancedNegativeAndSOANoData(self
):
1898 Advanced: NegativeAndSOAAction NoData
1900 name
= 'nodata.negativeandsoa.advanced.tests.powerdns.com.'
1902 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=False)
1903 query
.flags
&= ~dns
.flags
.RD
1904 expectedResponse
= dns
.message
.make_response(query
)
1905 expectedResponse
.set_rcode(dns
.rcode
.NOERROR
)
1906 soa
= dns
.rrset
.from_text("another-auth.",
1910 'mname. rname. 1 2 3 4 5')
1911 expectedResponse
.additional
.append(soa
)
1913 for method
in ("sendUDPQuery", "sendTCPQuery"):
1914 sender
= getattr(self
, method
)
1915 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1916 self
.checkMessageNoEDNS(expectedResponse
, receivedResponse
)
1919 query
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=True)
1920 query
.flags
&= ~dns
.flags
.RD
1921 expectedResponse
= dns
.message
.make_response(query
, our_payload
=self
._selfGeneratedPayloadSize
)
1922 expectedResponse
.set_rcode(dns
.rcode
.NOERROR
)
1923 soa
= dns
.rrset
.from_text("another-auth.",
1927 'mname. rname. 1 2 3 4 5')
1928 expectedResponse
.additional
.append(soa
)
1930 for method
in ("sendUDPQuery", "sendTCPQuery"):
1931 sender
= getattr(self
, method
)
1932 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1933 self
.checkMessageEDNSWithoutOptions(expectedResponse
, receivedResponse
)
1935 class TestAdvancedLuaRule(DNSDistTest
):
1937 _config_template
= """
1939 function luarulefunction(dq)
1940 if dq:getTag('a-tag') ~= 'a-value' then
1941 print('invalid tag value')
1945 if tostring(dq.qname) ~= 'lua-rule.advanced.tests.powerdns.com.' then
1946 print('invalid qname')
1953 addAction(AllRule(), SetTagAction('a-tag', 'a-value'))
1954 addAction(LuaRule(luarulefunction), RCodeAction(DNSRCode.NOTIMP))
1955 addAction(AllRule(), RCodeAction(DNSRCode.REFUSED))
1956 -- newServer{address="127.0.0.1:%s"}
1959 def testAdvancedLuaRule(self
):
1961 Advanced: Test the LuaRule rule
1963 name
= 'lua-rule.advanced.tests.powerdns.com.'
1964 query
= dns
.message
.make_query(name
, 'A', 'IN')
1965 # dnsdist set RA = RD for spoofed responses
1966 query
.flags
&= ~dns
.flags
.RD
1967 notimplResponse
= dns
.message
.make_response(query
)
1968 notimplResponse
.set_rcode(dns
.rcode
.NOTIMP
)
1970 for method
in ("sendUDPQuery", "sendTCPQuery"):
1971 sender
= getattr(self
, method
)
1972 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1973 self
.assertEqual(receivedResponse
, notimplResponse
)
1975 name
= 'not-lua-rule.advanced.tests.powerdns.com.'
1976 query
= dns
.message
.make_query(name
, 'A', 'IN')
1977 # dnsdist set RA = RD for spoofed responses
1978 query
.flags
&= ~dns
.flags
.RD
1979 refusedResponse
= dns
.message
.make_response(query
)
1980 refusedResponse
.set_rcode(dns
.rcode
.REFUSED
)
1982 for method
in ("sendUDPQuery", "sendTCPQuery"):
1983 sender
= getattr(self
, method
)
1984 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
1985 self
.assertEqual(receivedResponse
, refusedResponse
)
1987 class TestAdvancedLuaFFI(DNSDistTest
):
1989 _config_template
= """
1990 local ffi = require("ffi")
1992 local expectingUDP = true
1994 function luaffirulefunction(dq)
1995 local qtype = ffi.C.dnsdist_ffi_dnsquestion_get_qtype(dq)
1996 if qtype ~= DNSQType.A and qtype ~= DNSQType.SOA then
1997 print('invalid qtype')
2001 local qclass = ffi.C.dnsdist_ffi_dnsquestion_get_qclass(dq)
2002 if qclass ~= DNSClass.IN then
2003 print('invalid qclass')
2007 local ret_ptr = ffi.new("char *[1]")
2008 local ret_ptr_param = ffi.cast("const char **", ret_ptr)
2009 local ret_size = ffi.new("size_t[1]")
2010 local ret_size_param = ffi.cast("size_t*", ret_size)
2011 ffi.C.dnsdist_ffi_dnsquestion_get_qname_raw(dq, ret_ptr_param, ret_size_param)
2012 if ret_size[0] ~= 36 then
2013 print('invalid length for the qname ')
2018 local expectedQname = string.char(6)..'luaffi'..string.char(8)..'advanced'..string.char(5)..'tests'..string.char(8)..'powerdns'..string.char(3)..'com'
2019 if ffi.string(ret_ptr[0]) ~= expectedQname then
2020 print('invalid qname')
2021 print(ffi.string(ret_ptr[0]))
2025 local rcode = ffi.C.dnsdist_ffi_dnsquestion_get_rcode(dq)
2027 print('invalid rcode')
2031 local opcode = ffi.C.dnsdist_ffi_dnsquestion_get_opcode(dq)
2032 if qtype == DNSQType.A and opcode ~= DNSOpcode.Query then
2033 print('invalid opcode')
2035 elseif qtype == DNSQType.SOA and opcode ~= DNSOpcode.Update then
2036 print('invalid opcode')
2040 local tcp = ffi.C.dnsdist_ffi_dnsquestion_get_tcp(dq)
2041 if expectingUDP == tcp then
2042 print('invalid tcp')
2045 expectingUDP = expectingUDP == false
2047 local dnssecok = ffi.C.dnsdist_ffi_dnsquestion_get_do(dq)
2048 if dnssecok ~= false then
2049 print('invalid DNSSEC OK')
2053 local len = ffi.C.dnsdist_ffi_dnsquestion_get_len(dq)
2055 print('invalid length')
2060 local tag = ffi.C.dnsdist_ffi_dnsquestion_get_tag(dq, 'a-tag')
2061 if ffi.string(tag) ~= 'a-value' then
2062 print('invalid tag value')
2063 print(ffi.string(tag))
2069 function luaffiactionfunction(dq)
2070 local qtype = ffi.C.dnsdist_ffi_dnsquestion_get_qtype(dq)
2071 if qtype == DNSQType.A then
2072 local str = "192.0.2.1"
2073 local buf = ffi.new("char[?]", #str + 1)
2075 ffi.C.dnsdist_ffi_dnsquestion_set_result(dq, buf, #str)
2076 return DNSAction.Spoof
2077 elseif qtype == DNSQType.SOA then
2078 ffi.C.dnsdist_ffi_dnsquestion_set_rcode(dq, DNSRCode.REFUSED)
2079 return DNSAction.Refused
2083 function luaffiactionsettag(dq)
2084 ffi.C.dnsdist_ffi_dnsquestion_set_tag(dq, 'a-tag', 'a-value')
2085 return DNSAction.None
2088 addAction(AllRule(), LuaFFIAction(luaffiactionsettag))
2089 addAction(LuaFFIRule(luaffirulefunction), LuaFFIAction(luaffiactionfunction))
2090 -- newServer{address="127.0.0.1:%s"}
2093 def testAdvancedLuaFFI(self
):
2095 Advanced: Test the Lua FFI interface
2097 name
= 'luaffi.advanced.tests.powerdns.com.'
2098 query
= dns
.message
.make_query(name
, 'A', 'IN')
2099 # dnsdist set RA = RD for spoofed responses
2100 query
.flags
&= ~dns
.flags
.RD
2102 response
= dns
.message
.make_response(query
)
2103 rrset
= dns
.rrset
.from_text(name
,
2108 response
.answer
.append(rrset
)
2110 for method
in ("sendUDPQuery", "sendTCPQuery"):
2111 sender
= getattr(self
, method
)
2112 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
2113 self
.assertEqual(receivedResponse
, response
)
2115 def testAdvancedLuaFFIUpdate(self
):
2117 Advanced: Test the Lua FFI interface via an update
2119 name
= 'luaffi.advanced.tests.powerdns.com.'
2120 query
= dns
.message
.make_query(name
, 'SOA', 'IN')
2121 query
.set_opcode(dns
.opcode
.UPDATE
)
2122 # dnsdist set RA = RD for spoofed responses
2123 query
.flags
&= ~dns
.flags
.RD
2125 response
= dns
.message
.make_response(query
)
2126 response
.set_rcode(dns
.rcode
.REFUSED
)
2128 for method
in ("sendUDPQuery", "sendTCPQuery"):
2129 sender
= getattr(self
, method
)
2130 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
2131 self
.assertEqual(receivedResponse
, response
)
2133 class TestAdvancedLuaFFIPerThread(DNSDistTest
):
2135 _config_template
= """
2137 local rulefunction = [[
2138 local ffi = require("ffi")
2141 local qtype = ffi.C.dnsdist_ffi_dnsquestion_get_qtype(dq)
2142 if qtype ~= DNSQType.A and qtype ~= DNSQType.SOA then
2143 print('invalid qtype')
2147 local qclass = ffi.C.dnsdist_ffi_dnsquestion_get_qclass(dq)
2148 if qclass ~= DNSClass.IN then
2149 print('invalid qclass')
2153 local ret_ptr = ffi.new("char *[1]")
2154 local ret_ptr_param = ffi.cast("const char **", ret_ptr)
2155 local ret_size = ffi.new("size_t[1]")
2156 local ret_size_param = ffi.cast("size_t*", ret_size)
2157 ffi.C.dnsdist_ffi_dnsquestion_get_qname_raw(dq, ret_ptr_param, ret_size_param)
2158 if ret_size[0] ~= 45 then
2159 print('invalid length for the qname ')
2164 local expectedQname = string.char(15)..'luaffiperthread'..string.char(8)..'advanced'..string.char(5)..'tests'..string.char(8)..'powerdns'..string.char(3)..'com'
2165 if ffi.string(ret_ptr[0]) ~= expectedQname then
2166 print('invalid qname')
2167 print(ffi.string(ret_ptr[0]))
2171 local rcode = ffi.C.dnsdist_ffi_dnsquestion_get_rcode(dq)
2173 print('invalid rcode')
2177 local opcode = ffi.C.dnsdist_ffi_dnsquestion_get_opcode(dq)
2178 if qtype == DNSQType.A and opcode ~= DNSOpcode.Query then
2179 print('invalid opcode')
2181 elseif qtype == DNSQType.SOA and opcode ~= DNSOpcode.Update then
2182 print('invalid opcode')
2186 local dnssecok = ffi.C.dnsdist_ffi_dnsquestion_get_do(dq)
2187 if dnssecok ~= false then
2188 print('invalid DNSSEC OK')
2192 local len = ffi.C.dnsdist_ffi_dnsquestion_get_len(dq)
2194 print('invalid length')
2199 local tag = ffi.C.dnsdist_ffi_dnsquestion_get_tag(dq, 'a-tag')
2200 if ffi.string(tag) ~= 'a-value' then
2201 print('invalid tag value')
2202 print(ffi.string(tag))
2210 local actionfunction = [[
2211 local ffi = require("ffi")
2214 local qtype = ffi.C.dnsdist_ffi_dnsquestion_get_qtype(dq)
2215 if qtype == DNSQType.A then
2216 local str = "192.0.2.1"
2217 local buf = ffi.new("char[?]", #str + 1)
2219 ffi.C.dnsdist_ffi_dnsquestion_set_result(dq, buf, #str)
2220 return DNSAction.Spoof
2221 elseif qtype == DNSQType.SOA then
2222 ffi.C.dnsdist_ffi_dnsquestion_set_rcode(dq, DNSRCode.REFUSED)
2223 return DNSAction.Refused
2228 local settagfunction = [[
2229 local ffi = require("ffi")
2232 ffi.C.dnsdist_ffi_dnsquestion_set_tag(dq, 'a-tag', 'a-value')
2233 return DNSAction.None
2237 addAction(AllRule(), LuaFFIPerThreadAction(settagfunction))
2238 addAction(LuaFFIPerThreadRule(rulefunction), LuaFFIPerThreadAction(actionfunction))
2239 -- newServer{address="127.0.0.1:%s"}
2242 def testAdvancedLuaPerthreadFFI(self
):
2244 Advanced: Test the Lua FFI per-thread interface
2246 name
= 'luaffiperthread.advanced.tests.powerdns.com.'
2247 query
= dns
.message
.make_query(name
, 'A', 'IN')
2248 # dnsdist set RA = RD for spoofed responses
2249 query
.flags
&= ~dns
.flags
.RD
2251 response
= dns
.message
.make_response(query
)
2252 rrset
= dns
.rrset
.from_text(name
,
2257 response
.answer
.append(rrset
)
2259 for method
in ("sendUDPQuery", "sendTCPQuery"):
2260 sender
= getattr(self
, method
)
2261 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
2262 self
.assertEqual(receivedResponse
, response
)
2264 def testAdvancedLuaFFIPerThreadUpdate(self
):
2266 Advanced: Test the Lua FFI per-thread interface via an update
2268 name
= 'luaffiperthread.advanced.tests.powerdns.com.'
2269 query
= dns
.message
.make_query(name
, 'SOA', 'IN')
2270 query
.set_opcode(dns
.opcode
.UPDATE
)
2271 # dnsdist set RA = RD for spoofed responses
2272 query
.flags
&= ~dns
.flags
.RD
2274 response
= dns
.message
.make_response(query
)
2275 response
.set_rcode(dns
.rcode
.REFUSED
)
2277 for method
in ("sendUDPQuery", "sendTCPQuery"):
2278 sender
= getattr(self
, method
)
2279 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
2280 self
.assertEqual(receivedResponse
, response
)
2282 class TestAdvancedDropEmptyQueries(DNSDistTest
):
2284 _config_template
= """
2285 setDropEmptyQueries(true)
2286 newServer{address="127.0.0.1:%s"}
2289 def testAdvancedDropEmptyQueries(self
):
2291 Advanced: Drop empty queries
2293 name
= 'drop-empty-queries.advanced.tests.powerdns.com.'
2294 query
= dns
.message
.Message()
2296 for method
in ("sendUDPQuery", "sendTCPQuery"):
2297 sender
= getattr(self
, method
)
2298 (_
, receivedResponse
) = sender(query
, response
=None, useQueue
=False)
2299 self
.assertEqual(receivedResponse
, None)
2301 class TestProtocols(DNSDistTest
):
2302 _config_template
= """
2303 function checkUDP(dq)
2304 if dq:getProtocol() ~= "Do53 UDP" then
2305 return DNSAction.Spoof, '1.2.3.4'
2307 return DNSAction.None
2310 function checkTCP(dq)
2311 if dq:getProtocol() ~= "Do53 TCP" then
2312 return DNSAction.Spoof, '1.2.3.4'
2314 return DNSAction.None
2317 addAction("udp.protocols.advanced.tests.powerdns.com.", LuaAction(checkUDP))
2318 addAction("tcp.protocols.advanced.tests.powerdns.com.", LuaAction(checkTCP))
2319 newServer{address="127.0.0.1:%s"}
2322 def testProtocolUDP(self
):
2324 Advanced: Test DNSQuestion.Protocol over UDP
2326 name
= 'udp.protocols.advanced.tests.powerdns.com.'
2327 query
= dns
.message
.make_query(name
, 'A', 'IN')
2328 response
= dns
.message
.make_response(query
)
2330 (receivedQuery
, receivedResponse
) = self
.sendUDPQuery(query
, response
)
2331 receivedQuery
.id = query
.id
2332 self
.assertEqual(receivedQuery
, query
)
2333 self
.assertEqual(receivedResponse
, response
)
2335 def testProtocolTCP(self
):
2337 Advanced: Test DNSQuestion.Protocol over TCP
2339 name
= 'tcp.protocols.advanced.tests.powerdns.com.'
2340 query
= dns
.message
.make_query(name
, 'A', 'IN')
2341 response
= dns
.message
.make_response(query
)
2343 (receivedQuery
, receivedResponse
) = self
.sendTCPQuery(query
, response
)
2344 receivedQuery
.id = query
.id
2345 self
.assertEqual(receivedQuery
, query
)
2346 self
.assertEqual(receivedResponse
, response
)