]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: add support for response maps for DoH3
authorEnsar Sarajčić <dev@ensarsarajcic.com>
Thu, 26 Mar 2026 08:43:49 +0000 (09:43 +0100)
committerEnsar Sarajčić <dev@ensarsarajcic.com>
Thu, 26 Mar 2026 08:43:49 +0000 (09:43 +0100)
Closes: #16202
Signed-off-by: Ensar Sarajčić <dev@ensarsarajcic.com>
pdns/dnsdistdist/dnsdist-configuration-yaml.cc
pdns/dnsdistdist/dnsdist-lua.cc
pdns/dnsdistdist/doh3.cc
pdns/dnsdistdist/doh3.hh

index 48eff1d21670d84dae0a931676f1c5c838d5d65e..5c69ed274a24085170c37d41d01ca91712a51bbc 100644 (file)
@@ -352,6 +352,23 @@ static bool handleTLSConfiguration(const Context& context, const dnsdist::rust::
     frontend->d_quicheParams.d_keyLogFile = std::string(bind.tls.key_log_file);
     frontend->d_quicheParams.d_ccAlgo = std::string(bind.quic.congestion_control_algorithm);
     frontend->d_internalPipeBufferSize = bind.quic.internal_pipe_buffer_size;
+
+    if (!bind.doh.responses_map.empty()) {
+      auto newMap = std::make_shared<std::vector<std::shared_ptr<DOHResponseMapEntry>>>();
+      for (const auto& responsesMap : bind.doh.responses_map) {
+        std::optional<std::unordered_map<std::string, std::string>> headers;
+        if (!responsesMap.headers.empty()) {
+          headers = std::unordered_map<std::string, std::string>();
+          for (const auto& header : responsesMap.headers) {
+            headers->emplace(boost::to_lower_copy(std::string(header.key)), std::string(header.value));
+          }
+        }
+        auto entry = std::make_shared<DOHResponseMapEntry>(std::string(responsesMap.expression), responsesMap.status, PacketBuffer(responsesMap.content.begin(), responsesMap.content.end()), headers);
+        newMap->emplace_back(std::move(entry));
+      }
+      frontend->d_responsesMap = std::move(newMap);
+    }
+
     state.doh3Frontend = std::move(frontend);
   }
 #endif /* HAVE_DNS_OVER_HTTP3 */
index fd90ee55a4422868db7e5ffa8e136a156778c6fb..f81b846439cbc7388ea99c25e8ab37080d4c06c5 100644 (file)
@@ -2690,6 +2690,19 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
       frontend->reloadCertificates();
     }
   });
+
+  luaCtx.registerFunction<void (std::shared_ptr<DOH3Frontend>::*)(const LuaArray<std::shared_ptr<DOHResponseMapEntry>>&)>("setResponsesMap", [](const std::shared_ptr<DOH3Frontend>& frontend, const LuaArray<std::shared_ptr<DOHResponseMapEntry>>& map) {
+    if (frontend != nullptr) {
+      auto newMap = std::make_shared<std::vector<std::shared_ptr<DOHResponseMapEntry>>>();
+      newMap->reserve(map.size());
+
+      for (const auto& entry : map) {
+        newMap->push_back(entry.second);
+      }
+
+      frontend->d_responsesMap = std::move(newMap);
+    }
+  });
 #endif
 
   luaCtx.writeFunction("showDOHResponseCodes", []() {
index 71d19a40ecc84322946cc79c53b596e4130df144..e1dcbf4cbbc301763e2b94ff07797b9ce155658b 100644 (file)
@@ -523,6 +523,27 @@ static void processDOH3Query(DOH3UnitUniquePtr&& doh3Unit)
       return;
     }
 
+    /* the responses map can be updated at runtime, so we need to take a copy of
+       the shared pointer, increasing the reference counter */
+    auto responsesMap = unit->dsc->df->d_responsesMap;
+    if (responsesMap) {
+      for (const auto& entry : *responsesMap) {
+        if (entry->matches(unit->getHTTPPath())) {
+          const auto& customHeaders = entry->getHeaders();
+          unit->status_code = entry->getStatusCode();
+          unit->response = entry->getContent();
+          if (customHeaders) {
+            unit->headers = *customHeaders;
+          }
+
+          auto conn = getConnection(unit->dsc->df->d_server_config->d_connections, unit->serverConnID);
+          handleResponse(*unit->dsc->df, *conn, unit->streamID, unit->status_code, unit->response, unit->d_contentTypeOut);
+          unit->ids.doh3u.reset();
+          return;
+        }
+      }
+    }
+
     if (unit->query.size() < sizeof(dnsheader)) {
       ++dnsdist::metrics::g_stats.nonCompliantQueries;
       ++clientState.nonCompliantQueries;
index 2fa07a9af1beed07e555bf0356f57e2e7dab5d83..df498f29068131717c3c881edaeee673974e4b6c 100644 (file)
@@ -26,6 +26,7 @@
 #include <unordered_map>
 
 #include "config.h"
+#include "dnsdist-doh-common.hh"
 #include "noinitvector.hh"
 
 #ifdef HAVE_DNS_OVER_HTTP3
@@ -66,6 +67,7 @@ struct DOH3Frontend
   }
 
   std::shared_ptr<const Logr::Logger> d_logger{nullptr};
+  std::shared_ptr<std::vector<std::shared_ptr<DOHResponseMapEntry>>> d_responsesMap;
   std::unique_ptr<DOH3ServerConfig> d_server_config;
   ComboAddress d_local;