From: Ensar Sarajčić Date: Thu, 26 Mar 2026 08:43:49 +0000 (+0100) Subject: dnsdist: add support for response maps for DoH3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3703eab0bc2f154fab14d3c2ee677ff94f83abdc;p=thirdparty%2Fpdns.git dnsdist: add support for response maps for DoH3 Closes: #16202 Signed-off-by: Ensar Sarajčić --- diff --git a/pdns/dnsdistdist/dnsdist-configuration-yaml.cc b/pdns/dnsdistdist/dnsdist-configuration-yaml.cc index 48eff1d216..5c69ed274a 100644 --- a/pdns/dnsdistdist/dnsdist-configuration-yaml.cc +++ b/pdns/dnsdistdist/dnsdist-configuration-yaml.cc @@ -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>>(); + for (const auto& responsesMap : bind.doh.responses_map) { + std::optional> headers; + if (!responsesMap.headers.empty()) { + headers = std::unordered_map(); + 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(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 */ diff --git a/pdns/dnsdistdist/dnsdist-lua.cc b/pdns/dnsdistdist/dnsdist-lua.cc index fd90ee55a4..f81b846439 100644 --- a/pdns/dnsdistdist/dnsdist-lua.cc +++ b/pdns/dnsdistdist/dnsdist-lua.cc @@ -2690,6 +2690,19 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) frontend->reloadCertificates(); } }); + + luaCtx.registerFunction::*)(const LuaArray>&)>("setResponsesMap", [](const std::shared_ptr& frontend, const LuaArray>& map) { + if (frontend != nullptr) { + auto newMap = std::make_shared>>(); + newMap->reserve(map.size()); + + for (const auto& entry : map) { + newMap->push_back(entry.second); + } + + frontend->d_responsesMap = std::move(newMap); + } + }); #endif luaCtx.writeFunction("showDOHResponseCodes", []() { diff --git a/pdns/dnsdistdist/doh3.cc b/pdns/dnsdistdist/doh3.cc index 71d19a40ec..e1dcbf4cbb 100644 --- a/pdns/dnsdistdist/doh3.cc +++ b/pdns/dnsdistdist/doh3.cc @@ -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; diff --git a/pdns/dnsdistdist/doh3.hh b/pdns/dnsdistdist/doh3.hh index 2fa07a9af1..df498f2906 100644 --- a/pdns/dnsdistdist/doh3.hh +++ b/pdns/dnsdistdist/doh3.hh @@ -26,6 +26,7 @@ #include #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 d_logger{nullptr}; + std::shared_ptr>> d_responsesMap; std::unique_ptr d_server_config; ComboAddress d_local;