From: Remi Gacogne Date: Fri, 11 Jul 2025 08:47:26 +0000 (+0200) Subject: dnsdist: Bring back listening on multiple web server addresses X-Git-Tag: rec-5.4.0-alpha0~25^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=11f9083073119595c655988a3981ab5f1ccc2e40;p=thirdparty%2Fpdns.git dnsdist: Bring back listening on multiple web server addresses This was broken during the refactoring of the configuration between 1.9.x and 2.0.x. Signed-off-by: Remi Gacogne --- diff --git a/pdns/dnsdistdist/dnsdist-configuration-yaml.cc b/pdns/dnsdistdist/dnsdist-configuration-yaml.cc index 5c9b59ad91..d0be262901 100644 --- a/pdns/dnsdistdist/dnsdist-configuration-yaml.cc +++ b/pdns/dnsdistdist/dnsdist-configuration-yaml.cc @@ -792,15 +792,15 @@ static void loadBinds(const ::rust::Vec(std::string(webConfig.password), webConfig.hash_plaintext_credentials); if (!holder->wasHashed() && holder->isHashingAvailable()) { @@ -1077,7 +1077,7 @@ bool loadConfigurationFromFile(const std::string& fileName, [[maybe_unused]] boo } #endif /* DISABLE_CARBON */ - if (!globalConfig.webserver.listen_address.empty()) { + if (!globalConfig.webserver.listen_addresses.empty()) { const auto& webConfig = globalConfig.webserver; loadWebServer(webConfig); } diff --git a/pdns/dnsdistdist/dnsdist-configuration.hh b/pdns/dnsdistdist/dnsdist-configuration.hh index 29903199d2..75702e6fd6 100644 --- a/pdns/dnsdistdist/dnsdist-configuration.hh +++ b/pdns/dnsdistdist/dnsdist-configuration.hh @@ -127,7 +127,7 @@ struct RuntimeConfiguration NetmaskGroup d_proxyProtocolACL; NetmaskGroup d_consoleACL; NetmaskGroup d_webServerACL; - std::optional d_webServerAddress{std::nullopt}; + std::set d_webServerAddresses; dnsdist::QueryCount::Configuration d_queryCountConfig; ComboAddress d_consoleServerAddress{"127.0.0.1:5199"}; std::string d_consoleKey; diff --git a/pdns/dnsdistdist/dnsdist-lua.cc b/pdns/dnsdistdist/dnsdist-lua.cc index 3dc3592ef6..7c0a23d1b9 100644 --- a/pdns/dnsdistdist/dnsdist-lua.cc +++ b/pdns/dnsdistdist/dnsdist-lua.cc @@ -1069,7 +1069,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) } dnsdist::configuration::updateRuntimeConfiguration([local](dnsdist::configuration::RuntimeConfiguration& config) { - config.d_webServerAddress = local; + config.d_webServerAddresses.emplace(local); }); if (dnsdist::configuration::isImmutableConfigurationDone()) { @@ -1077,7 +1077,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) auto sock = Socket(local.sin4.sin_family, SOCK_STREAM, 0); sock.bind(local, true); sock.listen(5); - thread thr(dnsdist::webserver::WebserverThread, std::move(sock)); + thread thr(dnsdist::webserver::WebserverThread, local, std::move(sock)); thr.detach(); } catch (const std::exception& e) { diff --git a/pdns/dnsdistdist/dnsdist-settings-definitions.yml b/pdns/dnsdistdist/dnsdist-settings-definitions.yml index b6d4711cba..a82bc41322 100644 --- a/pdns/dnsdistdist/dnsdist-settings-definitions.yml +++ b/pdns/dnsdistdist/dnsdist-settings-definitions.yml @@ -403,10 +403,10 @@ key_value_stores: webserver: parameters: - - name: "listen_address" - type: "String" + - name: "listen_addresses" + type: "Vec" default: "" - description: "IP address and port to listen on" + description: "IP addresses and ports to listen on" - name: "password" type: "String" default: "" diff --git a/pdns/dnsdistdist/dnsdist-web.cc b/pdns/dnsdistdist/dnsdist-web.cc index 2cba82f5e0..de657f3ee0 100644 --- a/pdns/dnsdistdist/dnsdist-web.cc +++ b/pdns/dnsdistdist/dnsdist-web.cc @@ -1914,23 +1914,22 @@ void setMaxConcurrentConnections(size_t max) s_connManager.setMaxConcurrentConnections(max); } -void WebserverThread(Socket sock) +void WebserverThread(ComboAddress listeningAddress, Socket sock) { setThreadName("dnsdist/webserv"); // coverity[auto_causes_copy] - const auto local = *dnsdist::configuration::getCurrentRuntimeConfiguration().d_webServerAddress; - infolog("Webserver launched on %s", local.toStringWithPort()); + infolog("Webserver launched on %s", listeningAddress.toStringWithPort()); { const auto& config = dnsdist::configuration::getCurrentRuntimeConfiguration(); if (!config.d_webPassword && config.d_dashboardRequiresAuthentication) { - warnlog("Webserver launched on %s without a password set!", local.toStringWithPort()); + warnlog("Webserver launched on %s without a password set!", listeningAddress.toStringWithPort()); } } for (;;) { try { - ComboAddress remote(local); + ComboAddress remote(listeningAddress); int fileDesc = SAccept(sock.getHandle(), remote); if (!isClientAllowedByACL(remote)) { diff --git a/pdns/dnsdistdist/dnsdist-web.hh b/pdns/dnsdistdist/dnsdist-web.hh index 9acff20f98..bd6e9e1eee 100644 --- a/pdns/dnsdistdist/dnsdist-web.hh +++ b/pdns/dnsdistdist/dnsdist-web.hh @@ -6,7 +6,7 @@ namespace dnsdist::webserver { -void WebserverThread(Socket sock); +void WebserverThread(ComboAddress listeningAddress, Socket sock); void setMaxConcurrentConnections(size_t max); void registerBuiltInWebHandlers(); void clearWebHandlers(); diff --git a/pdns/dnsdistdist/dnsdist.cc b/pdns/dnsdistdist/dnsdist.cc index 9d760f842d..4b69356e14 100644 --- a/pdns/dnsdistdist/dnsdist.cc +++ b/pdns/dnsdistdist/dnsdist.cc @@ -3317,7 +3317,7 @@ static void startFrontends() struct ListeningSockets { Socket d_consoleSocket{-1}; - Socket d_webServerSocket{-1}; + std::vector> d_webServerSockets; }; static ListeningSockets initListeningSockets() @@ -3337,12 +3337,12 @@ static ListeningSockets initListeningSockets() } } - if (currentConfig.d_webServerAddress) { - const auto& local = *currentConfig.d_webServerAddress; + for (const auto& local : currentConfig.d_webServerAddresses) { try { - result.d_webServerSocket = Socket(local.sin4.sin_family, SOCK_STREAM, 0); - result.d_webServerSocket.bind(local, true); - result.d_webServerSocket.listen(5); + auto webServerSocket = Socket(local.sin4.sin_family, SOCK_STREAM, 0); + webServerSocket.bind(local, true); + webServerSocket.listen(5); + result.d_webServerSockets.emplace_back(local, std::move(webServerSocket)); } catch (const std::exception& exp) { errlog("Unable to bind to web server socket on %s: %s", local.toStringWithPort(), exp.what()); @@ -3615,8 +3615,8 @@ int main(int argc, char** argv) std::thread consoleControlThread(dnsdist::console::controlThread, std::move(listeningSockets.d_consoleSocket)); consoleControlThread.detach(); } - if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_webServerAddress) { - std::thread webServerThread(dnsdist::webserver::WebserverThread, std::move(listeningSockets.d_webServerSocket)); + for (auto& [listeningAddress, socket] : listeningSockets.d_webServerSockets) { + std::thread webServerThread(dnsdist::webserver::WebserverThread, std::move(listeningAddress), std::move(socket)); webServerThread.detach(); } diff --git a/regression-tests.dnsdist/test_API.py b/regression-tests.dnsdist/test_API.py index dfdda817f8..9afc1f4f5f 100644 --- a/regression-tests.dnsdist/test_API.py +++ b/regression-tests.dnsdist/test_API.py @@ -434,11 +434,12 @@ class TestAPIServerDown(APITestsBase): class TestAPIWritable(APITestsBase): __test__ = True _APIWriteDir = '/tmp' - _config_params = ['_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKeyHashed', '_APIWriteDir'] + _config_params = ['_testServerPort', '_webServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKeyHashed', '_APIWriteDir'] _config_template = """ setACL({"127.0.0.1/32", "::1/128"}) - newServer{address="127.0.0.1:%s"} - webserver("127.0.0.1:%s") + newServer{address="127.0.0.1:%d"} + webserver("127.0.0.1:%d") + webserver("127.0.0.2:%d") setWebserverConfig({password="%s", apiKey="%s"}) setAPIWritable(true, "%s") """ diff --git a/regression-tests.dnsdist/test_OutgoingDOH.py b/regression-tests.dnsdist/test_OutgoingDOH.py index d5e8faffb5..8e6cd41c41 100644 --- a/regression-tests.dnsdist/test_OutgoingDOH.py +++ b/regression-tests.dnsdist/test_OutgoingDOH.py @@ -370,7 +370,8 @@ backends: health_checks: mode: "UP" webserver: - listen_address: "127.0.0.1:%d" + listen_addresses: + - "127.0.0.1:%d" password: "%s" api_key: "%s" acl: diff --git a/regression-tests.dnsdist/test_OutgoingTLS.py b/regression-tests.dnsdist/test_OutgoingTLS.py index d701b2712f..159436b85b 100644 --- a/regression-tests.dnsdist/test_OutgoingTLS.py +++ b/regression-tests.dnsdist/test_OutgoingTLS.py @@ -184,7 +184,8 @@ backends: ca_store: "ca.pem" subject_name: "powerdns.com" webserver: - listen_address: "127.0.0.1:%d" + listen_addresses: + - "127.0.0.1:%d" password: "%s" api_key: "%s" acl: diff --git a/regression-tests.dnsdist/test_TLSSessionResumption.py b/regression-tests.dnsdist/test_TLSSessionResumption.py index b46eded2cb..8760c2b451 100644 --- a/regression-tests.dnsdist/test_TLSSessionResumption.py +++ b/regression-tests.dnsdist/test_TLSSessionResumption.py @@ -320,7 +320,8 @@ class TestTLSSessionResumptionDOTIdenticalFrontends(DNSDistTest): _config_params = [] _yaml_config_template = """--- webserver: - listen_address: "127.0.0.1:%d" + listen_addresses: + - "127.0.0.1:%d" password: "%s" api_key: "%s" acl: diff --git a/regression-tests.dnsdist/test_Yaml.py b/regression-tests.dnsdist/test_Yaml.py index 1abed07c2f..bf756abcf3 100644 --- a/regression-tests.dnsdist/test_Yaml.py +++ b/regression-tests.dnsdist/test_Yaml.py @@ -7,7 +7,9 @@ class TestYaml(DNSDistTest): _yaml_config_template = """--- webserver: - listen_address: "127.0.0.1:%d" + listen_addresses: + - "127.0.0.2:%d" + - "127.0.0.1:%d" acl: - 127.0.0.0/8 @@ -113,12 +115,13 @@ response_rules: type: "TC" """ _webServerPort = pickAvailablePort() + _webServerPort2 = pickAvailablePort() _dnsDistPort = pickAvailablePort() _consoleKey = DNSDistTest.generateConsoleKey() _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') _consolePort = pickAvailablePort() _testServerPort = pickAvailablePort() - _yaml_config_params = ['_webServerPort', '_consolePort', '_consoleKeyB64', '_dnsDistPort', '_testServerPort'] + _yaml_config_params = ['_webServerPort', '_webServerPort2', '_consolePort', '_consoleKeyB64', '_dnsDistPort', '_testServerPort'] _config_params = [] def testForwarded(self):