From 56f2845eee04f1be5145fd21e94e2ba890f0474c Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Thu, 1 Aug 2019 16:36:54 +0200 Subject: [PATCH] dnsdist: Add HTTPPathRegexRule --- pdns/dnsdist-console.cc | 1 + pdns/dnsdist-lua-rules.cc | 3 +++ pdns/dnsdistdist/dnsdist-rules.hh | 11 +++++++++++ pdns/dnsdistdist/docs/rules-actions.rst | 7 +++++++ pdns/dnsdistdist/doh.cc | 25 +++++++++++++++++++++++++ 5 files changed, 47 insertions(+) diff --git a/pdns/dnsdist-console.cc b/pdns/dnsdist-console.cc index e0f0db3693..f332922296 100644 --- a/pdns/dnsdist-console.cc +++ b/pdns/dnsdist-console.cc @@ -408,6 +408,7 @@ const std::vector g_consoleKeywords{ { "getTLSContext", true, "n", "returns the TLS context with index n" }, { "getTLSFrontend", true, "n", "returns the TLS frontend with index n" }, { "HTTPHeaderRule", true, "name, regex", "matches DoH queries with a HTTP header 'name' whose content matches the regular expression 'regex'"}, + { "HTTPPathRegexRule", true, "regex", "matches DoH queries whose HTTP path matches 'regex'"}, { "HTTPPathRule", true, "path", "matches DoH queries whose HTTP path is an exact match to 'path'"}, { "inClientStartup", true, "", "returns true during console client parsing of configuration" }, { "includeDirectory", true, "path", "nclude configuration files from `path`" }, diff --git a/pdns/dnsdist-lua-rules.cc b/pdns/dnsdist-lua-rules.cc index 98aae9ddb2..3ed911748d 100644 --- a/pdns/dnsdist-lua-rules.cc +++ b/pdns/dnsdist-lua-rules.cc @@ -287,6 +287,9 @@ void setupLuaRules() g_lua.writeFunction("HTTPPathRule", [](const std::string& path) { return std::shared_ptr(new HTTPPathRule(path)); }); + g_lua.writeFunction("HTTPPathRegexRule", [](const std::string& regex) { + return std::shared_ptr(new HTTPPathRegexRule(regex)); + }); #endif #ifdef HAVE_RE2 diff --git a/pdns/dnsdistdist/dnsdist-rules.hh b/pdns/dnsdistdist/dnsdist-rules.hh index 1d9944e527..ebe80318ed 100644 --- a/pdns/dnsdistdist/dnsdist-rules.hh +++ b/pdns/dnsdistdist/dnsdist-rules.hh @@ -529,6 +529,17 @@ public: private: string d_path; }; + +class HTTPPathRegexRule : public DNSRule +{ +public: + HTTPPathRegexRule(const std::string& regex); + bool matches(const DNSQuestion* dq) const override; + string toString() const override; +private: + Regex d_regex; + std::string d_visual; +}; #endif class SNIRule : public DNSRule diff --git a/pdns/dnsdistdist/docs/rules-actions.rst b/pdns/dnsdistdist/docs/rules-actions.rst index a5879eb965..d3194e9c5f 100644 --- a/pdns/dnsdistdist/docs/rules-actions.rst +++ b/pdns/dnsdistdist/docs/rules-actions.rst @@ -583,6 +583,13 @@ These ``DNSRule``\ s be one of the following items: :param str name: The case-insensitive name of the HTTP header to match on :param str regex: A regular expression to match the content of the specified header +.. function:: HTTPPathRegexRule(regex) + .. versionadded:: 1.4.0 + + Matches DNS over HTTPS queries with a HTTP path matching the regular expression supplied in ``regex``. For example, if the query has been sent to the https://192.0.2.1:443/PowerDNS?dns=... URL, the path would be '/PowerDNS'. + + :param str regex: The regex to match on + .. function:: HTTPPathRule(path) .. versionadded:: 1.4.0 diff --git a/pdns/dnsdistdist/doh.cc b/pdns/dnsdistdist/doh.cc index f932c49f37..618333322a 100644 --- a/pdns/dnsdistdist/doh.cc +++ b/pdns/dnsdistdist/doh.cc @@ -542,6 +542,7 @@ HTTPHeaderRule::HTTPHeaderRule(const std::string& header, const std::string& reg d_visual = "http[" + header+ "] ~ " + regex; } + bool HTTPHeaderRule::matches(const DNSQuestion* dq) const { if(!dq->du) { @@ -587,6 +588,30 @@ string HTTPPathRule::toString() const return "url path == " + d_path; } +HTTPPathRegexRule::HTTPPathRegexRule(const std::string& regex): d_regex(regex), d_visual("http path ~ " + regex) +{ +} + +bool HTTPPathRegexRule::matches(const DNSQuestion* dq) const +{ + if(!dq->du) { + return false; + } + + if(dq->du->req->query_at == SIZE_MAX) { + return d_regex.match(std::string(dq->du->req->path.base, dq->du->req->path.len)); + } + else { + cerr<du->req->path.base, dq->du->req->path.len - dq->du->req->query_at)<du->req->path.base, dq->du->req->path.len - dq->du->req->query_at)); + } +} + +string HTTPPathRegexRule::toString() const +{ + return d_visual; +} + void dnsdistclient(int qsock, int rsock) { setThreadName("dnsdist/doh-cli"); -- 2.39.2