summaryrefslogtreecommitdiffstats
path: root/test-dnsdistdynblocks_hh.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test-dnsdistdynblocks_hh.cc')
-rw-r--r--test-dnsdistdynblocks_hh.cc355
1 files changed, 236 insertions, 119 deletions
diff --git a/test-dnsdistdynblocks_hh.cc b/test-dnsdistdynblocks_hh.cc
index dda6ff8..fbd24dd 100644
--- a/test-dnsdistdynblocks_hh.cc
+++ b/test-dnsdistdynblocks_hh.cc
@@ -1,11 +1,15 @@
+#ifndef BOOST_TEST_DYN_LINK
#define BOOST_TEST_DYN_LINK
+#endif
+
#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>
#include "dnsdist.hh"
#include "dnsdist-dynblocks.hh"
+#include "dnsdist-metrics.hh"
#include "dnsdist-rings.hh"
Rings g_rings;
@@ -15,9 +19,22 @@ shared_ptr<BPFFilter> g_defaultBPFFilter{nullptr};
BOOST_AUTO_TEST_SUITE(dnsdistdynblocks_hh)
-BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate) {
- dnsheader dh;
- memset(&dh, 0, sizeof(dh));
+struct TestFixture
+{
+ TestFixture()
+ {
+ g_rings.reset();
+ g_rings.init();
+ }
+ ~TestFixture()
+ {
+ g_rings.reset();
+ }
+};
+
+BOOST_FIXTURE_TEST_CASE(test_DynBlockRulesGroup_QueryRate, TestFixture) {
+ dnsheader dnsHeader{};
+ memset(&dnsHeader, 0, sizeof(dnsHeader));
DNSName qname("rings.powerdns.com.");
ComboAddress requestor1("192.0.2.1");
ComboAddress requestor2("192.0.2.2");
@@ -36,9 +53,6 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate) {
const auto action = DNSAction::Action::Drop;
const std::string reason = "Exceeded query rate";
- g_rings.reset();
- g_rings.init();
-
DynBlockRulesGroup dbrg;
dbrg.setQuiet(true);
@@ -54,10 +68,10 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate) {
g_dynblockNMG.setState(emptyNMG);
for (size_t idx = 0; idx < numberOfQueries; idx++) {
- g_rings.insertQuery(now, requestor1, qname, qtype, size, dh, protocol);
+ g_rings.insertQuery(now, requestor1, qname, qtype, size, dnsHeader, protocol);
/* we do not care about the response during that test, but we want to make sure
these do not interfere with the computation */
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), numberOfQueries);
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -76,8 +90,8 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate) {
g_dynblockNMG.setState(emptyNMG);
for (size_t idx = 0; idx < numberOfQueries; idx++) {
- g_rings.insertQuery(now, requestor1, qname, qtype, size, dh, protocol);
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertQuery(now, requestor1, qname, qtype, size, dnsHeader, protocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -108,8 +122,8 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate) {
for (size_t idx = 0; idx < numberOfQueries; idx++) {
struct timespec when = now;
when.tv_sec -= (9 - timeIdx);
- g_rings.insertQuery(when, requestor1, qname, qtype, size, dh, protocol);
- g_rings.insertResponse(when, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertQuery(when, requestor1, qname, qtype, size, dnsHeader, protocol);
+ g_rings.insertResponse(when, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries * numberOfSeconds);
@@ -154,11 +168,11 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate) {
}
}
-BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate_RangeV6) {
+BOOST_FIXTURE_TEST_CASE(test_DynBlockRulesGroup_QueryRate_RangeV6, TestFixture) {
/* Check that we correctly group IPv6 addresses from the same /64 subnet into the same
dynamic block entry, if instructed to do so */
- dnsheader dh;
- memset(&dh, 0, sizeof(dh));
+ dnsheader dnsHeader{};
+ memset(&dnsHeader, 0, sizeof(dnsHeader));
DNSName qname("rings.powerdns.com.");
ComboAddress requestor1("2001:db8::1");
ComboAddress backend("2001:0db8:ffff:ffff:ffff:ffff:ffff:ffff");
@@ -180,9 +194,6 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate_RangeV6) {
dbrg.setQuiet(true);
dbrg.setMasks(32, 64, 0);
- g_rings.reset();
- g_rings.init();
-
/* block above 50 qps for numberOfSeconds seconds, no warning */
dbrg.setQueryRate(50, 0, numberOfSeconds, reason, blockDuration, action);
@@ -195,10 +206,10 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate_RangeV6) {
g_dynblockNMG.setState(emptyNMG);
for (size_t idx = 0; idx < numberOfQueries; idx++) {
- g_rings.insertQuery(now, requestor1, qname, qtype, size, dh, protocol);
+ g_rings.insertQuery(now, requestor1, qname, qtype, size, dnsHeader, protocol);
/* we do not care about the response during that test, but we want to make sure
these do not interfere with the computation */
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), numberOfQueries);
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -218,8 +229,8 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate_RangeV6) {
for (size_t idx = 0; idx < numberOfQueries; idx++) {
ComboAddress requestor("2001:db8::" + std::to_string(idx));
- g_rings.insertQuery(now, requestor, qname, qtype, size, dh, protocol);
- g_rings.insertResponse(now, requestor, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertQuery(now, requestor, qname, qtype, size, dnsHeader, protocol);
+ g_rings.insertResponse(now, requestor, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -257,10 +268,10 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate_RangeV6) {
}
}
-BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate_V4Ports) {
+BOOST_FIXTURE_TEST_CASE(test_DynBlockRulesGroup_QueryRate_V4Ports, TestFixture) {
/* Check that we correctly split IPv4 addresses based on port ranges, when instructed to do so */
- dnsheader dh;
- memset(&dh, 0, sizeof(dh));
+ dnsheader dnsHeader{};
+ memset(&dnsHeader, 0, sizeof(dnsHeader));
DNSName qname("rings.powerdns.com.");
ComboAddress requestor1("192.0.2.1:42");
ComboAddress backend("192.0.2.254");
@@ -283,9 +294,6 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate_V4Ports) {
/* split v4 by ports using a /2 (0 - 16383, 16384 - 32767, 32768 - 49151, 49152 - 65535) */
dbrg.setMasks(32, 128, 2);
- g_rings.reset();
- g_rings.init();
-
/* block above 50 qps for numberOfSeconds seconds, no warning */
dbrg.setQueryRate(50, 0, numberOfSeconds, reason, blockDuration, action);
@@ -298,10 +306,10 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate_V4Ports) {
g_dynblockNMG.setState(emptyNMG);
for (size_t idx = 0; idx < numberOfQueries; idx++) {
- g_rings.insertQuery(now, requestor1, qname, qtype, size, dh, protocol);
+ g_rings.insertQuery(now, requestor1, qname, qtype, size, dnsHeader, protocol);
/* we do not care about the response during that test, but we want to make sure
these do not interfere with the computation */
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), numberOfQueries);
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -321,8 +329,8 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate_V4Ports) {
for (size_t idx = 0; idx < numberOfQueries; idx++) {
ComboAddress requestor("192.0.2.1:" + std::to_string(idx));
- g_rings.insertQuery(now, requestor, qname, qtype, size, dh, protocol);
- g_rings.insertResponse(now, requestor, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertQuery(now, requestor, qname, qtype, size, dnsHeader, protocol);
+ g_rings.insertResponse(now, requestor, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -370,8 +378,8 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate_V4Ports) {
for (size_t idx = 0; idx < numberOfQueries; idx++) {
ComboAddress requestor("192.0.2.1:" + std::to_string(idx));
- g_rings.insertQuery(now, requestor, qname, qtype, size, dh, protocol);
- g_rings.insertResponse(now, requestor, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertQuery(now, requestor, qname, qtype, size, dnsHeader, protocol);
+ g_rings.insertResponse(now, requestor, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -391,11 +399,11 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate_V4Ports) {
}
}
-BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate_responses) {
+BOOST_FIXTURE_TEST_CASE(test_DynBlockRulesGroup_QueryRate_responses, TestFixture) {
/* check that the responses are not accounted as queries when a
rcode rate rule is defined (sounds very specific but actually happened) */
- dnsheader dh;
- memset(&dh, 0, sizeof(dh));
+ dnsheader dnsHeader{};
+ memset(&dnsHeader, 0, sizeof(dnsHeader));
DNSName qname("rings.powerdns.com.");
ComboAddress requestor1("192.0.2.1");
ComboAddress requestor2("192.0.2.2");
@@ -438,10 +446,10 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate_responses) {
struct timespec when = now;
when.tv_sec -= (99 - timeIdx);
for (size_t idx = 0; idx < numberOfQueries; idx++) {
- g_rings.insertQuery(when, requestor1, qname, qtype, size, dh, protocol);
+ g_rings.insertQuery(when, requestor1, qname, qtype, size, dnsHeader, protocol);
/* we do not care about the response during that test, but we want to make sure
these do not interfere with the computation */
- g_rings.insertResponse(when, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(when, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), numberOfQueries * 100);
@@ -453,9 +461,9 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QueryRate_responses) {
}
}
-BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QTypeRate) {
- dnsheader dh;
- memset(&dh, 0, sizeof(dh));
+BOOST_FIXTURE_TEST_CASE(test_DynBlockRulesGroup_QTypeRate, TestFixture) {
+ dnsheader dnsHeader{};
+ memset(&dnsHeader, 0, sizeof(dnsHeader));
DNSName qname("rings.powerdns.com.");
ComboAddress requestor1("192.0.2.1");
ComboAddress requestor2("192.0.2.2");
@@ -473,8 +481,6 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QTypeRate) {
DynBlockRulesGroup dbrg;
dbrg.setQuiet(true);
- g_rings.reset();
- g_rings.init();
/* block above 50 qps for numberOfSeconds seconds, no warning */
dbrg.setQTypeRate(QType::AAAA, 50, 0, numberOfSeconds, reason, blockDuration, action);
@@ -488,7 +494,7 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QTypeRate) {
g_dynblockNMG.setState(emptyNMG);
for (size_t idx = 0; idx < numberOfQueries; idx++) {
- g_rings.insertQuery(now, requestor1, qname, qtype, size, dh, protocol);
+ g_rings.insertQuery(now, requestor1, qname, qtype, size, dnsHeader, protocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -506,7 +512,7 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QTypeRate) {
g_dynblockNMG.setState(emptyNMG);
for (size_t idx = 0; idx < numberOfQueries; idx++) {
- g_rings.insertQuery(now, requestor1, qname, QType::A, size, dh, protocol);
+ g_rings.insertQuery(now, requestor1, qname, QType::A, size, dnsHeader, protocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -524,7 +530,7 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QTypeRate) {
g_dynblockNMG.setState(emptyNMG);
for (size_t idx = 0; idx < numberOfQueries; idx++) {
- g_rings.insertQuery(now, requestor1, qname, qtype, size, dh, protocol);
+ g_rings.insertQuery(now, requestor1, qname, qtype, size, dnsHeader, protocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -543,9 +549,9 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_QTypeRate) {
}
-BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_RCodeRate) {
- dnsheader dh;
- memset(&dh, 0, sizeof(dh));
+BOOST_FIXTURE_TEST_CASE(test_DynBlockRulesGroup_RCodeRate, TestFixture) {
+ dnsheader dnsHeader{};
+ memset(&dnsHeader, 0, sizeof(dnsHeader));
DNSName qname("rings.powerdns.com.");
ComboAddress requestor1("192.0.2.1");
ComboAddress requestor2("192.0.2.2");
@@ -578,9 +584,9 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_RCodeRate) {
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 0U);
g_dynblockNMG.setState(emptyNMG);
- dh.rcode = rcode;
+ dnsHeader.rcode = rcode;
for (size_t idx = 0; idx < numberOfResponses; idx++) {
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), numberOfResponses);
@@ -596,9 +602,9 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_RCodeRate) {
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 0U);
g_dynblockNMG.setState(emptyNMG);
- dh.rcode = RCode::FormErr;
+ dnsHeader.rcode = RCode::FormErr;
for (size_t idx = 0; idx < numberOfResponses; idx++) {
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), numberOfResponses);
@@ -615,9 +621,9 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_RCodeRate) {
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 0U);
g_dynblockNMG.setState(emptyNMG);
- dh.rcode = rcode;
+ dnsHeader.rcode = rcode;
for (size_t idx = 0; idx < numberOfResponses; idx++) {
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), numberOfResponses);
@@ -636,9 +642,9 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_RCodeRate) {
}
-BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_RCodeRatio) {
- dnsheader dh;
- memset(&dh, 0, sizeof(dh));
+BOOST_FIXTURE_TEST_CASE(test_DynBlockRulesGroup_RCodeRatio, TestFixture) {
+ dnsheader dnsHeader{};
+ memset(&dnsHeader, 0, sizeof(dnsHeader));
DNSName qname("rings.powerdns.com.");
ComboAddress requestor1("192.0.2.1");
ComboAddress requestor2("192.0.2.2");
@@ -660,9 +666,6 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_RCodeRatio) {
DynBlockRulesGroup dbrg;
dbrg.setQuiet(true);
- g_rings.reset();
- g_rings.init();
-
/* block above 0.2 ServFail/Total ratio over numberOfSeconds seconds, no warning, minimum number of queries should be at least 51 */
dbrg.setRCodeRatio(rcode, 0.2, 0, numberOfSeconds, reason, blockDuration, action, 51);
@@ -673,13 +676,13 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_RCodeRatio) {
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 0U);
g_dynblockNMG.setState(emptyNMG);
- dh.rcode = rcode;
+ dnsHeader.rcode = rcode;
for (size_t idx = 0; idx < 20; idx++) {
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
- dh.rcode = RCode::NoError;
+ dnsHeader.rcode = RCode::NoError;
for (size_t idx = 0; idx < 80; idx++) {
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 100U);
@@ -694,9 +697,9 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_RCodeRatio) {
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 0U);
g_dynblockNMG.setState(emptyNMG);
- dh.rcode = RCode::FormErr;
+ dnsHeader.rcode = RCode::FormErr;
for (size_t idx = 0; idx < 50; idx++) {
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 50U);
@@ -712,13 +715,13 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_RCodeRatio) {
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 0U);
g_dynblockNMG.setState(emptyNMG);
- dh.rcode = rcode;
+ dnsHeader.rcode = rcode;
for (size_t idx = 0; idx < 21; idx++) {
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
- dh.rcode = RCode::NoError;
+ dnsHeader.rcode = RCode::NoError;
for (size_t idx = 0; idx < 79; idx++) {
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 100U);
@@ -742,13 +745,13 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_RCodeRatio) {
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 0U);
g_dynblockNMG.setState(emptyNMG);
- dh.rcode = rcode;
+ dnsHeader.rcode = rcode;
for (size_t idx = 0; idx < 11; idx++) {
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
- dh.rcode = RCode::NoError;
+ dnsHeader.rcode = RCode::NoError;
for (size_t idx = 0; idx < 39; idx++) {
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 50U);
@@ -758,9 +761,9 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_RCodeRatio) {
}
}
-BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_ResponseByteRate) {
- dnsheader dh;
- memset(&dh, 0, sizeof(dh));
+BOOST_FIXTURE_TEST_CASE(test_DynBlockRulesGroup_ResponseByteRate, TestFixture) {
+ dnsheader dnsHeader{};
+ memset(&dnsHeader, 0, sizeof(dnsHeader));
DNSName qname("rings.powerdns.com.");
ComboAddress requestor1("192.0.2.1");
ComboAddress requestor2("192.0.2.2");
@@ -782,9 +785,6 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_ResponseByteRate) {
DynBlockRulesGroup dbrg;
dbrg.setQuiet(true);
- g_rings.reset();
- g_rings.init();
-
/* block above 10kB/s for numberOfSeconds seconds, no warning */
dbrg.setResponseByteRate(10000, 0, numberOfSeconds, reason, blockDuration, action);
@@ -796,9 +796,9 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_ResponseByteRate) {
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 0U);
g_dynblockNMG.setState(emptyNMG);
- dh.rcode = rcode;
+ dnsHeader.rcode = rcode;
for (size_t idx = 0; idx < numberOfResponses; idx++) {
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), numberOfResponses);
@@ -814,9 +814,9 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_ResponseByteRate) {
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 0U);
g_dynblockNMG.setState(emptyNMG);
- dh.rcode = rcode;
+ dnsHeader.rcode = rcode;
for (size_t idx = 0; idx < numberOfResponses; idx++) {
- g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dh, backend, outgoingProtocol);
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), numberOfResponses);
@@ -832,12 +832,133 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_ResponseByteRate) {
BOOST_CHECK_EQUAL(block.blocks, 0U);
BOOST_CHECK_EQUAL(block.warning, false);
}
+}
+
+BOOST_FIXTURE_TEST_CASE(test_DynBlockRulesGroup_CacheMissRatio, TestFixture) {
+ dnsheader dnsHeader{};
+ memset(&dnsHeader, 0, sizeof(dnsHeader));
+ DNSName qname("rings.powerdns.com.");
+ ComboAddress requestor1("192.0.2.1");
+ ComboAddress requestor2("192.0.2.2");
+ ComboAddress backend("192.0.2.42");
+ ComboAddress cacheHit;
+ uint16_t qtype = QType::AAAA;
+ uint16_t size = 42;
+ dnsdist::Protocol outgoingProtocol = dnsdist::Protocol::DoUDP;
+ unsigned int responseTime = 100 * 1000; /* 100ms */
+ struct timespec now
+ {
+ };
+ gettime(&now);
+ NetmaskTree<DynBlock, AddressAndPortRange> emptyNMG;
+
+ time_t numberOfSeconds = 10;
+ unsigned int blockDuration = 60;
+ const auto action = DNSAction::Action::Drop;
+ const std::string reason = "Exceeded cache-miss ratio";
+
+ DynBlockRulesGroup dbrg;
+ dbrg.setQuiet(true);
+
+ /* block above 0.5 Cache-Miss/Total ratio over numberOfSeconds seconds, no warning, minimum number of queries should be at least 51, global cache hit at least 80% */
+ dnsdist::metrics::g_stats.cacheHits.store(80);
+ dnsdist::metrics::g_stats.cacheMisses.store(20);
+ dbrg.setCacheMissRatio(0.5, 0, numberOfSeconds, reason, blockDuration, action, 51, 0.8);
+
+ {
+ /* insert 50 cache misses and 50 cache hits from a given client in the last 10s
+ this should not trigger the rule */
+ g_rings.clear();
+ BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 0U);
+ g_dynblockNMG.setState(emptyNMG);
+
+ for (size_t idx = 0; idx < 20; idx++) {
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
+ }
+ for (size_t idx = 0; idx < 80; idx++) {
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, cacheHit, outgoingProtocol);
+ }
+ BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 100U);
+
+ dbrg.apply(now);
+ BOOST_CHECK_EQUAL(g_dynblockNMG.getLocal()->size(), 0U);
+ BOOST_CHECK(g_dynblockNMG.getLocal()->lookup(requestor1) == nullptr);
+ }
+
+ {
+ /* insert 51 cache misses and 49 hits from a given client in the last 10s
+ this should trigger the rule this time */
+ g_rings.clear();
+ BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 0U);
+ g_dynblockNMG.setState(emptyNMG);
+
+ for (size_t idx = 0; idx < 51; idx++) {
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
+ }
+ for (size_t idx = 0; idx < 49; idx++) {
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, cacheHit, outgoingProtocol);
+ }
+ BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 100U);
+
+ dbrg.apply(now);
+ BOOST_CHECK_EQUAL(g_dynblockNMG.getLocal()->size(), 1U);
+ BOOST_REQUIRE(g_dynblockNMG.getLocal()->lookup(requestor1) != nullptr);
+ BOOST_CHECK(g_dynblockNMG.getLocal()->lookup(requestor2) == nullptr);
+ const auto& block = g_dynblockNMG.getLocal()->lookup(requestor1)->second;
+ BOOST_CHECK_EQUAL(block.reason, reason);
+ BOOST_CHECK_EQUAL(block.until.tv_sec, now.tv_sec + blockDuration);
+ BOOST_CHECK(block.domain.empty());
+ BOOST_CHECK(block.action == action);
+ BOOST_CHECK_EQUAL(block.blocks, 0U);
+ BOOST_CHECK_EQUAL(block.warning, false);
+ }
+ {
+ /* insert 40 misses and 10 hits from a given client in the last 10s
+ this should NOT trigger the rule since we don't have more than 50 queries */
+ g_rings.clear();
+ BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 0U);
+ g_dynblockNMG.setState(emptyNMG);
+
+ for (size_t idx = 0; idx < 40; idx++) {
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
+ }
+ for (size_t idx = 0; idx < 10; idx++) {
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, cacheHit, outgoingProtocol);
+ }
+ BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 50U);
+
+ dbrg.apply(now);
+ BOOST_CHECK_EQUAL(g_dynblockNMG.getLocal()->size(), 0U);
+ BOOST_CHECK(g_dynblockNMG.getLocal()->lookup(requestor1) == nullptr);
+ }
+
+ /* the global cache-hit rate is too low, should not trigger */
+ dnsdist::metrics::g_stats.cacheHits.store(60);
+ dnsdist::metrics::g_stats.cacheMisses.store(40);
+ {
+ /* insert 51 cache misses and 49 hits from a given client in the last 10s */
+ g_rings.clear();
+ BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 0U);
+ g_dynblockNMG.setState(emptyNMG);
+
+ for (size_t idx = 0; idx < 51; idx++) {
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, backend, outgoingProtocol);
+ }
+ for (size_t idx = 0; idx < 49; idx++) {
+ g_rings.insertResponse(now, requestor1, qname, qtype, responseTime, size, dnsHeader, cacheHit, outgoingProtocol);
+ }
+ BOOST_CHECK_EQUAL(g_rings.getNumberOfResponseEntries(), 100U);
+
+ dbrg.apply(now);
+ BOOST_CHECK_EQUAL(g_dynblockNMG.getLocal()->size(), 0U);
+ BOOST_REQUIRE(g_dynblockNMG.getLocal()->lookup(requestor1) == nullptr);
+ }
}
-BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_Warning) {
- dnsheader dh;
- memset(&dh, 0, sizeof(dh));
+BOOST_FIXTURE_TEST_CASE(test_DynBlockRulesGroup_Warning, TestFixture) {
+ dnsheader dnsHeader{};
+ memset(&dnsHeader, 0, sizeof(dnsHeader));
DNSName qname("rings.powerdns.com.");
ComboAddress requestor1("192.0.2.1");
ComboAddress requestor2("192.0.2.2");
@@ -856,9 +977,6 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_Warning) {
DynBlockRulesGroup dbrg;
dbrg.setQuiet(true);
- g_rings.reset();
- g_rings.init();
-
/* warn above 20 qps for numberOfSeconds seconds, block above 50 qps */
dbrg.setQueryRate(50, 20, numberOfSeconds, reason, blockDuration, action);
@@ -871,7 +989,7 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_Warning) {
g_dynblockNMG.setState(emptyNMG);
for (size_t idx = 0; idx < numberOfQueries; idx++) {
- g_rings.insertQuery(now, requestor1, qname, qtype, size, dh, protocol);
+ g_rings.insertQuery(now, requestor1, qname, qtype, size, dnsHeader, protocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -889,7 +1007,7 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_Warning) {
g_dynblockNMG.setState(emptyNMG);
for (size_t idx = 0; idx < numberOfQueries; idx++) {
- g_rings.insertQuery(now, requestor1, qname, qtype, size, dh, protocol);
+ g_rings.insertQuery(now, requestor1, qname, qtype, size, dnsHeader, protocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -917,7 +1035,7 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_Warning) {
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), 0U);
for (size_t idx = 0; idx < numberOfQueries; idx++) {
- g_rings.insertQuery(now, requestor1, qname, qtype, size, dh, protocol);
+ g_rings.insertQuery(now, requestor1, qname, qtype, size, dnsHeader, protocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -946,7 +1064,7 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_Warning) {
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), 0U);
for (size_t idx = 0; idx < numberOfQueries; idx++) {
- g_rings.insertQuery(now, requestor1, qname, qtype, size, dh, protocol);
+ g_rings.insertQuery(now, requestor1, qname, qtype, size, dnsHeader, protocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -977,7 +1095,7 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_Warning) {
g_dynblockNMG.setState(emptyNMG);
for (size_t idx = 0; idx < numberOfQueries; idx++) {
- g_rings.insertQuery(now, requestor1, qname, qtype, size, dh, protocol);
+ g_rings.insertQuery(now, requestor1, qname, qtype, size, dnsHeader, protocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries);
@@ -998,9 +1116,9 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_Warning) {
}
}
-BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_Ranges) {
- dnsheader dh;
- memset(&dh, 0, sizeof(dh));
+BOOST_FIXTURE_TEST_CASE(test_DynBlockRulesGroup_Ranges, TestFixture) {
+ dnsheader dnsHeader{};
+ memset(&dnsHeader, 0, sizeof(dnsHeader));
DNSName qname("rings.powerdns.com.");
ComboAddress requestor1("192.0.2.1");
ComboAddress requestor2("192.0.2.42");
@@ -1026,9 +1144,6 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_Ranges) {
/* block above 50 qps for numberOfSeconds seconds, no warning */
dbrg.setQueryRate(50, 0, numberOfSeconds, reason, blockDuration, action);
- g_rings.reset();
- g_rings.init();
-
{
/* insert just above 50 qps from the two clients in the last 10s
this should trigger the rule for the first one but not the second one */
@@ -1038,8 +1153,8 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_Ranges) {
g_dynblockNMG.setState(emptyNMG);
for (size_t idx = 0; idx < numberOfQueries; idx++) {
- g_rings.insertQuery(now, requestor1, qname, qtype, size, dh, protocol);
- g_rings.insertQuery(now, requestor2, qname, qtype, size, dh, protocol);
+ g_rings.insertQuery(now, requestor1, qname, qtype, size, dnsHeader, protocol);
+ g_rings.insertQuery(now, requestor2, qname, qtype, size, dnsHeader, protocol);
}
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), numberOfQueries * 2);
@@ -1058,9 +1173,9 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesGroup_Ranges) {
}
-BOOST_AUTO_TEST_CASE(test_DynBlockRulesMetricsCache_GetTopN) {
- dnsheader dh;
- memset(&dh, 0, sizeof(dh));
+BOOST_FIXTURE_TEST_CASE(test_DynBlockRulesMetricsCache_GetTopN, TestFixture) {
+ dnsheader dnsHeader{};
+ memset(&dnsHeader, 0, sizeof(dnsHeader));
DNSName qname("rings.powerdns.com.");
uint16_t qtype = QType::AAAA;
uint16_t size = 42;
@@ -1094,7 +1209,7 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesMetricsCache_GetTopN) {
*/
for (size_t idx = 0; idx < 256; idx++) {
const ComboAddress requestor("192.0.2." + std::to_string(idx));
- g_rings.insertQuery(now, requestor, qname, qtype, size, dh, protocol);
+ g_rings.insertQuery(now, requestor, qname, qtype, size, dnsHeader, protocol);
}
/* we apply the rules, all clients should be blocked */
@@ -1142,15 +1257,15 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesMetricsCache_GetTopN) {
dbrg.setSuffixMatchRule(numberOfSeconds, reason, blockDuration, action, [](const StatNode& node, const StatNode::Stat& self, const StatNode::Stat& children) {
if (self.queries > 0) {
- return std::tuple<bool, boost::optional<std::string>>(true, boost::none);
+ return std::tuple<bool, boost::optional<std::string>, boost::optional<int>>(true, boost::none, boost::none);
}
- return std::tuple<bool, boost::optional<std::string>>(false, boost::none);
+ return std::tuple<bool, boost::optional<std::string>, boost::optional<int>>(false, boost::none, boost::none);
});
/* insert one fake response for 255 DNS names */
const ComboAddress requestor("192.0.2.1");
for (size_t idx = 0; idx < 256; idx++) {
- g_rings.insertResponse(now, requestor, DNSName(std::to_string(idx)) + qname, qtype, 1000 /*usec*/, size, dh, requestor /* backend, technically, but we don't care */, outgoingProtocol);
+ g_rings.insertResponse(now, requestor, DNSName(std::to_string(idx)) + qname, qtype, 1000 /*usec*/, size, dnsHeader, requestor /* backend, technically, but we don't care */, outgoingProtocol);
}
/* we apply the rules, all suffixes should be blocked */
@@ -1160,6 +1275,7 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesMetricsCache_GetTopN) {
const DNSName name(DNSName(std::to_string(idx)) + qname);
const auto* block = g_dynblockSMT.getLocal()->lookup(name);
BOOST_REQUIRE(block != nullptr);
+ BOOST_REQUIRE(block->action == action);
/* simulate that:
- 1.rings.powerdns.com. got 1 query
...
@@ -1198,15 +1314,15 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesMetricsCache_GetTopN) {
dbrg.setSuffixMatchRule(numberOfSeconds, reason, blockDuration, action, [](const StatNode& node, const StatNode::Stat& self, const StatNode::Stat& children) {
if (self.queries > 0) {
- return std::tuple<bool, boost::optional<std::string>>(true, "blocked for a different reason");
+ return std::tuple<bool, boost::optional<std::string>, boost::optional<int>>(true, "blocked for a different reason", static_cast<int>(DNSAction::Action::Truncate));
}
- return std::tuple<bool, boost::optional<std::string>>(false, boost::none);
+ return std::tuple<bool, boost::optional<std::string>, boost::optional<int>>(false, boost::none, boost::none);
});
/* insert one fake response for 255 DNS names */
const ComboAddress requestor("192.0.2.1");
for (size_t idx = 0; idx < 256; idx++) {
- g_rings.insertResponse(now, requestor, DNSName(std::to_string(idx)) + qname, qtype, 1000 /*usec*/, size, dh, requestor /* backend, technically, but we don't care */, dnsdist::Protocol::DoUDP);
+ g_rings.insertResponse(now, requestor, DNSName(std::to_string(idx)) + qname, qtype, 1000 /*usec*/, size, dnsHeader, requestor /* backend, technically, but we don't care */, dnsdist::Protocol::DoUDP);
}
/* we apply the rules, all suffixes should be blocked */
@@ -1216,6 +1332,7 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesMetricsCache_GetTopN) {
const DNSName name(DNSName(std::to_string(idx)) + qname);
const auto* block = g_dynblockSMT.getLocal()->lookup(name);
BOOST_REQUIRE(block != nullptr);
+ BOOST_REQUIRE(block->action == DNSAction::Action::Truncate);
/* simulate that:
- 1.rings.powerdns.com. got 1 query
...
@@ -1255,9 +1372,9 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesMetricsCache_GetTopN) {
dbrg.setSuffixMatchRule(numberOfSeconds, reason, blockDuration, action, [](const StatNode& node, const StatNode::Stat& self, const StatNode::Stat& children) {
if (self.queries > 0) {
- return std::tuple<bool, boost::optional<std::string>>(true, boost::none);
+ return std::tuple<bool, boost::optional<std::string>, boost::optional<int>>(true, boost::none, boost::none);
}
- return std::tuple<bool, boost::optional<std::string>>(false, boost::none);
+ return std::tuple<bool, boost::optional<std::string>, boost::optional<int>>(false, boost::none, boost::none);
});
bool done = false;
@@ -1266,7 +1383,7 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesMetricsCache_GetTopN) {
for (size_t idxC = 0; !done && idxC < 256; idxC++) {
for (size_t idxD = 0; !done && idxD < 256; idxD++) {
const DNSName victim(std::to_string(idxB) + "." + std::to_string(idxC) + "." + std::to_string(idxD) + qname.toString());
- g_rings.insertResponse(now, requestor, victim, qtype, 1000 /*usec*/, size, dh, requestor /* backend, technically, but we don't care */, outgoingProtocol);
+ g_rings.insertResponse(now, requestor, victim, qtype, 1000 /*usec*/, size, dnsHeader, requestor /* backend, technically, but we don't care */, outgoingProtocol);
if (g_rings.getNumberOfQueryEntries() == 1000000) {
done = true;
break;
@@ -1311,7 +1428,7 @@ BOOST_AUTO_TEST_CASE(test_DynBlockRulesMetricsCache_GetTopN) {
for (size_t idxC = 0; !done && idxC < 256; idxC++) {
for (size_t idxD = 0; !done && idxD < 256; idxD++) {
const ComboAddress requestor("192." + std::to_string(idxB) + "." + std::to_string(idxC) + "." + std::to_string(idxD));
- g_rings.insertQuery(now, requestor, qname, qtype, size, dh, protocol);
+ g_rings.insertQuery(now, requestor, qname, qtype, size, dnsHeader, protocol);
if (g_rings.getNumberOfQueryEntries() == 1000000) {
done = true;
break;