From: Remi Gacogne Date: Mon, 13 Nov 2023 10:59:24 +0000 (+0100) Subject: dnsdist: Add a Lua hook called when a new dynamic block is inserted X-Git-Tag: rec-5.0.0-rc1~31^2~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b7217cf6e7dc5936580a124c4bd4e5c950a5e7e1;p=thirdparty%2Fpdns.git dnsdist: Add a Lua hook called when a new dynamic block is inserted --- diff --git a/pdns/dnsdist-dynblocks.hh b/pdns/dnsdist-dynblocks.hh index 25c1036c23..a8bd5ae613 100644 --- a/pdns/dnsdist-dynblocks.hh +++ b/pdns/dnsdist-dynblocks.hh @@ -44,7 +44,7 @@ struct LuaContext::Pusher { } }; -typedef std::function dnsdist_ffi_stat_node_visitor_t; +using dnsdist_ffi_stat_node_visitor_t = std::function; struct dnsdist_ffi_stat_node_t { @@ -58,6 +58,8 @@ struct dnsdist_ffi_stat_node_t std::optional& reason; }; +using dnsdist_ffi_dynamic_block_inserted_hook = std::function; + class DynBlockRulesGroup { private: @@ -273,6 +275,11 @@ public: d_smtVisitorFFI = std::move(visitor); } + void setNewBlockHook(dnsdist_ffi_dynamic_block_inserted_hook& callback) + { + d_newBlockHook = std::move(callback); + } + void setMasks(uint8_t v4, uint8_t v6, uint8_t port) { d_v4Mask = v4; @@ -404,6 +411,7 @@ private: SuffixMatchNode d_excludedDomains; smtVisitor_t d_smtVisitor; dnsdist_ffi_stat_node_visitor_t d_smtVisitorFFI; + dnsdist_ffi_dynamic_block_inserted_hook d_newBlockHook; uint8_t d_v6Mask{128}; uint8_t d_v4Mask{32}; uint8_t d_portMask{0}; diff --git a/pdns/dnsdist-lua-inspection.cc b/pdns/dnsdist-lua-inspection.cc index f1bb31fb16..105d422ea8 100644 --- a/pdns/dnsdist-lua-inspection.cc +++ b/pdns/dnsdist-lua-inspection.cc @@ -860,6 +860,11 @@ void setupLuaInspection(LuaContext& luaCtx) group->setSuffixMatchRuleFFI(seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, std::move(visitor)); } }); + luaCtx.registerFunction::*)(dnsdist_ffi_dynamic_block_inserted_hook)>("setNewBlockInsertedHook", [](std::shared_ptr& group, dnsdist_ffi_dynamic_block_inserted_hook hook) { + if (group) { + group->setNewBlockHook(hook); + } + }); luaCtx.registerFunction::*)(uint8_t, unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setRCodeRate", [](std::shared_ptr& group, uint8_t rcode, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { if (group) { group->setRCodeRate(rcode, rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None); diff --git a/pdns/dnsdistdist/dnsdist-dynblocks.cc b/pdns/dnsdistdist/dnsdist-dynblocks.cc index fbb2fefa2f..87ad7b4ae5 100644 --- a/pdns/dnsdistdist/dnsdist-dynblocks.cc +++ b/pdns/dnsdistdist/dnsdist-dynblocks.cc @@ -319,6 +319,14 @@ void DynBlockRulesGroup::addOrRefreshBlock(boost::optional(rule.d_action), rule.d_blockDuration, warning); + } + catch (const std::exception& exp) { + warnlog("Error calling the Lua hook after a dynamic block insertion: %s", exp.what()); + } + } } void DynBlockRulesGroup::addOrRefreshBlockSMT(SuffixMatchTree& blocks, const struct timespec& now, const DNSName& name, const DynBlockRule& rule, bool& updated) @@ -329,6 +337,14 @@ void DynBlockRulesGroup::addOrRefreshBlockSMT(SuffixMatchTree& blocks, } updated = dnsdist::DynamicBlocks::addOrRefreshBlockSMT(blocks, now, name, rule.d_blockReason, rule.d_blockDuration, rule.d_action, d_beQuiet); + if (updated && d_newBlockHook) { + try { + d_newBlockHook(dnsdist_ffi_dynamic_block_type_smt, name.toString().c_str(), rule.d_blockReason.c_str(), static_cast(rule.d_action), rule.d_blockDuration, false); + } + catch (const std::exception& exp) { + warnlog("Error calling the Lua hook after a dynamic block insertion: %s", exp.what()); + } + } } void DynBlockRulesGroup::processQueryRules(counts_t& counts, const struct timespec& now) diff --git a/pdns/dnsdistdist/dnsdist-lua-inspection-ffi.h b/pdns/dnsdistdist/dnsdist-lua-inspection-ffi.h index ca70eedaff..0ee42a3a32 100644 --- a/pdns/dnsdistdist/dnsdist-lua-inspection-ffi.h +++ b/pdns/dnsdistdist/dnsdist-lua-inspection-ffi.h @@ -44,3 +44,7 @@ uint64_t dnsdist_ffi_stat_node_get_children_hits(const dnsdist_ffi_stat_node_t* void dnsdist_ffi_state_node_set_reason(dnsdist_ffi_stat_node_t* node, const char* reason, size_t reasonSize) __attribute__ ((visibility ("default"))); +typedef enum { + dnsdist_ffi_dynamic_block_type_nmt = 0, + dnsdist_ffi_dynamic_block_type_smt = 1, +} dnsdist_ffi_dynamic_block_type; diff --git a/pdns/dnsdistdist/docs/reference/config.rst b/pdns/dnsdistdist/docs/reference/config.rst index 95a65724a4..f5bd25e4ac 100644 --- a/pdns/dnsdistdist/docs/reference/config.rst +++ b/pdns/dnsdistdist/docs/reference/config.rst @@ -1547,6 +1547,19 @@ faster than the existing rules. :param int action: The action to take when the dynamic block matches, see :ref:`DNSAction `. (default to the one set with :func:`setDynBlocksAction`) :param int warningRate: If set to a non-zero value, the rate above which a warning message will be issued and a no-op block inserted + .. method:: DynBlockRulesGroup:setNewBlockInsertedHook(hook) + + .. versionadded:: 1.9.0 + + Set a Lua function that will be called everytime a new dynamic block is inserted. The function receives: + + * an integer whose value is 0 if the block is Netmask-based one (Client IP or range) and 1 instead (Domain name suffix) + * the key (Client IP/range or domain suffix) as a string + * the reason of the block as a string + * the action of the block as an integer + * the duration of the block in seconds + * whether this is a warning block (true) or not (false) + .. method:: DynBlockRulesGroup:setRCodeRate(rcode, rate, seconds, reason, blockingTime [, action [, warningRate]]) Adds a rate-limiting rule for responses of code ``rcode``, equivalent to: