]> git.ipfire.org Git - thirdparty/pdns.git/blame - regression-tests.dnsdist/test_CacheMissActions.py
dnsdist: Add regression tests for the new cache-miss rules chain
[thirdparty/pdns.git] / regression-tests.dnsdist / test_CacheMissActions.py
CommitLineData
046a03e9
RG
1#!/usr/bin/env python
2import base64
3import time
4import dns
5from dnsdisttests import DNSDistTest, pickAvailablePort
6
7class TestCacheMissSelfAnswered(DNSDistTest):
8 _consoleKey = DNSDistTest.generateConsoleKey()
9 _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii')
10 _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort']
11
12 _config_template = """
13 setKey("%s")
14 controlSocket("127.0.0.1:%d")
15 newServer{address="127.0.0.1:%d"}
16
17 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
18 getPool(""):setCache(pc)
19 -- this does not really make sense on its own, but we might want
20 -- to refuse queries for a domain under attack if the anwer is not cached
21 addCacheMissAction(SuffixMatchNodeRule("refused.cache-miss.tests.powerdns.com."), RCodeAction(DNSRCode.REFUSED), {name="myFirstRule"})
22 """
23
24 def testRefusedWhenNotCached(self):
25 """
26 CacheMiss: Refused when not in cache
27 """
28 # check that the rule is in place
29 lines = self.sendConsoleCommand('showCacheMissRules()').splitlines()
30 self.assertEqual(len(lines), 2)
31 self.assertIn('myFirstRule', lines[1])
32
33 name = 'refused.cache-miss.tests.powerdns.com.'
34 query = dns.message.make_query(name, 'AAAA', 'IN')
35 # dnsdist set RA = RD for spoofed responses
36 query.flags &= ~dns.flags.RD
37 expectedResponse = dns.message.make_response(query)
38 expectedResponse.set_rcode(dns.rcode.REFUSED)
39
40 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
41 self.assertTrue(receivedResponse)
42 self.assertEqual(receivedResponse, expectedResponse)
43
44 # now we remove the rule
45 self.sendConsoleCommand('clearCacheMissRules()')
46 lines = self.sendConsoleCommand('showCacheMissRules()').splitlines()
47 self.assertEqual(len(lines), 1)
48
49 # get a response inserted into the cache
50 response = dns.message.make_response(query)
51 rrset = dns.rrset.from_text(name,
52 60,
53 dns.rdataclass.IN,
54 dns.rdatatype.AAAA,
55 '2001:db8::1')
56 response.answer.append(rrset)
57 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response=response)
58 self.assertTrue(receivedQuery)
59 self.assertTrue(receivedResponse)
60 receivedQuery.id = query.id
61 self.assertEqual(receivedQuery, query)
62 self.assertEqual(receivedResponse, response)
63
64 # add the rule back
65 self.sendConsoleCommand('addCacheMissAction(SuffixMatchNodeRule("refused.cache-miss.tests.powerdns.com."), RCodeAction(DNSRCode.REFUSED), {name="myFirstRule"})')
66 lines = self.sendConsoleCommand('showCacheMissRules()').splitlines()
67 self.assertEqual(len(lines), 2)
68 self.assertIn('myFirstRule', lines[1])
69
70 # and check that we do get the cached response
71 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
72 self.assertTrue(receivedResponse)
73 self.assertEqual(receivedResponse, response)
74
75class TestCacheMissGoToADifferentPool(DNSDistTest):
76 _consoleKey = DNSDistTest.generateConsoleKey()
77 _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii')
78 _testServer2Port = pickAvailablePort()
79 _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_testServer2Port']
80
81 _config_template = """
82 setKey("%s")
83 controlSocket("127.0.0.1:%d")
84
85 newServer{address="127.0.0.1:%d", pool="slow", name="slow"}
86 newServer{address="127.0.0.1:%d", pool="initial", name="initial"}
87
88 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
89 getPool("initial"):setCache(pc)
90 getPool("slow"):setCache(pc)
91
92 addAction(AllRule(), PoolAction("initial"))
93 -- this does not really make sense on its own, but we might want
94 -- to route queries for a domain under attack to a different pool
95 -- of 'best-effort' servers if the anwer is not cached
96 addCacheMissAction(SuffixMatchNodeRule("routed-to-slow.cache-miss.tests.powerdns.com."), PoolAction("slow"))
97 """
98
99 def testRoutedToSlowWhenNotCached(self):
100 """
101 CacheMiss: Routed to a different pool when not in cache
102 """
103 name = 'routed-to-slow.cache-miss.tests.powerdns.com.'
104 query = dns.message.make_query(name, 'AAAA', 'IN')
105 response = dns.message.make_response(query)
106 rrset = dns.rrset.from_text(name,
107 60,
108 dns.rdataclass.IN,
109 dns.rdatatype.AAAA,
110 '2001:db8::1')
111 response.answer.append(rrset)
112
113 # first query goes to the 'slow' server
114 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response=response)
115 self.assertTrue(receivedQuery)
116 self.assertTrue(receivedResponse)
117 receivedQuery.id = query.id
118 self.assertEqual(receivedQuery, query)
119 self.assertEqual(receivedResponse, response)
120
121 # the second one is a cache-hit
122 (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
123 self.assertTrue(receivedResponse)
124 self.assertEqual(receivedResponse, response)
125
126 backendLines = self.sendConsoleCommand('showServers()').splitlines(False)
127 self.assertEqual(len(backendLines), 4)
128 for line in backendLines:
129 if line.startswith('#') or line.startswith('All'):
130 continue
131 tokens = line.split()
132 self.assertEqual(len(tokens), 15)
133 pool = tokens[13]
134 queries = int(tokens[9])
135 if pool == 'slow':
136 self.assertEqual(queries, 1)
137 else:
138 self.assertEqual(queries, 0)