_dynBlockDuration = _maintenanceWaitTime + 2
_config_params = ['_dynBlockQPS', '_dynBlockPeriod', '_dynBlockDuration', '_testServerPort']
- def doTestDynBlockViaAPI(self, ipRange, reason, minSeconds, maxSeconds, minBlocks, maxBlocks):
+ def doTestDynBlockViaAPI(self, ipRange, reason, minSeconds, maxSeconds, minBlocks, maxBlocks, ebpf=False):
headers = {'x-api-key': self._webServerAPIKey}
url = 'http://127.0.0.1:' + str(self._webServerPort) + '/jsonstat?command=dynblocklist'
r = requests.get(url, headers=headers, timeout=self._webTimeout)
self.assertIn(ipRange, content)
values = content[ipRange]
- for key in ['reason', 'seconds', 'blocks', 'action']:
+ for key in ['reason', 'seconds', 'blocks', 'action', 'ebpf']:
self.assertIn(key, values)
self.assertEqual(values['reason'], reason)
self.assertLessEqual(values['seconds'], maxSeconds)
self.assertGreaterEqual(values['blocks'], minBlocks)
self.assertLessEqual(values['blocks'], maxBlocks)
+ self.assertEqual(values['ebpf'], True if ebpf else False)
- def doTestQRate(self, name, testViaAPI=True):
+ def doTestQRate(self, name, testViaAPI=True, ebpf=False):
query = dns.message.make_query(name, 'A', 'IN')
response = dns.message.make_response(query)
rrset = dns.rrset.from_text(name,
self.assertEqual(receivedResponse, None)
if testViaAPI:
- self.doTestDynBlockViaAPI('127.0.0.1/32', 'Exceeded query rate', 1, self._dynBlockDuration, (sent-allowed)+1, (sent-allowed)+1)
+ self.doTestDynBlockViaAPI('127.0.0.1/32', 'Exceeded query rate', 1, self._dynBlockDuration, (sent-allowed)+1, (sent-allowed)+1, ebpf)
# wait until we are not blocked anymore
time.sleep(self._dynBlockDuration + self._dynBlockPeriod)
_answerUnexpected = True
_checkConfigExpectedOutput = None
_verboseMode = False
+ _sudoMode = False
_skipListeningOnCL = False
_alternateListeningAddr = None
_alternateListeningPort = None
if cls._verboseMode:
dnsdistcmd.append('-v')
+ if cls._sudoMode:
+ if 'LD_LIBRARY_PATH' in os.environ:
+ dnsdistcmd.insert(0, 'LD_LIBRARY_PATH=' + os.environ['LD_LIBRARY_PATH'])
+ dnsdistcmd.insert(0, 'sudo')
for acl in cls._acl:
dnsdistcmd.extend(['--acl', acl])
if useQueue:
cls._toResponderQueue.put(response, True, timeout)
- sock = cls.openTCPConnection(timeout)
+ try:
+ sock = cls.openTCPConnection(timeout)
+ except socket.timeout as e:
+ print("Timeout while opening TCP connection: %s" % (str(e)))
+ return (None, None)
try:
cls.sendTCPQueryOverConnection(sock, query, rawQuery)
--- /dev/null
+#!/usr/bin/env python
+import dns
+import os
+import unittest
+from dnsdisttests import DNSDistTest
+from dnsdistDynBlockTests import DynBlocksTest
+
+class EBPFTest(object):
+ pass
+
+@unittest.skipUnless('ENABLE_SUDO_TESTS' in os.environ, "sudo is not available")
+class TestDynBlockEBPFQPS(DynBlocksTest):
+
+ _config_template = """
+ bpf = newBPFFilter({ipv4MaxItems=10, ipv6MaxItems=10, qnamesMaxItems=10})
+ setDefaultBPFFilter(bpf)
+ local dbr = dynBlockRulesGroup()
+ dbr:setQueryRate(%d, %d, "Exceeded query rate", %d)
+ function maintenance()
+ dbr:apply()
+ end
+
+ -- not going to wait 60s!
+ setDynBlocksPurgeInterval(1)
+
+ -- exercise the manual blocking methods
+ bpf:block(newCA("2001:DB8::42"))
+ bpf:blockQName(newDNSName("powerdns.com."), 255)
+ bpf:getStats()
+ bpf:unblock(newCA("2001:DB8::42"))
+ bpf:unblockQName(newDNSName("powerdns.com."), 255)
+
+ newServer{address="127.0.0.1:%s"}
+ webserver("127.0.0.1:%s")
+ setWebserverConfig({password="%s", apiKey="%s"})
+ """
+ _config_params = ['_dynBlockQPS', '_dynBlockPeriod', '_dynBlockDuration', '_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKeyHashed']
+ _sudoMode = True
+
+ def testDynBlocksQRate(self):
+ """
+ Dyn Blocks: QRate
+ """
+ name = 'qrate.dynblocks.tests.powerdns.com.'
+ self.doTestQRate(name, ebpf=True)