]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3116] Allow D2 to listen on ANY addresses
authorThomas Markwalder <tmark@isc.org>
Thu, 19 Oct 2023 15:02:14 +0000 (11:02 -0400)
committerThomas Markwalder <tmark@isc.org>
Fri, 20 Oct 2023 12:53:12 +0000 (12:53 +0000)
D2 now allows but warns when configured to listen
on 0.0.0.0 or ::

src/bin/d2/d2_process.cc
    D2Process::reconfigureQueueMgr() - emit new warning

src/bin/d2/tests/d2_cfg_mgr_unittests.cc
    TEST_F(D2CfgMgrTest, listenOnANYAddresses)  - new test

src/lib/d2srv/d2_config.cc
    D2Params::validateContents() - remove ANY address check

src/lib/d2srv/d2_messages.*
    DHCP_DDNS_LISTENING_ON_ALL_INTERFACES - new message

src/lib/d2srv/d2_simple_parser.cc
    D2SimpleParser::parse() - remove ANY address check

Added ChangeLog entry

ChangeLog
src/bin/d2/d2_process.cc
src/bin/d2/tests/d2_cfg_mgr_unittests.cc
src/lib/d2srv/d2_config.cc
src/lib/d2srv/d2_messages.cc
src/lib/d2srv/d2_messages.h
src/lib/d2srv/d2_messages.mes
src/lib/d2srv/d2_simple_parser.cc

