From: Remi Gacogne Date: Tue, 14 May 2024 15:38:35 +0000 (+0200) Subject: dnsdist: Handle dynamic rules' tag action from Lua X-Git-Tag: rec-5.1.0-beta1~27^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=099e95eee273937d666255dc7ebe510d717b4a07;p=thirdparty%2Fpdns.git dnsdist: Handle dynamic rules' tag action from Lua --- diff --git a/pdns/dnsdistdist/dnsdist-dynblocks.cc b/pdns/dnsdistdist/dnsdist-dynblocks.cc index a2db09ae94..7f4ee53462 100644 --- a/pdns/dnsdistdist/dnsdist-dynblocks.cc +++ b/pdns/dnsdistdist/dnsdist-dynblocks.cc @@ -214,32 +214,27 @@ static DNSAction::Action getActualAction(const DynBlock& block) namespace dnsdist::DynamicBlocks { -bool addOrRefreshBlock(NetmaskTree& blocks, const struct timespec& now, const AddressAndPortRange& requestor, const std::string& reason, unsigned int duration, DNSAction::Action action, bool warning, bool beQuiet, std::shared_ptr tagSettings) +bool addOrRefreshBlock(NetmaskTree& blocks, const timespec& now, const AddressAndPortRange& requestor, DynBlock&& dblock, bool beQuiet) { unsigned int count = 0; bool expired = false; bool wasWarning = false; bool bpf = false; - struct timespec until = now; - until.tv_sec += duration; - - DynBlock dblock{reason, until, DNSName(), warning ? DNSAction::Action::NoOp : action}; - dblock.warning = warning; const auto& got = blocks.lookup(requestor); if (got != nullptr) { bpf = got->second.bpf; - if (warning && !got->second.warning) { + if (dblock.warning && !got->second.warning) { /* we have an existing entry which is not a warning, don't override it */ return false; } - if (!warning && got->second.warning) { + if (!dblock.warning && got->second.warning) { wasWarning = true; } else { - if (until < got->second.until) { + if (dblock.until < got->second.until) { // had a longer policy return false; } @@ -255,9 +250,6 @@ bool addOrRefreshBlock(NetmaskTree& blocks, const } dblock.blocks = count; - if (action == DNSAction::Action::SetTag) { - dblock.tagSettings = std::move(tagSettings); - } if (got == nullptr || expired || wasWarning) { const auto actualAction = getActualAction(dblock); @@ -276,7 +268,7 @@ bool addOrRefreshBlock(NetmaskTree& blocks, const } if (!beQuiet) { - warnlog("Inserting %s%sdynamic block for %s for %d seconds: %s", warning ? "(warning) " : "", bpf ? "eBPF " : "", requestor.toString(), duration, reason); + warnlog("Inserting %s%sdynamic block for %s for %d seconds: %s", dblock.warning ? "(warning) " : "", bpf ? "eBPF " : "", requestor.toString(), dblock.until.tv_sec - now.tv_sec, dblock.reason); } } @@ -287,23 +279,20 @@ bool addOrRefreshBlock(NetmaskTree& blocks, const return true; } -bool addOrRefreshBlockSMT(SuffixMatchTree& blocks, const struct timespec& now, const DNSName& name, const std::string& reason, unsigned int duration, DNSAction::Action action, bool beQuiet, std::shared_ptr tagSettings) +bool addOrRefreshBlockSMT(SuffixMatchTree& blocks, const timespec& now, DynBlock&& dblock, bool beQuiet) { - struct timespec until = now; - until.tv_sec += duration; unsigned int count = 0; - DynBlock dblock{reason, until, name.makeLowerCase(), action}; /* be careful, if you try to insert a longer suffix lookup() might return a shorter one if it is already in the tree as a final node */ - const DynBlock* got = blocks.lookup(name); - if (got != nullptr && got->domain != name) { + const DynBlock* got = blocks.lookup(dblock.domain); + if (got != nullptr && got->domain != dblock.domain) { got = nullptr; } bool expired = false; if (got != nullptr) { - if (until < got->until) { + if (dblock.until < got->until) { // had a longer policy return false; } @@ -318,14 +307,11 @@ bool addOrRefreshBlockSMT(SuffixMatchTree& blocks, const struct timesp } dblock.blocks = count; - if (action == DNSAction::Action::SetTag) { - dblock.tagSettings = std::move(tagSettings); - } if (!beQuiet && (got == nullptr || expired)) { - warnlog("Inserting dynamic block for %s for %d seconds: %s", name, duration, reason); + warnlog("Inserting dynamic block for %s for %d seconds: %s", dblock.domain, dblock.until.tv_sec - now.tv_sec, dblock.reason); } - blocks.add(name, std::move(dblock)); + blocks.add(dblock.domain, std::move(dblock)); return true; } } @@ -338,11 +324,18 @@ void DynBlockRulesGroup::addOrRefreshBlock(boost::optional(rule.d_action), rule.d_blockDuration, warning); @@ -360,7 +353,13 @@ void DynBlockRulesGroup::addOrRefreshBlockSMT(SuffixMatchTree& blocks, return; } - updated = dnsdist::DynamicBlocks::addOrRefreshBlockSMT(blocks, now, name, rule.d_blockReason, rule.d_blockDuration, rule.d_action, d_beQuiet, rule.d_tagSettings); + timespec until{now}; + until.tv_sec += rule.d_blockDuration; + DynBlock dblock{rule.d_blockReason, until, name.makeLowerCase(), rule.d_action}; + if (rule.d_action == DNSAction::Action::SetTag) { + dblock.tagSettings = rule.d_tagSettings; + } + updated = dnsdist::DynamicBlocks::addOrRefreshBlockSMT(blocks, now, std::move(dblock), 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); diff --git a/pdns/dnsdistdist/dnsdist-dynblocks.hh b/pdns/dnsdistdist/dnsdist-dynblocks.hh index 1668aa779a..2cb39fcc28 100644 --- a/pdns/dnsdistdist/dnsdist-dynblocks.hh +++ b/pdns/dnsdistdist/dnsdist-dynblocks.hh @@ -385,7 +385,7 @@ private: namespace dnsdist::DynamicBlocks { -bool addOrRefreshBlock(NetmaskTree& blocks, const struct timespec& now, const AddressAndPortRange& requestor, const std::string& reason, unsigned int duration, DNSAction::Action action, bool warning, bool beQuiet, std::shared_ptr tagSettings); -bool addOrRefreshBlockSMT(SuffixMatchTree& blocks, const struct timespec& now, const DNSName& name, const std::string& reason, unsigned int duration, DNSAction::Action action, bool beQuiet, std::shared_ptr tagSettings); +bool addOrRefreshBlock(NetmaskTree& blocks, const timespec& now, const AddressAndPortRange& requestor, DynBlock&& dblock, bool beQuiet); +bool addOrRefreshBlockSMT(SuffixMatchTree& blocks, const timespec& now, DynBlock&& dblock, bool beQuiet); } #endif /* DISABLE_DYNBLOCKS */ diff --git a/pdns/dnsdistdist/dnsdist-lua-ffi.cc b/pdns/dnsdistdist/dnsdist-lua-ffi.cc index 65336d1e44..719fb584fb 100644 --- a/pdns/dnsdistdist/dnsdist-lua-ffi.cc +++ b/pdns/dnsdistdist/dnsdist-lua-ffi.cc @@ -1841,9 +1841,12 @@ bool dnsdist_ffi_dynamic_blocks_add(const char* address, const char* message, ui timespec now{}; gettime(&now); + timespec until{now}; + until.tv_sec += duration; + DynBlock dblock{message, until, DNSName(), static_cast(action)}; auto slow = g_dynblockNMG.getCopy(); #warning FIXME: need to handle tags - if (dnsdist::DynamicBlocks::addOrRefreshBlock(slow, now, target, message, duration, static_cast(action), false, false, nullptr)) { + if (dnsdist::DynamicBlocks::addOrRefreshBlock(slow, now, target, std::move(dblock), false)) { g_dynblockNMG.setState(slow); return true; } @@ -1879,9 +1882,12 @@ bool dnsdist_ffi_dynamic_blocks_smt_add(const char* suffix, const char* message, timespec now{}; gettime(&now); + timespec until{now}; + until.tv_sec += duration; + DynBlock dblock{message, until, domain, static_cast(action)}; auto slow = g_dynblockSMT.getCopy(); #warning FIXME: need to handle tags - if (dnsdist::DynamicBlocks::addOrRefreshBlockSMT(slow, now, domain, message, duration, static_cast(action), false, nullptr)) { + if (dnsdist::DynamicBlocks::addOrRefreshBlockSMT(slow, now, std::move(dblock), false)) { g_dynblockSMT.setState(slow); return true; } diff --git a/pdns/dnsdistdist/dnsdist-lua-inspection.cc b/pdns/dnsdistdist/dnsdist-lua-inspection.cc index 23368734ca..6543a26cad 100644 --- a/pdns/dnsdistdist/dnsdist-lua-inspection.cc +++ b/pdns/dnsdistdist/dnsdist-lua-inspection.cc @@ -1037,5 +1037,76 @@ void setupLuaInspection(LuaContext& luaCtx) luaCtx.registerMember("action", &DynBlock::action); luaCtx.registerMember("warning", &DynBlock::warning); luaCtx.registerMember("bpf", &DynBlock::bpf); + + luaCtx.writeFunction("addDynBlockSMT", + [](const LuaArray& names, const std::string& msg, boost::optional seconds, boost::optional action, DynamicActionOptionalParameters optionalParameters) { + if (names.empty()) { + return; + } + setLuaSideEffect(); + timespec now{}; + gettime(&now); + unsigned int actualSeconds = seconds ? *seconds : 10; + DynBlockRulesGroup::DynBlockRule rule; + parseDynamicActionOptionalParameters("addDynBlockSMT", rule, action, optionalParameters); + + bool needUpdate = false; + auto slow = g_dynblockSMT.getCopy(); + for (const auto& capair : names) { + DNSName domain(capair.second); + domain.makeUsLowerCase(); + timespec until{now}; + until.tv_sec += actualSeconds; + DynBlock dblock{msg, until, std::move(domain), action ? *action : DNSAction::Action::None}; + dblock.tagSettings = rule.d_tagSettings; + if (dnsdist::DynamicBlocks::addOrRefreshBlockSMT(slow, now, std::move(dblock), false)) { + needUpdate = true; + } + } + + if (needUpdate) { + g_dynblockSMT.setState(slow); + } + }); + + luaCtx.writeFunction("addDynamicBlock", + [](const boost::variant& clientIP, const std::string& msg, const boost::optional action, const boost::optional seconds, boost::optional clientIPMask, boost::optional clientIPPortMask, DynamicActionOptionalParameters optionalParameters) { + setLuaSideEffect(); + + ComboAddress clientIPCA; + if (clientIP.type() == typeid(ComboAddress)) { + clientIPCA = boost::get(clientIP); + } + else { + const auto& clientIPStr = boost::get(clientIP); + try { + clientIPCA = ComboAddress(clientIPStr); + } + catch (const std::exception& exp) { + errlog("addDynamicBlock: Unable to parse '%s': %s", clientIPStr, exp.what()); + return; + } + catch (const PDNSException& exp) { + errlog("addDynamicBlock: Unable to parse '%s': %s", clientIPStr, exp.reason); + return; + } + } + AddressAndPortRange target(clientIPCA, clientIPMask ? *clientIPMask : (clientIPCA.isIPv4() ? 32 : 128), clientIPPortMask ? *clientIPPortMask : 0); + unsigned int actualSeconds = seconds ? *seconds : 10; + DynBlockRulesGroup::DynBlockRule rule; + parseDynamicActionOptionalParameters("addDynBlockSMT", rule, action, optionalParameters); + + timespec now{}; + gettime(&now); + timespec until{now}; + until.tv_sec += actualSeconds; + DynBlock dblock{msg, until, DNSName(), action ? *action : DNSAction::Action::None}; + dblock.tagSettings = rule.d_tagSettings; + + auto slow = g_dynblockNMG.getCopy(); + if (dnsdist::DynamicBlocks::addOrRefreshBlock(slow, now, target, std::move(dblock), false)) { + g_dynblockNMG.setState(slow); + } + }); #endif /* DISABLE_DYNBLOCKS */ } diff --git a/pdns/dnsdistdist/dnsdist-lua.cc b/pdns/dnsdistdist/dnsdist-lua.cc index 81ace57ee9..a04c67ca4f 100644 --- a/pdns/dnsdistdist/dnsdist-lua.cc +++ b/pdns/dnsdistdist/dnsdist-lua.cc @@ -1636,66 +1636,6 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) }); #endif /* DISABLE_DEPRECATED_DYNBLOCK */ - luaCtx.writeFunction("addDynBlockSMT", - [](const LuaArray& names, const std::string& msg, boost::optional seconds, boost::optional action) { - if (names.empty()) { - return; - } - setLuaSideEffect(); - timespec now{}; - gettime(&now); - unsigned int actualSeconds = seconds ? *seconds : 10; - - bool needUpdate = false; - auto slow = g_dynblockSMT.getCopy(); - for (const auto& capair : names) { - DNSName domain(capair.second); - domain.makeUsLowerCase(); -#warning FIXME: need to handle tags - if (dnsdist::DynamicBlocks::addOrRefreshBlockSMT(slow, now, domain, msg, actualSeconds, action ? *action : DNSAction::Action::None, false, nullptr)) { - needUpdate = true; - } - } - - if (needUpdate) { - g_dynblockSMT.setState(slow); - } - }); - - luaCtx.writeFunction("addDynamicBlock", - [](const boost::variant& clientIP, const std::string& msg, const boost::optional action, const boost::optional seconds, boost::optional clientIPMask, boost::optional clientIPPortMask) { - setLuaSideEffect(); - - ComboAddress clientIPCA; - if (clientIP.type() == typeid(ComboAddress)) { - clientIPCA = boost::get(clientIP); - } - else { - const auto& clientIPStr = boost::get(clientIP); - try { - clientIPCA = ComboAddress(clientIPStr); - } - catch (const std::exception& exp) { - errlog("addDynamicBlock: Unable to parse '%s': %s", clientIPStr, exp.what()); - return; - } - catch (const PDNSException& exp) { - errlog("addDynamicBlock: Unable to parse '%s': %s", clientIPStr, exp.reason); - return; - } - } - AddressAndPortRange target(clientIPCA, clientIPMask ? *clientIPMask : (clientIPCA.isIPv4() ? 32 : 128), clientIPPortMask ? *clientIPPortMask : 0); - unsigned int actualSeconds = seconds ? *seconds : 10; - - timespec now{}; - gettime(&now); - auto slow = g_dynblockNMG.getCopy(); -#warning FIXME: need to handle tags - if (dnsdist::DynamicBlocks::addOrRefreshBlock(slow, now, target, msg, actualSeconds, action ? *action : DNSAction::Action::None, false, false, nullptr)) { - g_dynblockNMG.setState(slow); - } - }); - luaCtx.writeFunction("setDynBlocksPurgeInterval", [](uint64_t interval) { DynBlockMaintenance::s_expiredDynBlocksPurgeInterval = static_cast(interval); });