From: Remi Gacogne Date: Fri, 11 Feb 2022 14:34:26 +0000 (+0100) Subject: dnsdist: Implement the ability to cap TTLs for some record types only X-Git-Tag: dnsdist-1.8.0-rc1~120^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6479f2e28b26cdcedfaf15f72dd3292ced908bd9;p=thirdparty%2Fpdns.git dnsdist: Implement the ability to cap TTLs for some record types only --- diff --git a/pdns/dnsdist-idstate.hh b/pdns/dnsdist-idstate.hh index 5b42f986f5..d11c5c4226 100644 --- a/pdns/dnsdist-idstate.hh +++ b/pdns/dnsdist-idstate.hh @@ -117,6 +117,7 @@ struct InternalQueryState InternalQueryState& operator=(const InternalQueryState& orig) = delete; boost::optional subnet{boost::none}; // 40 + std::set ttlCapTypes; ComboAddress origRemote; // 28 ComboAddress origDest; // 28 ComboAddress hopRemote; diff --git a/pdns/dnsdist-lua-actions.cc b/pdns/dnsdist-lua-actions.cc index 5d093bc25c..af6fec942f 100644 --- a/pdns/dnsdist-lua-actions.cc +++ b/pdns/dnsdist-lua-actions.cc @@ -2328,8 +2328,14 @@ void setupLuaActions(LuaContext& luaCtx) return std::shared_ptr(new LogResponseAction(fname ? *fname : "", append ? *append : false, buffered ? *buffered : false, verboseOnly ? *verboseOnly : true, includeTimestamp ? *includeTimestamp : false)); }); - luaCtx.writeFunction("LimitTTLResponseAction", [](uint32_t min, uint32_t max) { - return std::shared_ptr(new LimitTTLResponseAction(min, max)); + luaCtx.writeFunction("LimitTTLResponseAction", [](uint32_t min, uint32_t max, boost::optional> types) { + std::set capTypes; + if (types) { + for (const auto& [idx, type] : *types) { + capTypes.insert(QType(type)); + } + } + return std::shared_ptr(new LimitTTLResponseAction(min, max, capTypes)); }); luaCtx.writeFunction("SetMinTTLResponseAction", [](uint32_t min) { diff --git a/pdns/dnsdist-lua.hh b/pdns/dnsdist-lua.hh index 54049fa07b..abaf11904a 100644 --- a/pdns/dnsdist-lua.hh +++ b/pdns/dnsdist-lua.hh @@ -99,13 +99,17 @@ class LimitTTLResponseAction : public DNSResponseAction, public boost::noncopyab public: LimitTTLResponseAction() {} - LimitTTLResponseAction(uint32_t min, uint32_t max = std::numeric_limits::max()) : d_min(min), d_max(max) + LimitTTLResponseAction(uint32_t min, uint32_t max = std::numeric_limits::max(), std::set types = {}) : d_types(types), d_min(min), d_max(max) { } DNSResponseAction::Action operator()(DNSResponse* dr, std::string* ruleresult) const override { auto visitor = [&](uint8_t section, uint16_t qclass, uint16_t qtype, uint32_t ttl) { + if (!d_types.empty() && qclass == QClass::IN && d_types.count(qtype) == 0) { + return ttl; + } + if (d_min > 0) { if (ttl < d_min) { ttl = d_min; @@ -122,10 +126,27 @@ public: std::string toString() const override { - return "limit ttl (" + std::to_string(d_min) + " <= ttl <= " + std::to_string(d_max) + ")"; + std::string result = "limit ttl (" + std::to_string(d_min) + " <= ttl <= " + std::to_string(d_max); + if (!d_types.empty()) { + bool first = true; + result += ", types in ["; + for (const auto& type : d_types) { + if (first) { + first = false; + } + else { + result += " "; + } + result += type.toString(); + } + result += "]"; + } + result += + ")"; + return result; } private: + std::set d_types; uint32_t d_min{0}; uint32_t d_max{std::numeric_limits::max()}; }; diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index ddc933861b..2faeede4e1 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -554,7 +554,7 @@ bool processResponse(PacketBuffer& response, const std::vector 0) { std::string result; - LimitTTLResponseAction ac(0, dr.ids.ttlCap); + LimitTTLResponseAction ac(0, dr.ids.ttlCap, dr.ids.ttlCapTypes); ac(&dr, &result); } @@ -1226,7 +1226,7 @@ static bool prepareOutgoingResponse(LocalHolders& holders, ClientState& cs, DNSQ if (dr.ids.ttlCap > 0) { std::string result; - LimitTTLResponseAction ac(0, dr.ids.ttlCap); + LimitTTLResponseAction ac(0, dr.ids.ttlCap, dr.ids.ttlCapTypes); ac(&dr, &result); } diff --git a/pdns/dnsdistdist/dnsdist-lua-ffi-interface.h b/pdns/dnsdistdist/dnsdist-lua-ffi-interface.h index 3a509058a2..ee61517028 100644 --- a/pdns/dnsdistdist/dnsdist-lua-ffi-interface.h +++ b/pdns/dnsdistdist/dnsdist-lua-ffi-interface.h @@ -124,6 +124,8 @@ void dnsdist_ffi_dnsquestion_spoof_packet(dnsdist_ffi_dnsquestion_t* dq, const c /* decrease the returned TTL but _after_ inserting the original response into the packet cache */ void dnsdist_ffi_dnsquestion_set_max_returned_ttl(dnsdist_ffi_dnsquestion_t* dq, uint32_t max) __attribute__ ((visibility ("default"))); +/* add a record type to apply the TTL cap to (see above) */ +void dnsdist_ffi_dnsquestion_add_type_to_max_returned_ttl(dnsdist_ffi_dnsquestion_t* dr, uint16_t type) __attribute__ ((visibility ("default")));; typedef struct dnsdist_ffi_servers_list_t dnsdist_ffi_servers_list_t; typedef struct dnsdist_ffi_server_t dnsdist_ffi_server_t; @@ -146,6 +148,8 @@ void dnsdist_ffi_dnsresponse_set_max_ttl(dnsdist_ffi_dnsresponse_t* dr, uint32_t void dnsdist_ffi_dnsresponse_limit_ttl(dnsdist_ffi_dnsresponse_t* dr, uint32_t min, uint32_t max) __attribute__ ((visibility ("default"))); /* decrease the returned TTL but _after_ inserting the original response into the packet cache */ void dnsdist_ffi_dnsresponse_set_max_returned_ttl(dnsdist_ffi_dnsresponse_t* dr, uint32_t max) __attribute__ ((visibility ("default"))); +/* add a record type to apply the TTL cap to (see above) */ +void dnsdist_ffi_dnsresponse_add_type_to_max_returned_ttl(dnsdist_ffi_dnsresponse_t* dr, uint16_t type) __attribute__ ((visibility ("default")));; void dnsdist_ffi_dnsresponse_clear_records_type(dnsdist_ffi_dnsresponse_t* dr, uint16_t qtype) __attribute__ ((visibility ("default"))); typedef struct dnsdist_ffi_proxy_protocol_value { diff --git a/pdns/dnsdistdist/dnsdist-lua-ffi.cc b/pdns/dnsdistdist/dnsdist-lua-ffi.cc index a0f782710a..979e7f7627 100644 --- a/pdns/dnsdistdist/dnsdist-lua-ffi.cc +++ b/pdns/dnsdistdist/dnsdist-lua-ffi.cc @@ -549,6 +549,13 @@ void dnsdist_ffi_dnsquestion_set_max_returned_ttl(dnsdist_ffi_dnsquestion_t* dq, } } +void dnsdist_ffi_dnsquestion_add_type_to_max_returned_ttl(dnsdist_ffi_dnsquestion_t* dq, uint16_t type) +{ + if (dq != nullptr && dq->dq != nullptr) { + dq->dq->ids.ttlCapTypes.insert(type); + } +} + size_t dnsdist_ffi_servers_list_get_count(const dnsdist_ffi_servers_list_t* list) { return list->ffiServers.size(); @@ -642,6 +649,13 @@ void dnsdist_ffi_dnsresponse_set_max_returned_ttl(dnsdist_ffi_dnsresponse_t* dr, } } +void dnsdist_ffi_dnsresponse_add_type_to_max_returned_ttl(dnsdist_ffi_dnsresponse_t* dr, uint16_t type) +{ + if (dr != nullptr && dr->dr != nullptr) { + dr->dr->ids.ttlCapTypes.insert(type); + } +} + void dnsdist_ffi_dnsresponse_clear_records_type(dnsdist_ffi_dnsresponse_t* dr, uint16_t qtype) { if (dr != nullptr && dr->dr != nullptr) { diff --git a/pdns/dnsdistdist/docs/rules-actions.rst b/pdns/dnsdistdist/docs/rules-actions.rst index 8b0c017573..38bf7b564b 100644 --- a/pdns/dnsdistdist/docs/rules-actions.rst +++ b/pdns/dnsdistdist/docs/rules-actions.rst @@ -1089,7 +1089,7 @@ The following actions exist. :param KeyValueLookupKey lookupKey: The key to use for the lookup :param string destinationTag: The name of the tag to store the result into -.. function:: LimitTTLResponseAction(min[, max]) +.. function:: LimitTTLResponseAction(min[, max [, types]]) .. versionadded:: 1.8.0 @@ -1097,6 +1097,7 @@ The following actions exist. :param int min: The minimum allowed value :param int max: The maximum allowed value + :param list of int: The record types to cap the TTL for. Default is empty which means all records will be capped. .. function:: LogAction([filename[, binary[, append[, buffered[, verboseOnly[, includeTimestamp]]]]]])