index 967f37e09ab35ef10fe75119fa082ed588049012..1b46dd7a2205c7a5e04a9342b2444f36c0aeb7d7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+3116.  [func]          tmark
+       To facilitate use in containers the restriction from listening
+       on 0.0.0.0 or :: addresses has been removed from kea-dhcp-ddns.
+       The server will now issue a warning of configured to use either
+       address.
+       (Gitlab #3116)
+
 2186.  [bug]           andrei
        Fixed interface redetection which had stopped working since
        Kea 2.3.6.
index ab12dd6dad5a623484bbdb0de861b57a9acbfdae..2eef4a3371f67c44989f60abbb818153407cfb60 100644 (file)
@@ -408,8 +408,10 @@ D2Process::reconfigureQueueMgr() {
         /// Warn the user if the server address is not the loopback.
         /// @todo Remove this once we provide a secure mechanism.
         std::string ip_address = d2_params->getIpAddress().toText();
-        if (ip_address != "127.0.0.1" && ip_address != "::1") {
-            LOG_WARN(d2_logger, DHCP_DDNS_NOT_ON_LOOPBACK).arg(ip_address);
+        if (ip_address == "0.0.0.0" || ip_address == "::") {
+            LOG_WARN(d2_logger, DHCP_DDNS_LISTENING_ON_ALL_INTERFACES).arg(ip_address);
+        } else if (ip_address != "127.0.0.1" && ip_address != "::1") {
+           LOG_WARN(d2_logger, DHCP_DDNS_NOT_ON_LOOPBACK).arg(ip_address);
         }
 
         // Instantiate the listener.
index 5e27ff8a5c2a07806b591ffb763443a27c577138..6699f1c7f98ff742d097b3431cbc121194985270 100644 (file)
@@ -404,17 +404,8 @@ TEST_F(D2CfgMgrTest, unsupportedTopLevelItems) {
 /// -# ncr_protocol must be valid
 /// -# ncr_format must be valid
 TEST_F(D2CfgMgrTest, invalidEntry) {
-    // Cannot use IPv4 ANY address
-    std::string config = makeParamsConfigString ("0.0.0.0", 777, 333,
-                                           "UDP", "JSON");
-    LOGIC_ERROR(config, "IP address cannot be \"0.0.0.0\" (<string>:1:17)");
-
-    // Cannot use IPv6 ANY address
-    config = makeParamsConfigString ("::", 777, 333, "UDP", "JSON");
-    LOGIC_ERROR(config, "IP address cannot be \"::\" (<string>:1:17)");
-
     // Cannot use port  0
-    config = makeParamsConfigString ("127.0.0.1", 0, 333, "UDP", "JSON");
+    std::string config = makeParamsConfigString ("127.0.0.1", 0, 333, "UDP", "JSON");
     SYNTAX_ERROR(config, "<string>:1.40: port must be greater than zero but less than 65536");
 
     // Cannot use dns server timeout of 0
@@ -1077,4 +1068,36 @@ TEST_F(D2CfgMgrTest, comments) {
     EXPECT_EQ("1", srv_ctx->get("version")->str());
 }
 
+/// @brief Tests a basic valid configuration for D2Param.
+TEST_F(D2CfgMgrTest, listenOnANYAddresses) {
+    // Verify that ip_address 0.0.0.0 is valid.
+    std::string config = makeParamsConfigString ("0.0.0.0", 777, 333,
+                                           "UDP", "JSON");
+    RUN_CONFIG_OK(config);
+
+    EXPECT_EQ(isc::asiolink::IOAddress("0.0.0.0"),
+              d2_params_->getIpAddress());
+
+    // Verify the configuration summary.
+    EXPECT_EQ("listening on 0.0.0.0, port 777, using UDP",
+              d2_params_->getConfigSummary());
+
+    EXPECT_EQ(777, d2_params_->getPort());
+    EXPECT_EQ(333, d2_params_->getDnsServerTimeout());
+    EXPECT_EQ(dhcp_ddns::NCR_UDP, d2_params_->getNcrProtocol());
+    EXPECT_EQ(dhcp_ddns::FMT_JSON, d2_params_->getNcrFormat());
+
+    // Verify that ip_address :: valid.
+    config = makeParamsConfigString ("::", 777, 333, "UDP", "JSON");
+    RUN_CONFIG_OK(config);
+
+    // Verify that the global scalars have the proper values.
+    EXPECT_EQ(isc::asiolink::IOAddress("::"),
+              d2_params_->getIpAddress());
+
+    // Verify the configuration summary.
+    EXPECT_EQ("listening on ::, port 777, using UDP",
+              d2_params_->getConfigSummary());
+}
+
 } // end of anonymous namespace
index a5633f3ff3dd465f67f96af98fedd025a107b040..c75281b5f631f97cdf140d56690dcac2881d75ae 100644 (file)
@@ -52,11 +52,6 @@ D2Params::~D2Params(){};
 
 void
 D2Params::validateContents() {
-    if ((ip_address_.toText() == "0.0.0.0") || (ip_address_.toText() == "::")) {
-        isc_throw(D2CfgError,
-                  "D2Params: IP address cannot be \"" << ip_address_ << "\"");
-    }
-
     if (port_ == 0) {
         isc_throw(D2CfgError, "D2Params: port cannot be 0");
     }
index a35c63cd1cb53e203c0864371f8f1126ab420702..943987635704354bc9adb455ae18d71d70ec14d0 100644 (file)
@@ -45,6 +45,7 @@ extern const isc::log::MessageID DHCP_DDNS_FORWARD_REPLACE_RESP_CORRUPT = "DHCP_
 extern const isc::log::MessageID DHCP_DDNS_FORWARD_REPLACE_TIMEOUT = "DHCP_DDNS_FORWARD_REPLACE_TIMEOUT";
 extern const isc::log::MessageID DHCP_DDNS_FWD_REQUEST_IGNORED = "DHCP_DDNS_FWD_REQUEST_IGNORED";
 extern const isc::log::MessageID DHCP_DDNS_INVALID_RESPONSE = "DHCP_DDNS_INVALID_RESPONSE";
+extern const isc::log::MessageID DHCP_DDNS_LISTENING_ON_ALL_INTERFACES = "DHCP_DDNS_LISTENING_ON_ALL_INTERFACES";
 extern const isc::log::MessageID DHCP_DDNS_NOT_ON_LOOPBACK = "DHCP_DDNS_NOT_ON_LOOPBACK";
 extern const isc::log::MessageID DHCP_DDNS_NO_ELIGIBLE_JOBS = "DHCP_DDNS_NO_ELIGIBLE_JOBS";
 extern const isc::log::MessageID DHCP_DDNS_NO_FWD_MATCH_ERROR = "DHCP_DDNS_NO_FWD_MATCH_ERROR";
@@ -134,6 +135,7 @@ const char* values[] = {
     "DHCP_DDNS_FORWARD_REPLACE_TIMEOUT", "DHCP_DDNS Request ID %1: timed out waiting for a response to forward mapping replace for FQDN %2 to DNS server %3",
     "DHCP_DDNS_FWD_REQUEST_IGNORED", "Request ID %1: Forward updates are disabled, the forward portion of request will be ignored: %2",
     "DHCP_DDNS_INVALID_RESPONSE", "received response to DNS Update message is malformed: %1",
+    "DHCP_DDNS_LISTENING_ON_ALL_INTERFACES", "the DHCP-DDNS server has been configured to listen on %1. This is an insecure configuration supported for testing purposes only",
     "DHCP_DDNS_NOT_ON_LOOPBACK", "the DHCP-DDNS server has been configured to listen on %1 which is not the local loopback.  This is an insecure configuration supported for testing purposes only",
     "DHCP_DDNS_NO_ELIGIBLE_JOBS", "although there are queued requests, there are pending transactions for each, Queue count: %1  Transaction count: %2",
     "DHCP_DDNS_NO_FWD_MATCH_ERROR", "Request ID %1: the configured list of forward DDNS domains does not contain a match for: %2  The request has been discarded.",
index 2fcf22457738b2a93a8b391212727a2dffd1a5df..7c1d2740ad9da03a0ec5e3e579b8f1a7e823a95d 100644 (file)
@@ -46,6 +46,7 @@ extern const isc::log::MessageID DHCP_DDNS_FORWARD_REPLACE_RESP_CORRUPT;
 extern const isc::log::MessageID DHCP_DDNS_FORWARD_REPLACE_TIMEOUT;
 extern const isc::log::MessageID DHCP_DDNS_FWD_REQUEST_IGNORED;
 extern const isc::log::MessageID DHCP_DDNS_INVALID_RESPONSE;
+extern const isc::log::MessageID DHCP_DDNS_LISTENING_ON_ALL_INTERFACES;
 extern const isc::log::MessageID DHCP_DDNS_NOT_ON_LOOPBACK;
 extern const isc::log::MessageID DHCP_DDNS_NO_ELIGIBLE_JOBS;
 extern const isc::log::MessageID DHCP_DDNS_NO_FWD_MATCH_ERROR;
index 53a7a32771fd6459d863a72d9879e5bc9094f793..01c25926c5f44ad81077a378be373d60655bf355 100644 (file)
@@ -439,3 +439,11 @@ server.
 % DHCP_DDNS_UPDATE_RESPONSE_RECEIVED Request ID %1: to server: %2 status: %3
 This is a debug message issued when DHCP_DDNS receives sends a DNS update
 response from a DNS server.
+
+% DHCP_DDNS_LISTENING_ON_ALL_INTERFACES the DHCP-DDNS server has been configured to listen on %1. This is an insecure configuration supported for testing purposes only
+This is a warning message issued when the DHCP-DDNS server is configured to
+listen at either `0.0.0.0` or `::`. It is possible for a malicious attacker to send
+bogus NameChangeRequests to it and change entries in the DNS. For this reason,
+listening on all interfaces should only be used when deploying in containers
+or for testing purposes. A future version of Kea will disable this ability by
+default.
index c24dfdcc9abd4e098d61a98b798ee175b4abe989..8be6376272c393f1c5ec387556c11c6cee2ec4a5 100644 (file)
@@ -237,16 +237,7 @@ void D2SimpleParser::parse(const D2CfgContextPtr& ctx,
     dhcp_ddns::NameChangeFormat ncr_format = dhcp_ddns::FMT_JSON;
 
     ip_address = SimpleParser::getAddress(config, "ip-address");
-
-    if ((ip_address.toText() == "0.0.0.0") ||
-        (ip_address.toText() == "::")) {
-        isc_throw(D2CfgError, "IP address cannot be \""
-                  << ip_address << "\""
-                  << " (" << config->get("ip-address")->getPosition() << ")");
-    }
-
     port = SimpleParser::getUint32(config, "port");
-
     dns_server_timeout = SimpleParser::getUint32(config, "dns-server-timeout");
 
     ncr_protocol = getProtocol(config, "ncr-protocol");