From: Remi Gacogne Date: Thu, 8 Feb 2024 13:42:04 +0000 (+0100) Subject: dnsdist: Implementation reloading of TLS certs/keys for DoQ and DoH3 X-Git-Tag: dnsdist-1.9.0~6^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3791b473984a7abc16c9cf97e6c4f1a11c72b0d3;p=thirdparty%2Fpdns.git dnsdist: Implementation reloading of TLS certs/keys for DoQ and DoH3 --- diff --git a/pdns/dnsdist-console.cc b/pdns/dnsdist-console.cc index 0f9e085735..6444723b04 100644 --- a/pdns/dnsdist-console.cc +++ b/pdns/dnsdist-console.cc @@ -542,8 +542,12 @@ const std::vector g_consoleKeywords{ { "getDynamicBlocksSMT", true, "", "returns a table of the current suffix-based dynamic blocks" }, { "getDNSCryptBind", true, "n", "return the `DNSCryptContext` object corresponding to the bind `n`" }, { "getDNSCryptBindCount", true, "", "returns the number of DNSCrypt listeners" }, - { "getDOHFrontend", true, "n", "returns the DOH frontend with index n" }, + { "getDOHFrontend", true, "n", "returns the DoH frontend with index n" }, { "getDOHFrontendCount", true, "", "returns the number of DoH listeners" }, + { "getDOH3Frontend", true, "n", "returns the DoH3 frontend with index n" }, + { "getDOH3FrontendCount", true, "", "returns the number of DoH3 listeners" }, + { "getDOQFrontend", true, "n", "returns the DoQ frontend with index n" }, + { "getDOQFrontendCount", true, "", "returns the number of DoQ listeners" }, { "getListOfAddressesOfNetworkInterface", true, "itf", "returns the list of addresses configured on a given network interface, as strings" }, { "getListOfNetworkInterfaces", true, "", "returns the list of network interfaces present on the system, as strings" }, { "getListOfRangesOfNetworkInterface", true, "itf", "returns the list of network ranges configured on a given network interface, as strings" }, diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 50112a3730..6ea674a5f5 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -2841,6 +2841,41 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) #endif }); +#ifdef HAVE_DNS_OVER_QUIC + luaCtx.writeFunction("getDOQFrontend", [client](uint64_t index) { + std::shared_ptr result = nullptr; + if (client) { + return result; + } + setLuaNoSideEffect(); + try { + if (index < g_doqlocals.size()) { + result = g_doqlocals.at(index); + } + else { + errlog("Error: trying to get DOQ frontend with index %d but we only have %d frontend(s)\n", index, g_doqlocals.size()); + g_outputBuffer = "Error: trying to get DOQ frontend with index " + std::to_string(index) + " but we only have " + std::to_string(g_doqlocals.size()) + " frontend(s)\n"; + } + } + catch (const std::exception& e) { + g_outputBuffer = "Error while trying to get DOQ frontend with index " + std::to_string(index) + ": " + string(e.what()) + "\n"; + errlog("Error while trying to get DOQ frontend with index %d: %s\n", index, string(e.what())); + } + return result; + }); + + luaCtx.writeFunction("getDOQFrontendCount", []() { + setLuaNoSideEffect(); + return g_doqlocals.size(); + }); + + luaCtx.registerFunction::*)()>("reloadCertificates", [](std::shared_ptr frontend) { + if (frontend != nullptr) { + frontend->reloadCertificates(); + } + }); +#endif + luaCtx.writeFunction("showDOHFrontends", []() { #ifdef HAVE_DNS_OVER_HTTPS setLuaNoSideEffect(); @@ -2887,6 +2922,41 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) #endif }); +#ifdef HAVE_DNS_OVER_HTTP3 + luaCtx.writeFunction("getDOH3Frontend", [client](uint64_t index) { + std::shared_ptr result = nullptr; + if (client) { + return result; + } + setLuaNoSideEffect(); + try { + if (index < g_doh3locals.size()) { + result = g_doh3locals.at(index); + } + else { + errlog("Error: trying to get DOH3 frontend with index %d but we only have %d frontend(s)\n", index, g_doh3locals.size()); + g_outputBuffer = "Error: trying to get DOH3 frontend with index " + std::to_string(index) + " but we only have " + std::to_string(g_doh3locals.size()) + " frontend(s)\n"; + } + } + catch (const std::exception& e) { + g_outputBuffer = "Error while trying to get DOH3 frontend with index " + std::to_string(index) + ": " + string(e.what()) + "\n"; + errlog("Error while trying to get DOH3 frontend with index %d: %s\n", index, string(e.what())); + } + return result; + }); + + luaCtx.writeFunction("getDOH3FrontendCount", []() { + setLuaNoSideEffect(); + return g_doh3locals.size(); + }); + + luaCtx.registerFunction::*)()>("reloadCertificates", [](std::shared_ptr frontend) { + if (frontend != nullptr) { + frontend->reloadCertificates(); + } + }); +#endif + luaCtx.writeFunction("showDOHResponseCodes", []() { #ifdef HAVE_DNS_OVER_HTTPS setLuaNoSideEffect(); @@ -3246,6 +3316,16 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) frontend->dohFrontend->reloadCertificates(); } #endif /* HAVE_DNS_OVER_HTTPS */ +#ifdef HAVE_DNS_OVER_QUIC + if (frontend->doqFrontend) { + frontend->doqFrontend->reloadCertificates(); + } +#endif /* HAVE_DNS_OVER_QUIC */ +#ifdef HAVE_DNS_OVER_HTTP3 + if (frontend->doh3Frontend) { + frontend->doh3Frontend->reloadCertificates(); + } +#endif /* HAVE_DNS_OVER_HTTP3 */ } catch (const std::exception& e) { errlog("Error reloading certificates for frontend %s: %s", frontend->local.toStringWithPort(), e.what()); diff --git a/pdns/dnsdistdist/doh3.cc b/pdns/dnsdistdist/doh3.cc index 4c0823ab62..c6b6f4c2df 100644 --- a/pdns/dnsdistdist/doh3.cc +++ b/pdns/dnsdistdist/doh3.cc @@ -54,8 +54,8 @@ using h3_headers_t = std::map; class H3Connection { public: - H3Connection(const ComboAddress& peer, QuicheConnection&& conn) : - d_peer(peer), d_conn(std::move(conn)) + H3Connection(const ComboAddress& peer, QuicheConfig config, QuicheConnection&& conn) : + d_peer(peer), d_conn(std::move(conn)), d_config(std::move(config)) { } H3Connection(const H3Connection&) = delete; @@ -66,6 +66,7 @@ public: ComboAddress d_peer; QuicheConnection d_conn; + QuicheConfig d_config; QuicheHTTP3Connection d_http3{nullptr, quiche_h3_conn_free}; // buffer request headers by streamID std::unordered_map d_headersBuffers; @@ -379,16 +380,22 @@ static void handleResponse(DOH3Frontend& frontend, H3Connection& conn, const uin void DOH3Frontend::setup() { auto config = QuicheConfig(quiche_config_new(QUICHE_PROTOCOL_VERSION), quiche_config_free); - d_quicheParams.d_alpn = std::string(DOH3_ALPN.begin(), DOH3_ALPN.end()); configureQuiche(config, d_quicheParams, true); - // quiche_h3_config_new auto http3config = QuicheHTTP3Config(quiche_h3_config_new(), quiche_h3_config_free); d_server_config = std::make_unique(std::move(config), std::move(http3config), d_internalPipeBufferSize); } +void DOH3Frontend::reloadCertificates() +{ + auto config = QuicheConfig(quiche_config_new(QUICHE_PROTOCOL_VERSION), quiche_config_free); + d_quicheParams.d_alpn = std::string(DOH3_ALPN.begin(), DOH3_ALPN.end()); + configureQuiche(config, d_quicheParams, true); + std::atomic_store_explicit(&d_server_config->config, std::move(config), std::memory_order_release); +} + static std::optional> getConnection(DOH3ServerConfig::ConnectionsMap& connMap, const PacketBuffer& connID) { auto iter = connMap.find(connID); @@ -431,7 +438,7 @@ static std::optional> createConnection(DOH3 quiche_conn_set_keylog_path(quicheConn.get(), config.df->d_quicheParams.d_keyLogFile.c_str()); } - auto conn = H3Connection(peer, std::move(quicheConn)); + auto conn = H3Connection(peer, config.config, std::move(quicheConn)); auto pair = config.d_connections.emplace(serverSideID, std::move(conn)); return pair.first->second; } diff --git a/pdns/dnsdistdist/doh3.hh b/pdns/dnsdistdist/doh3.hh index bca7a4eb52..954ea4aab2 100644 --- a/pdns/dnsdistdist/doh3.hh +++ b/pdns/dnsdistdist/doh3.hh @@ -48,6 +48,7 @@ struct DOH3Frontend ~DOH3Frontend(); void setup(); + void reloadCertificates(); std::unique_ptr d_server_config; ComboAddress d_local; diff --git a/pdns/dnsdistdist/doq-common.hh b/pdns/dnsdistdist/doq-common.hh index 92af37f25f..c7a4b5c21a 100644 --- a/pdns/dnsdistdist/doq-common.hh +++ b/pdns/dnsdistdist/doq-common.hh @@ -47,7 +47,7 @@ static const std::map s_available_cc_algorithms = { using QuicheConnection = std::unique_ptr; using QuicheHTTP3Connection = std::unique_ptr; -using QuicheConfig = std::unique_ptr; +using QuicheConfig = std::shared_ptr; using QuicheHTTP3Config = std::unique_ptr; struct QuicheParams diff --git a/pdns/dnsdistdist/doq.cc b/pdns/dnsdistdist/doq.cc index 277a8c5985..4ac7267f0b 100644 --- a/pdns/dnsdistdist/doq.cc +++ b/pdns/dnsdistdist/doq.cc @@ -51,8 +51,8 @@ using namespace dnsdist::doq; class Connection { public: - Connection(const ComboAddress& peer, QuicheConnection&& conn) : - d_peer(peer), d_conn(std::move(conn)) + Connection(const ComboAddress& peer, QuicheConfig config, QuicheConnection conn) : + d_peer(peer), d_conn(std::move(conn)), d_config(std::move(config)) { } Connection(const Connection&) = delete; @@ -63,6 +63,8 @@ public: ComboAddress d_peer; QuicheConnection d_conn; + QuicheConfig d_config; + std::unordered_map d_streamBuffers; std::unordered_map d_streamOutBuffers; }; @@ -303,6 +305,14 @@ void DOQFrontend::setup() d_server_config = std::make_unique(std::move(config), d_internalPipeBufferSize); } +void DOQFrontend::reloadCertificates() +{ + auto config = QuicheConfig(quiche_config_new(QUICHE_PROTOCOL_VERSION), quiche_config_free); + d_quicheParams.d_alpn = std::string(DOQ_ALPN.begin(), DOQ_ALPN.end()); + configureQuiche(config, d_quicheParams, false); + std::atomic_store_explicit(&d_server_config->config, std::move(config), std::memory_order_release); +} + static std::optional> getConnection(DOQServerConfig::ConnectionsMap& connMap, const PacketBuffer& connID) { auto iter = connMap.find(connID); @@ -345,7 +355,7 @@ static std::optional> createConnection(DOQSer quiche_conn_set_keylog_path(quicheConn.get(), config.df->d_quicheParams.d_keyLogFile.c_str()); } - auto conn = Connection(peer, std::move(quicheConn)); + auto conn = Connection(peer, config.config, std::move(quicheConn)); auto pair = config.d_connections.emplace(serverSideID, std::move(conn)); return pair.first->second; } diff --git a/pdns/dnsdistdist/doq.hh b/pdns/dnsdistdist/doq.hh index a61af71a97..258194177a 100644 --- a/pdns/dnsdistdist/doq.hh +++ b/pdns/dnsdistdist/doq.hh @@ -49,6 +49,7 @@ struct DOQFrontend ~DOQFrontend(); void setup(); + void reloadCertificates(); std::unique_ptr d_server_config; dnsdist::doq::QuicheParams d_quicheParams;