self.assertEqual(query, receivedQuery)
self.assertEqual(response, receivedResponse)
- def doTestRCodeRatio(self, name, rcode, noerrorcount, rcodecount):
+ def doTestRCodeRatioViaProtocol(self, name, rcode, noerrorcount, rcodecount, method, cached=False):
+ sender = sender = getattr(self, method)
query = dns.message.make_query(name, 'A', 'IN')
response = dns.message.make_response(query)
rrset = dns.rrset.from_text(name,
dns.rdatatype.A,
'192.0.2.1')
response.answer.append(rrset)
- expectedResponse = dns.message.make_response(query)
+ rcodeQuery = dns.message.make_query('rcode-' + name, 'A', 'IN')
+ expectedResponse = dns.message.make_response(rcodeQuery)
expectedResponse.set_rcode(rcode)
+ firstQuery = True
# start with normal responses
for _ in range(noerrorcount-1):
- (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
- receivedQuery.id = query.id
- self.assertEqual(query, receivedQuery)
- self.assertEqual(response, receivedResponse)
-
- waitForMaintenanceToRun()
-
- # we should NOT be dropped!
- (_, receivedResponse) = self.sendUDPQuery(query, response)
- self.assertEqual(receivedResponse, response)
-
- # now with rcode!
- sent = 0
- allowed = 0
- for _ in range(rcodecount):
- (receivedQuery, receivedResponse) = self.sendUDPQuery(query, expectedResponse)
- sent = sent + 1
- if receivedQuery:
+ if cached and not firstQuery:
+ # should be a cache hit
+ (receivedQuery, receivedResponse) = sender(query, response=None, useQueue=False)
+ self.assertEqual(receivedQuery, None)
+ else:
+ (receivedQuery, receivedResponse) = sender(query, response)
receivedQuery.id = query.id
self.assertEqual(query, receivedQuery)
- self.assertEqual(expectedResponse, receivedResponse)
- allowed = allowed + 1
- else:
- # the query has not reached the responder,
- # let's clear the response queue
- self.clearToResponderQueue()
-
- # we should have been able to send all our queries since the minimum number of queries is set to noerrorcount + rcodecount
- self.assertGreaterEqual(allowed, rcodecount)
-
- waitForMaintenanceToRun()
-
- # we should now be dropped for up to self._dynBlockDuration + self._dynBlockPeriod
- (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False, timeout=1)
- self.assertEqual(receivedResponse, None)
-
- # wait until we are not blocked anymore
- time.sleep(self._dynBlockDuration + self._dynBlockPeriod)
-
- # this one should succeed
- (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
- receivedQuery.id = query.id
- self.assertEqual(query, receivedQuery)
- self.assertEqual(response, receivedResponse)
-
- # again, over TCP this time
- # start with normal responses
- for _ in range(noerrorcount-1):
- (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
- receivedQuery.id = query.id
- self.assertEqual(query, receivedQuery)
self.assertEqual(response, receivedResponse)
+ firstQuery = False
waitForMaintenanceToRun()
# we should NOT be dropped!
- (_, receivedResponse) = self.sendUDPQuery(query, response)
+ if cached:
+ (_, receivedResponse) = sender(query, response=None, useQueue=False)
+ else:
+ (_, receivedResponse) = sender(query, response)
self.assertEqual(receivedResponse, response)
# now with rcode!
sent = 0
allowed = 0
for _ in range(rcodecount):
- (receivedQuery, receivedResponse) = self.sendTCPQuery(query, expectedResponse)
+ (receivedQuery, receivedResponse) = sender(rcodeQuery, expectedResponse)
sent = sent + 1
if receivedQuery:
- receivedQuery.id = query.id
- self.assertEqual(query, receivedQuery)
+ receivedQuery.id = rcodeQuery.id
+ self.assertEqual(rcodeQuery, receivedQuery)
self.assertEqual(expectedResponse, receivedResponse)
allowed = allowed + 1
else:
# the query has not reached the responder,
# let's clear the response queue
self.clearToResponderQueue()
+ if cached and receivedResponse:
+ allowed = allowed + 1
# we should have been able to send all our queries since the minimum number of queries is set to noerrorcount + rcodecount
self.assertGreaterEqual(allowed, rcodecount)
waitForMaintenanceToRun()
# we should now be dropped for up to self._dynBlockDuration + self._dynBlockPeriod
- (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False, timeout=0.5)
+ (_, receivedResponse) = sender(query, response=None, useQueue=False, timeout=1)
self.assertEqual(receivedResponse, None)
# wait until we are not blocked anymore
time.sleep(self._dynBlockDuration + self._dynBlockPeriod)
# this one should succeed
- (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
- receivedQuery.id = query.id
- self.assertEqual(query, receivedQuery)
+ if cached:
+ (_, receivedResponse) = sender(query, response=None, useQueue=False)
+ else:
+ (receivedQuery, receivedResponse) = sender(query, response)
+ receivedQuery.id = query.id
+ self.assertEqual(query, receivedQuery)
self.assertEqual(response, receivedResponse)
+ def doTestRCodeRatio(self, name, rcode, noerrorcount, rcodecount):
+ self.doTestRCodeRatioViaProtocol(name, rcode, noerrorcount, rcodecount, "sendUDPQuery")
+ self.doTestRCodeRatioViaProtocol(name, rcode, noerrorcount, rcodecount, "sendTCPQuery")
+
def doTestCacheMissRatio(self, name, cacheHits, cacheMisses):
rrset = dns.rrset.from_text(name,
60,
import time
import dns
from dnsdistDynBlockTests import DynBlocksTest, waitForMaintenanceToRun
+from dnsdisttests import pickAvailablePort
class TestDynBlockGroupServFailsRatio(DynBlocksTest):
name = 'servfailratio.group.dynblocks.tests.powerdns.com.'
self.doTestRCodeRatio(name, dns.rcode.SERVFAIL, 10, 10)
+class TestDynBlockGroupServFailsRatioDoQ(DynBlocksTest):
+
+ # we need this period to be quite long because we request the valid
+ # queries to be still looked at to reach the 20 queries count!
+ _dynBlockPeriod = 6
+ _dnsDistListeningAddr = "127.0.0.2"
+ _serverKey = 'server.key'
+ _serverCert = 'server.chain'
+ _serverName = 'tls.tests.dnsdist.org'
+ _caCert = 'ca.pem'
+ _doqServerPort = pickAvailablePort()
+ _config_template = """
+ local dbr = dynBlockRulesGroup()
+ dbr:setRCodeRatio(DNSRCode.SERVFAIL, 0.2, %d, "Exceeded query rate", %d, 20)
+
+ function maintenance()
+ dbr:apply()
+ end
+
+ addDOQLocal("%s:%d", "%s", "%s")
+ newServer{address="127.0.0.1:%d"}
+ """
+ _config_params = ['_dynBlockPeriod', '_dynBlockDuration', '_dnsDistListeningAddr', '_doqServerPort', '_serverCert', '_serverKey', '_testServerPort']
+
+ def testDynBlocksServFailRatio(self):
+ """
+ Dyn Blocks (group): Server Failure Ratio via DoQ
+ """
+ name = 'servfailratio-doq.group.dynblocks.tests.powerdns.com.'
+ self.doTestRCodeRatioViaProtocol(name, dns.rcode.SERVFAIL, 10, 10, "sendDOQQueryWrapper")
+
+class TestDynBlockGroupServFailsRatioDoQCacheHit(DynBlocksTest):
+
+ # we need this period to be quite long because we request the valid
+ # queries to be still looked at to reach the 20 queries count!
+ _dynBlockPeriod = 6
+ _dnsDistListeningAddr = "127.0.0.2"
+ _serverKey = 'server.key'
+ _serverCert = 'server.chain'
+ _serverName = 'tls.tests.dnsdist.org'
+ _caCert = 'ca.pem'
+ _doqServerPort = pickAvailablePort()
+ _config_template = """
+ local dbr = dynBlockRulesGroup()
+ dbr:setRCodeRatio(DNSRCode.SERVFAIL, 0.2, %d, "Exceeded query rate", %d, 20)
+
+ function maintenance()
+ dbr:apply()
+ end
+
+ local pc = newPacketCache(1000, {maxTTL=86400, minTTL=1})
+ getPool(""):setCache(pc)
+
+ addDOQLocal("%s:%d", "%s", "%s")
+ newServer{address="127.0.0.1:%d"}
+ """
+ _config_params = ['_dynBlockPeriod', '_dynBlockDuration', '_dnsDistListeningAddr', '_doqServerPort', '_serverCert', '_serverKey', '_testServerPort']
+
+ def testDynBlocksServFailRatio(self):
+ """
+ Dyn Blocks (group): Server Failure Ratio via DoQ (cache hits)
+ """
+ name = 'servfailratio-doq-hits.group.dynblocks.tests.powerdns.com.'
+ self.doTestRCodeRatioViaProtocol(name, dns.rcode.SERVFAIL, 10, 10, "sendDOQQueryWrapper", cached=True)
+
+class TestDynBlockGroupServFailsRatioDoH3(DynBlocksTest):
+
+ # we need this period to be quite long because we request the valid
+ # queries to be still looked at to reach the 20 queries count!
+ _dynBlockPeriod = 6
+ _dnsDistListeningAddr = "127.0.0.2"
+ _serverKey = 'server.key'
+ _serverCert = 'server.chain'
+ _serverName = 'tls.tests.dnsdist.org'
+ _caCert = 'ca.pem'
+ _doh3ServerPort = pickAvailablePort()
+ _dohBaseURL = ("https://%s:%d/" % (_serverName, _doh3ServerPort))
+ _config_template = """
+ local dbr = dynBlockRulesGroup()
+ dbr:setRCodeRatio(DNSRCode.SERVFAIL, 0.2, %d, "Exceeded query rate", %d, 20)
+
+ function maintenance()
+ dbr:apply()
+ end
+
+ addDOH3Local("%s:%d", "%s", "%s")
+ newServer{address="127.0.0.1:%d"}
+ """
+ _config_params = ['_dynBlockPeriod', '_dynBlockDuration', '_dnsDistListeningAddr', '_doh3ServerPort', '_serverCert', '_serverKey', '_testServerPort']
+
+ def testDynBlocksServFailRatio(self):
+ """
+ Dyn Blocks (group): Server Failure Ratio via DoH3
+ """
+ name = 'servfailratio-doh3.group.dynblocks.tests.powerdns.com.'
+ self.doTestRCodeRatioViaProtocol(name, dns.rcode.SERVFAIL, 10, 10, "sendDOH3QueryWrapper")
+
+class TestDynBlockGroupServFailsRatioDoH3CacheHit(DynBlocksTest):
+
+ # we need this period to be quite long because we request the valid
+ # queries to be still looked at to reach the 20 queries count!
+ _dynBlockPeriod = 6
+ _dnsDistListeningAddr = "127.0.0.2"
+ _serverKey = 'server.key'
+ _serverCert = 'server.chain'
+ _serverName = 'tls.tests.dnsdist.org'
+ _caCert = 'ca.pem'
+ _doh3ServerPort = pickAvailablePort()
+ _dohBaseURL = ("https://%s:%d/" % (_serverName, _doh3ServerPort))
+ _config_template = """
+ local dbr = dynBlockRulesGroup()
+ dbr:setRCodeRatio(DNSRCode.SERVFAIL, 0.2, %d, "Exceeded query rate", %d, 20)
+
+ function maintenance()
+ dbr:apply()
+ end
+
+ local pc = newPacketCache(1000, {maxTTL=86400, minTTL=1})
+ getPool(""):setCache(pc)
+
+ addDOH3Local("%s:%d", "%s", "%s")
+ newServer{address="127.0.0.1:%d"}
+ """
+ _config_params = ['_dynBlockPeriod', '_dynBlockDuration', '_dnsDistListeningAddr', '_doh3ServerPort', '_serverCert', '_serverKey', '_testServerPort']
+
+ def testDynBlocksServFailRatio(self):
+ """
+ Dyn Blocks (group): Server Failure Ratio via DoH3 (cache hits)
+ """
+ name = 'servfailratio-doh3-hits.group.dynblocks.tests.powerdns.com.'
+ self.doTestRCodeRatioViaProtocol(name, dns.rcode.SERVFAIL, 10, 10, "sendDOH3QueryWrapper", cached=True)
+
class TestDynBlockGroupCacheMissRatio(DynBlocksTest):
# we need this period to be quite long because we request the valid