From: Otto Moerbeek Date: Wed, 27 Mar 2019 12:17:06 +0000 (+0100) Subject: Add tests for ecs-cache-limit-ttl X-Git-Tag: dnsdist-1.4.0-alpha1~37^2~3 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2cbe6a45ec0699f5ced3eb45945ce77b3a7fa343;p=pdns Add tests for ecs-cache-limit-ttl --- diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index 712b5dae7..d89be18c9 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -4271,7 +4271,6 @@ int main(int argc, char **argv) ::arg().set("ecs-minimum-ttl-override", "Set under adverse conditions, a minimum TTL for records in ECS-specific answers")="0"; ::arg().set("ecs-cache-limit-ttl", "Minimum TTL to cache ECS response")="0"; ::arg().set("edns-subnet-whitelist", "List of netmasks and domains that we should enable EDNS subnet for")=""; - ::arg().set("edns-subnet-whitelist", "List of netmasks and domains that we should enable EDNS subnet for")=""; ::arg().set("ecs-add-for", "List of client netmasks for which EDNS Client Subnet will be added")="0.0.0.0/0, ::/0, " LOCAL_NETS_INVERSE; ::arg().set("ecs-scope-zero-address", "Address to send to whitelisted authoritative servers for incoming queries with ECS prefix-length source of 0")=""; ::arg().setSwitch( "use-incoming-edns-subnet", "Pass along received EDNS Client Subnet information")="no"; diff --git a/pdns/recursordist/docs/settings.rst b/pdns/recursordist/docs/settings.rst index a1b692b49..21a698a01 100644 --- a/pdns/recursordist/docs/settings.rst +++ b/pdns/recursordist/docs/settings.rst @@ -425,6 +425,8 @@ Can be set at runtime using ``rec_control set-ecs-minimum-ttl 3600``. ``ecs-cache-limit-ttl`` ----------------------- +.. versionadded:: 4.1.12 + - Integer - Default: 0 (disabled) diff --git a/pdns/recursordist/test-syncres_cc.cc b/pdns/recursordist/test-syncres_cc.cc index 322e792a8..a2ed49b8a 100644 --- a/pdns/recursordist/test-syncres_cc.cc +++ b/pdns/recursordist/test-syncres_cc.cc @@ -132,6 +132,7 @@ static void init(bool debug=false) SyncRes::s_ecsipv6limit = 56; SyncRes::s_ecsipv4cachelimit = 24; SyncRes::s_ecsipv6cachelimit = 56; + SyncRes::s_ecscachelimitttl = 0; SyncRes::s_rootNXTrust = true; SyncRes::s_minimumTTL = 0; SyncRes::s_minimumECSTTL = 0; @@ -2181,6 +2182,85 @@ BOOST_AUTO_TEST_CASE(test_ecs_cache_limit_denied) { BOOST_REQUIRE_EQUAL(cached.size(), 0); } +BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_allowed) { + std::unique_ptr sr; + initSR(sr); + + primeHints(); + + const DNSName target("www.powerdns.com."); + + SyncRes::addEDNSDomain(DNSName("powerdns.com.")); + + EDNSSubnetOpts incomingECS; + incomingECS.source = Netmask("192.0.2.128/32"); + sr->setQuerySource(ComboAddress(), boost::optional(incomingECS)); + SyncRes::s_ecscachelimitttl = 30; + + sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, LWResult* res, bool* chained) { + + BOOST_REQUIRE(srcmask); + BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24"); + + setLWResult(res, 0, true, false, true); + addRecordToLW(res, target, QType::A, "192.0.2.1"); + + return 1; + }); + + const time_t now = sr->getNow().tv_sec; + vector ret; + int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(ret.size(), 1); + + /* should have been cached */ + const ComboAddress who("192.0.2.128"); + vector cached; + BOOST_REQUIRE_GT(t_RC->get(now, target, QType(QType::A), true, &cached, who), 0); + BOOST_REQUIRE_EQUAL(cached.size(), 1); +} + +BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_notallowed) { + std::unique_ptr sr; + initSR(sr); + + primeHints(); + + const DNSName target("www.powerdns.com."); + + SyncRes::addEDNSDomain(DNSName("powerdns.com.")); + + EDNSSubnetOpts incomingECS; + incomingECS.source = Netmask("192.0.2.128/32"); + sr->setQuerySource(ComboAddress(), boost::optional(incomingECS)); + SyncRes::s_ecscachelimitttl = 100; + + sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, LWResult* res, bool* chained) { + + BOOST_REQUIRE(srcmask); + BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24"); + + setLWResult(res, 0, true, false, true); + addRecordToLW(res, target, QType::A, "192.0.2.1"); + + return 1; + }); + + const time_t now = sr->getNow().tv_sec; + vector ret; + int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(ret.size(), 1); + + /* should have NOT been cached because TTL of 60 is too small */ + const ComboAddress who("192.0.2.128"); + vector cached; + BOOST_REQUIRE_LT(t_RC->get(now, target, QType(QType::A), true, &cached, who), 0); + BOOST_REQUIRE_EQUAL(cached.size(), 0); +} + + BOOST_AUTO_TEST_CASE(test_ns_speed) { std::unique_ptr sr; initSR(sr); diff --git a/pdns/syncres.cc b/pdns/syncres.cc index c0412b388..52c75c8d2 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -121,8 +121,8 @@ static void accountAuthLatency(int usec, int family) SyncRes::SyncRes(const struct timeval& now) : d_authzonequeries(0), d_outqueries(0), d_tcpoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_unreachables(0), d_totUsec(0), d_now(now), d_cacheonly(false), d_doDNSSEC(false), d_doEDNS0(false), d_lm(s_lm) - -{ + +{ } /** everything begins here - this is the entry point just after receiving a packet */ @@ -435,10 +435,10 @@ uint64_t SyncRes::doDumpThrottleMap(int fd) Another cause of "No answer" may simply be a network condition. Nonsense answers are a clearer indication this host won't be able to do DNSSEC evah. - Previous implementations have suffered from turning off DNSSEC questions for an authoritative server based on timeouts. + Previous implementations have suffered from turning off DNSSEC questions for an authoritative server based on timeouts. A clever idea is to only turn off DNSSEC if we know a domain isn't signed anyhow. The problem with that really - clever idea however is that at this point in PowerDNS, we may simply not know that yet. All the DNSSEC thinking happens - elsewhere. It may not have happened yet. + clever idea however is that at this point in PowerDNS, we may simply not know that yet. All the DNSSEC thinking happens + elsewhere. It may not have happened yet. For now this means we can't be clever, but will turn off DNSSEC if you reply with FormError or gibberish. */ @@ -449,19 +449,19 @@ int SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsMANDATORY, con the goal is to get as many remotes as possible on the highest level of EDNS support The levels are: - 0) UNKNOWN Unknown state + 0) UNKNOWN Unknown state 1) EDNS: Honors EDNS0 2) EDNSIGNORANT: Ignores EDNS0, gives replies without EDNS0 3) NOEDNS: Generates FORMERR on EDNS queries Everybody starts out assumed to be '0'. If '0', send out EDNS0 - If you FORMERR us, go to '3', + If you FORMERR us, go to '3', If no EDNS in response, go to '2' If '1', send out EDNS0 If FORMERR, downgrade to 3 If '2', keep on including EDNS0, see what happens - Same behaviour as 0 + Same behaviour as 0 If '3', send bare queries */ @@ -485,7 +485,7 @@ int SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsMANDATORY, con int ret; for(int tries = 0; tries < 3; ++tries) { // cerr<<"Remote '"<modeSetAt) ednsstatus->modeSetAt=d_now.tv_sec; - // cerr<<"Result: ret="<d_haveEDNS<<", new mode: "<d_haveEDNS<<", new mode: "<