From: Remi Gacogne Date: Mon, 11 Dec 2023 09:55:30 +0000 (+0100) Subject: dnsdist: Add `QNameSuffixRule` X-Git-Tag: dnsdist-1.9.0-alpha4~7^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=34d16877dca0bc8204f91f5b5464250cdc86ed34;p=thirdparty%2Fpdns.git dnsdist: Add `QNameSuffixRule` An easier to type alias to `SuffixMatchNodeRule`, as suggested by HÃ¥kan Lindqvist. --- diff --git a/pdns/dnsdist-lua-rules.cc b/pdns/dnsdist-lua-rules.cc index 9cbeec7529..502421c2c6 100644 --- a/pdns/dnsdist-lua-rules.cc +++ b/pdns/dnsdist-lua-rules.cc @@ -283,6 +283,29 @@ static boost::optional getRuleFromSelector(const std::vector& rules, const return boost::none; } +namespace +{ +std::shared_ptr qnameSuffixRule(const boost::variant> names, boost::optional quiet) +{ + if (names.type() == typeid(string)) { + SuffixMatchNode smn; + smn.add(DNSName(*boost::get(&names))); + return std::shared_ptr(new SuffixMatchNodeRule(smn, quiet ? *quiet : false)); + } + + if (names.type() == typeid(LuaArray)) { + SuffixMatchNode smn; + for (const auto& str : *boost::get>(&names)) { + smn.add(DNSName(str.second)); + } + return std::shared_ptr(new SuffixMatchNodeRule(smn, quiet ? *quiet : false)); + } + + const auto& smn = *boost::get(&names); + return std::shared_ptr(new SuffixMatchNodeRule(smn, quiet ? *quiet : false)); +} +} + // NOLINTNEXTLINE(readability-function-cognitive-complexity): this function declares Lua bindings, even with a good refactoring it will likely blow up the threshold void setupLuaRules(LuaContext& luaCtx) { @@ -521,24 +544,7 @@ void setupLuaRules(LuaContext& luaCtx) return std::shared_ptr(new SNIRule(name)); }); - luaCtx.writeFunction("SuffixMatchNodeRule", [](const boost::variant> names, boost::optional quiet) { - if (names.type() == typeid(string)) { - SuffixMatchNode smn; - smn.add(DNSName(*boost::get(&names))); - return std::shared_ptr(new SuffixMatchNodeRule(smn, quiet ? *quiet : false)); - } - - if (names.type() == typeid(LuaArray)) { - SuffixMatchNode smn; - for (const auto& str : *boost::get>(&names)) { - smn.add(DNSName(str.second)); - } - return std::shared_ptr(new SuffixMatchNodeRule(smn, quiet ? *quiet : false)); - } - - const auto& smn = *boost::get(&names); - return std::shared_ptr(new SuffixMatchNodeRule(smn, quiet ? *quiet : false)); - }); + luaCtx.writeFunction("SuffixMatchNodeRule", qnameSuffixRule); luaCtx.writeFunction("NetmaskGroupRule", [](const boost::variant> netmasks, boost::optional src, boost::optional quiet) { if (netmasks.type() == typeid(string)) { @@ -612,6 +618,8 @@ void setupLuaRules(LuaContext& luaCtx) return std::shared_ptr(new QNameRule(DNSName(qname))); }); + luaCtx.writeFunction("QNameSuffixRule", qnameSuffixRule); + luaCtx.writeFunction("QTypeRule", [](boost::variant str) { uint16_t qtype; if (auto dir = boost::get(&str)) { diff --git a/pdns/dnsdistdist/docs/rules-actions.rst b/pdns/dnsdistdist/docs/rules-actions.rst index b4266f05aa..31895927b9 100644 --- a/pdns/dnsdistdist/docs/rules-actions.rst +++ b/pdns/dnsdistdist/docs/rules-actions.rst @@ -73,7 +73,7 @@ The regex is applied case insensitively. Alternatively, if compiled in, :func:`RE2Rule` provides similar functionality, but against libre2. -Note that to check if a name is in a list of domains, :func:`SuffixMatchNodeRule` is preferred over complex regular expressions or multiple instances of :func:`RegexRule`. +Note that to check if a name is in a list of domains, :func:`QNameSuffixRule` is preferred over complex regular expressions or multiple instances of :func:`RegexRule`. Rule Generators --------------- @@ -154,7 +154,7 @@ For Rules related to the incoming query: Added ``name`` to the ``options``. .. versionchanged:: 1.9.0 - Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule` instead + Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`QNameSuffixRule` instead Add a Rule and Action to the existing rules. If a string (or list of) is passed as the first parameter instead of a :class:`DNSRule`, it behaves as if the string or list of strings was passed to :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule`. @@ -299,7 +299,7 @@ For Rules related to responses: Added ``name`` to the ``options``. .. versionchanged:: 1.9.0 - Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule` instead + Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`QNameSuffixRule` instead Add a Rule and Action for responses to the existing rules. If a string (or list of) is passed as the first parameter instead of a :class:`DNSRule`, it behaves as if the string or list of strings was passed to :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule`. @@ -362,7 +362,7 @@ Functions for manipulating Cache Hit Response Rules: Added ``name`` to the ``options``. .. versionchanged:: 1.9.0 - Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule` instead + Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`QNameSuffixRule` instead Add a Rule and ResponseAction for Cache Hits to the existing rules. If a string (or list of) is passed as the first parameter instead of a :class:`DNSRule`, it behaves as if the string or list of strings was passed to :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule`. @@ -422,7 +422,7 @@ Functions for manipulating Cache Inserted Response Rules: .. versionadded:: 1.8.0 .. versionchanged:: 1.9.0 - Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule` instead + Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`QNameSuffixRule` instead Add a Rule and ResponseAction that is executed after a cache entry has been inserted to the existing rules. If a string (or list of) is passed as the first parameter instead of a :class:`DNSRule`, it behaves as if the string or list of strings was passed to :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule`. @@ -479,7 +479,7 @@ Functions for manipulating Self-Answered Response Rules: Added ``name`` to the ``options``. .. versionchanged:: 1.9.0 - Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule` instead + Passing a string or list of strings instead of a :class:`DNSRule` is deprecated, use :func:`NetmaskGroupRule` or :func:`QNameSuffixRule` instead Add a Rule and Action for Self-Answered queries to the existing rules. If a string (or list of) is passed as the first parameter instead of a :class:`DNSRule`, it behaves as if the string or list of strings was passed to :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule`. @@ -761,10 +761,29 @@ These ``DNSRule``\ s be one of the following items: Matches if the set contains exact qname. - To match subdomain names, see :func:`SuffixMatchNodeRule`. + To match subdomain names, see :func:`QNameSuffixRule`. :param DNSNameSet set: Set with qnames. +.. function:: QNameSuffixRule(suffixes [, quiet@) + + .. versionadded:: 1.9.0 + + Matches based on a group of domain suffixes for rapid testing of membership. + The first parameter, ``suffixes``, can be a string, list of strings or a class:`SuffixMatchNode` object created with :func:`newSuffixMatchNode`. + Pass true as second parameter to prevent listing of all domains matched. + + To match domain names exactly, see :func:`QNameSetRule`. + + This rule existed before 1.9.0 but was called :func:`SuffixMatchNodeRule`, only accepting a :class:`SuffixMatchNode` parameter. + + :param suffixes: A string, list of strings, or a :class:`SuffixMatchNode` to match on + :param bool quiet: Do not display the list of matched domains in Rules. Default is false. + + Matches queries with the specified qname exactly. + + :param string qname: Qname to match + .. function:: QNameLabelsCountRule(min, max) Matches if the qname has less than ``min`` or more than ``max`` labels. @@ -870,6 +889,8 @@ These ``DNSRule``\ s be one of the following items: To match domain names exactly, see :func:`QNameSetRule`. + Since 1.9.0, this rule can also be used via the alias :func:`QNameSuffixRule`. + :param SuffixMatchNode smn: A string, list of strings, or a :class:`SuffixMatchNode` to match on :param bool quiet: Do not display the list of matched domains in Rules. Default is false. @@ -945,7 +966,7 @@ Convenience Functions .. function:: makeRule(rule) .. versionchanged:: 1.9.0 - This function is deprecated, please use :func:`NetmaskGroupRule` or :func:`SuffixMatchNodeRule` instead + This function is deprecated, please use :func:`NetmaskGroupRule` or :func:`QnameSuffixRule` instead Make a :func:`NetmaskGroupRule` or a :func:`SuffixMatchNodeRule`, depending on how it is called. The `rule` parameter can be a string, or a list of strings, that should contain either: diff --git a/regression-tests.dnsdist/test_Basics.py b/regression-tests.dnsdist/test_Basics.py index 241ca32692..6292ab75b0 100644 --- a/regression-tests.dnsdist/test_Basics.py +++ b/regression-tests.dnsdist/test_Basics.py @@ -13,7 +13,7 @@ class TestBasics(DNSDistTest): mySMN = newSuffixMatchNode() mySMN:add(newDNSName("nameAndQtype.tests.powerdns.com.")) addAction(AndRule{SuffixMatchNodeRule(mySMN), QTypeRule("TXT")}, RCodeAction(DNSRCode.NOTIMP)) - addAction(SuffixMatchNodeRule({"drop.test.powerdns.com.", "drop2.test.powerdns.com."}), DropAction()) + addAction(QNameSuffixRule({"drop.test.powerdns.com.", "drop2.test.powerdns.com."}), DropAction()) addAction(AndRule({QTypeRule(DNSQType.A),QNameRule("ds9a.nl")}), SpoofAction("1.2.3.4")) addAction(newDNSName("dnsname.addaction.powerdns.com."), RCodeAction(DNSRCode.REFUSED)) addAction({newDNSName("dnsname-table1.addaction.powerdns.com."), newDNSName("dnsname-table2.addaction.powerdns.com.")}, RCodeAction(DNSRCode.REFUSED)) diff --git a/regression-tests.dnsdist/test_RulesActions.py b/regression-tests.dnsdist/test_RulesActions.py index bdabfc3b49..4299fbc8fa 100644 --- a/regression-tests.dnsdist/test_RulesActions.py +++ b/regression-tests.dnsdist/test_RulesActions.py @@ -14,7 +14,7 @@ class TestAdvancedAllow(DNSDistTest): _config_template = """ addAction(AllRule(), NoneAction()) - addAction(SuffixMatchNodeRule("allowed.advanced.tests.powerdns.com."), AllowAction()) + addAction(QNameSuffixRule("allowed.advanced.tests.powerdns.com."), AllowAction()) addAction(AllRule(), DropAction()) newServer{address="127.0.0.1:%s"} """