From: Miod Vallat Date: Wed, 30 Jul 2025 12:40:11 +0000 (+0200) Subject: Allow edns-cookie-secret to be set to "random". X-Git-Tag: auth-5.1.0-alpha0~1^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F15948%2Fhead;p=thirdparty%2Fpdns.git Allow edns-cookie-secret to be set to "random". Signed-off-by: Miod Vallat --- diff --git a/docs/settings.rst b/docs/settings.rst index 4545d623e..482ec473e 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -744,6 +744,9 @@ PowerDNS will also respond with BADCOOKIE to clients that have sent only a clien This setting MUST be 32 hexadecimal characters, as the siphash algorithm's key used to create the cookie requires a 128-bit key. +Alternatively, starting with version 5.0.0, this parameter can be set to +`random`, in which case a random cookie value will be generated upon startup. + .. _setting-edns-subnet-processing: ``edns-subnet-processing`` diff --git a/pdns/auth-main.cc b/pdns/auth-main.cc index 017285ec8..0a28e3faf 100644 --- a/pdns/auth-main.cc +++ b/pdns/auth-main.cc @@ -744,15 +744,23 @@ static void mainthread() // User wants cookie processing #ifdef HAVE_CRYPTO_SHORTHASH // we can do siphash-based cookies DNSPacket::s_doEDNSCookieProcessing = true; - try { - if (::arg()["edns-cookie-secret"].size() != EDNSCookiesOpt::EDNSCookieSecretSize) { - throw std::range_error("wrong size (" + std::to_string(::arg()["edns-cookie-secret"].size()) + "), must be " + std::to_string(EDNSCookiesOpt::EDNSCookieSecretSize)); - } - DNSPacket::s_EDNSCookieKey = makeBytesFromHex(::arg()["edns-cookie-secret"]); + const std::string& secret = ::arg()["edns-cookie-secret"]; + if (secret == "random") { + std::array key{}; + dns_random(key.data(), key.size()); + DNSPacket::s_EDNSCookieKey = std::string(key.data(), key.size()); } - catch (const std::range_error& e) { - g_log << Logger::Error << "edns-cookie-secret invalid: " << e.what() << endl; - exit(1); + else { + try { + if (secret.size() != EDNSCookiesOpt::EDNSCookieSecretSize) { + throw std::range_error("wrong size (" + std::to_string(secret.size()) + "), must be " + std::to_string(EDNSCookiesOpt::EDNSCookieSecretSize)); + } + DNSPacket::s_EDNSCookieKey = makeBytesFromHex(secret); + } + catch (const std::range_error& e) { + g_log << Logger::Error << "edns-cookie-secret invalid: " << e.what() << endl; + exit(1); // NOLINT(concurrency-mt-unsafe) we're single threaded at this point + } } #else g_log << Logger::Error << "Support for EDNS Cookies is not available because of missing cryptographic functions (libsodium support should be enabled, with the crypto_shorthash() function available)" << endl; diff --git a/regression-tests.auth-py/test_Cookies.py b/regression-tests.auth-py/test_Cookies.py index ac85c3312..e063b48c6 100644 --- a/regression-tests.auth-py/test_Cookies.py +++ b/regression-tests.auth-py/test_Cookies.py @@ -3,7 +3,6 @@ import dns from authtests import AuthTest - class TestEdnsCookies(AuthTest): _config_template = """ launch={backend} @@ -108,3 +107,9 @@ www.example.org. 3600 IN A 192.0.2.5 self.assertNotEqual(opt.data, opts[0].data) return self.fail() + +class TestEdnsRandomCookies(TestEdnsCookies): + _config_template = """ +launch={backend} +edns-cookie-secret=random +"""