From 063cf4eaa5d8e2c429b802a6c75633908c483588 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 10 Jan 2025 15:13:33 +0100 Subject: [PATCH] dnsdist: Remove `TLSContext` This PR removes the `TLSContext` class which is a duplicate of the more powerful `TLSFrontend` one, and rename `showTLSContexts` to `showTLSFrontends` to be consistent. --- pdns/dnsdistdist/dnsdist-console.cc | 3 +- pdns/dnsdistdist/dnsdist-lua.cc | 38 +------------------ .../docs/advanced/tls-sessions-management.rst | 4 +- pdns/dnsdistdist/docs/reference/config.rst | 20 +++++++++- pdns/dnsdistdist/docs/upgrade_guide.rst | 6 +++ .../test_TLSSessionResumption.py | 22 +++++------ 6 files changed, 40 insertions(+), 53 deletions(-) diff --git a/pdns/dnsdistdist/dnsdist-console.cc b/pdns/dnsdistdist/dnsdist-console.cc index 12926eeedf94..1ad865573bab 100644 --- a/pdns/dnsdistdist/dnsdist-console.cc +++ b/pdns/dnsdistdist/dnsdist-console.cc @@ -581,7 +581,6 @@ static const std::vector s_consoleKeywords {"getTopRules", true, "[top]", "return the `top` rules"}, {"getTopSelfAnsweredResponseRules", true, "[top]", "return the `top` self-answered response rules"}, {"getTopXFRResponseRules", true, "[top]", "return the `top` XFR response rules"}, - {"getTLSContext", true, "n", "returns the TLS context with index n"}, {"getTLSFrontend", true, "n", "returns the TLS frontend with index n"}, {"getTLSFrontendCount", true, "", "returns the number of DoT listeners"}, {"getVerbose", true, "", "get whether log messages at the verbose level will be logged"}, @@ -796,8 +795,8 @@ static const std::vector s_consoleKeywords {"showServerPolicy", true, "", "show name of currently operational server selection policy"}, {"showServers", true, "[{showUUIDs=false}]", "output all servers, optionally with their UUIDs"}, {"showTCPStats", true, "", "show some statistics regarding TCP"}, - {"showTLSContexts", true, "", "list all the available TLS contexts"}, {"showTLSErrorCounters", true, "", "show metrics about TLS handshake failures"}, + {"showTLSFrontends", true, "", "list all the available TLS contexts"}, {"showVersion", true, "", "show the current version"}, {"showWebserverConfig", true, "", "Show the current webserver configuration"}, {"shutdown", true, "", "shut down `dnsdist`"}, diff --git a/pdns/dnsdistdist/dnsdist-lua.cc b/pdns/dnsdistdist/dnsdist-lua.cc index d97c8329e0de..4cd7ab494a89 100644 --- a/pdns/dnsdistdist/dnsdist-lua.cc +++ b/pdns/dnsdistdist/dnsdist-lua.cc @@ -3147,7 +3147,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) #endif }); - luaCtx.writeFunction("showTLSContexts", []() { + luaCtx.writeFunction("showTLSFrontends", []() { #ifdef HAVE_DNS_OVER_TLS setLuaNoSideEffect(); try { @@ -3171,30 +3171,6 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) #endif }); - luaCtx.writeFunction("getTLSContext", [](uint64_t index) { - std::shared_ptr result = nullptr; -#ifdef HAVE_DNS_OVER_TLS - setLuaNoSideEffect(); - const auto tlsFrontends = dnsdist::getDoTFrontends(); - try { - if (index < tlsFrontends.size()) { - result = tlsFrontends.at(index)->getContext(); - } - else { - errlog("Error: trying to get TLS context with index %d but we only have %d context(s)\n", index, tlsFrontends.size()); - g_outputBuffer = "Error: trying to get TLS context with index " + std::to_string(index) + " but we only have " + std::to_string(tlsFrontends.size()) + " context(s)\n"; - } - } - catch (const std::exception& e) { - g_outputBuffer = "Error while trying to get TLS context with index " + std::to_string(index) + ": " + string(e.what()) + "\n"; - errlog("Error while trying to get TLS context with index %d: %s\n", index, string(e.what())); - } -#else - g_outputBuffer="DNS over TLS support is not present!\n"; -#endif - return result; - }); - luaCtx.writeFunction("getTLSFrontend", [](uint64_t index) { std::shared_ptr result = nullptr; #ifdef HAVE_DNS_OVER_TLS @@ -3224,18 +3200,6 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) return dnsdist::getDoTFrontends().size(); }); - luaCtx.registerFunction::*)()>("rotateTicketsKey", [](std::shared_ptr& ctx) { - if (ctx != nullptr) { - ctx->rotateTicketsKey(time(nullptr)); - } - }); - - luaCtx.registerFunction::*)(const std::string&)>("loadTicketsKeys", [](std::shared_ptr& ctx, const std::string& file) { - if (ctx != nullptr) { - ctx->loadTicketsKeys(file); - } - }); - luaCtx.registerFunction::*)() const>("getAddressAndPort", [](const std::shared_ptr& frontend) { if (frontend == nullptr) { return std::string(); diff --git a/pdns/dnsdistdist/docs/advanced/tls-sessions-management.rst b/pdns/dnsdistdist/docs/advanced/tls-sessions-management.rst index 8b6b5e61ccd5..6700b91003c2 100644 --- a/pdns/dnsdistdist/docs/advanced/tls-sessions-management.rst +++ b/pdns/dnsdistdist/docs/advanced/tls-sessions-management.rst @@ -34,7 +34,7 @@ By default, dnsdist will generate a new, random STEK at startup for each :func:` When the automatic rotation mechanism kicks in a new, random key will be added to the list of keys. With the OpenSSL provider, the new key becomes active, so new tickets will be encrypted with this key, and the existing keys become passive and only be used to decrypt existing tickets. With the GnuTLS provider only one key is currently supported so the existing keys are immediately discarded. This automatic rotation can be disabled by setting ``ticketsKeysRotationDelay`` to 0. -It is also possible to manually request a STEK rotation using the :func:`getDOHFrontend` (DoH) and :func:`getTLSContext` (DoT) functions to retrieve the bind object, and calling its ``rotateTicketsKey`` method (:meth:`DOHFrontend:rotateTicketsKey`, :meth:`TLSContext:rotateTicketsKey`). +It is also possible to manually request a STEK rotation using the :func:`getDOHFrontend` (DoH) and :func:`getTLSFrontend` (DoT) functions to retrieve the bind object, and calling its ``rotateTicketsKey`` method (:meth:`DOHFrontend:rotateTicketsKey`, :meth:`TLSFrontend:rotateTicketsKey`). The default settings should be fine for most deployments, but generating a random key for every dnsdist instance will not allow resuming the session from a different instance in a cluster. It is also not very useful to have a different key for every :func:`addTLSLocal` and :func:`addDOHLocal` directive if you are using the same certificate and key, and it would be much better to use the same STEK to improve the session resumption ratio. @@ -53,7 +53,7 @@ The file can then be loaded at startup by using the ``ticketKeyFile`` parameter If the file contains several keys, so for example 240 random bytes, dnsdist will load several STEKs, using the last one for encrypting new tickets and all of them to decrypt existing tickets. In order to rotate the keys at runtime, it is possible to instruct dnsdist to reload the content of the certificates, keys, and STEKs from the same file used at configuration time, for all DoH and DoH binds, by issuing the :func:`reloadAllCertificates` command. -It can also be done one bind at a time using the :func:`getDOHFrontend` (DoH) and :func:`getTLSContext` (DoT) functions to retrieve the bind object, and calling its ``loadTicketsKeys`` method (:meth:`DOHFrontend:loadTicketsKeys`, :meth:`TLSContext:loadTicketsKeys`). +It can also be done one bind at a time using the :func:`getDOHFrontend` (DoH) and :func:`getTLSFrontend` (DoT) functions to retrieve the bind object, and calling its ``loadTicketsKeys`` method (:meth:`DOHFrontend:loadTicketsKeys`, :meth:`TLSFrontend:loadTicketsKeys`). One possible way of handling manual rotation of the key would be to first: diff --git a/pdns/dnsdistdist/docs/reference/config.rst b/pdns/dnsdistdist/docs/reference/config.rst index bddf2756059d..e3fe1835b42d 100644 --- a/pdns/dnsdistdist/docs/reference/config.rst +++ b/pdns/dnsdistdist/docs/reference/config.rst @@ -1226,6 +1226,9 @@ Status, Statistics and More .. function:: getTLSContext(idx) + .. versionchanged:: 2.0.0 + This directive was removed in version 2.0.0, see :func:`getTLSFrontend` instead. + Return the TLSContext object for the context of index ``idx``. .. function:: getTLSFrontend(idx) @@ -1424,7 +1427,10 @@ Status, Statistics and More .. function:: showTLSContexts() - Print the list of all available DNS over TLS contexts. + .. versionchanged:: 2.0.0 + This function has been renamed to :func:`showTLSFrontends`. + + Print the list of all available DNS over TLS frontends. .. function:: showTLSErrorCounters() @@ -1432,6 +1438,15 @@ Status, Statistics and More Display metrics about TLS handshake failures. +.. function:: showTLSContexts() + + .. versionadded:: 2.0.0 + + .. note:: + Before 2.0.0 this function was called ``showTLSContexts``. + + Print the list of all available DNS over TLS frontends. + .. function:: showVersion() Print the version of dnsdist @@ -2509,6 +2524,9 @@ TLSContext .. class:: TLSContext + .. versionchanged:: 2.0.0 + This class has been removed in version 2.0.0. + This object represents an address and port dnsdist is listening on for DNS over TLS queries. .. method:: TLSContext:loadTicketsKeys(ticketsKeysFile) diff --git a/pdns/dnsdistdist/docs/upgrade_guide.rst b/pdns/dnsdistdist/docs/upgrade_guide.rst index 7ea7c9638381..40d64175aa09 100644 --- a/pdns/dnsdistdist/docs/upgrade_guide.rst +++ b/pdns/dnsdistdist/docs/upgrade_guide.rst @@ -1,6 +1,12 @@ Upgrade Guide ============= +1.9.x to 2.0.0 +-------------- + +:func:`showTLSContexts` has been renamed to :func:`showTLSFrontends`. +:func:`getTLSContext` and the associated :class:`TLSContext` have been removed, please use :func:`getTLSFrontend` and the associated :class:`TLSFrontend` instead. + 1.8.x to 1.9.0 -------------- diff --git a/regression-tests.dnsdist/test_TLSSessionResumption.py b/regression-tests.dnsdist/test_TLSSessionResumption.py index 97eb826c3be7..7f41c79491f9 100644 --- a/regression-tests.dnsdist/test_TLSSessionResumption.py +++ b/regression-tests.dnsdist/test_TLSSessionResumption.py @@ -230,20 +230,20 @@ def testSessionResumption(self): # rotate the TLS session ticket keys several times, but keep the previously active one around so we can resume for _ in range(self._numberOfKeys - 1): - self.sendConsoleCommand("getTLSContext(0):rotateTicketsKey()") + self.sendConsoleCommand("getTLSFrontend(0):rotateTicketsKey()") # the session should be resumed and a new ticket, encrypted with the newly active key, should be stored self.assertTrue(self.checkSessionResumed('127.0.0.1', self._tlsServerPort, self._serverName, self._caCert, '/tmp/session.dot', '/tmp/session.dot')) # rotate the TLS session ticket keys several times, but keep the previously active one around so we can resume for _ in range(self._numberOfKeys - 1): - self.sendConsoleCommand("getTLSContext(0):rotateTicketsKey()") + self.sendConsoleCommand("getTLSFrontend(0):rotateTicketsKey()") self.assertTrue(self.checkSessionResumed('127.0.0.1', self._tlsServerPort, self._serverName, self._caCert, '/tmp/session.dot', '/tmp/session.dot')) # rotate the TLS session ticket keys several times, not keeping any key around this time! for _ in range(self._numberOfKeys): - self.sendConsoleCommand("getTLSContext(0):rotateTicketsKey()") + self.sendConsoleCommand("getTLSFrontend(0):rotateTicketsKey()") # we should not be able to resume self.assertFalse(self.checkSessionResumed('127.0.0.1', self._tlsServerPort, self._serverName, self._caCert, '/tmp/session.dot', '/tmp/session.dot')) @@ -252,26 +252,26 @@ def testSessionResumption(self): self.generateTicketKeysFile(self._numberOfKeys, '/tmp/ticketKeys.1') self.generateTicketKeysFile(self._numberOfKeys - 1, '/tmp/ticketKeys.2') # load all ticket keys from the file - self.sendConsoleCommand("getTLSContext(0):loadTicketsKeys('/tmp/ticketKeys.1')") + self.sendConsoleCommand("getTLSFrontend(0):loadTicketsKeys('/tmp/ticketKeys.1')") # create a new session, resume it self.assertFalse(self.checkSessionResumed('127.0.0.1', self._tlsServerPort, self._serverName, self._caCert, '/tmp/session.dot', None)) self.assertTrue(self.checkSessionResumed('127.0.0.1', self._tlsServerPort, self._serverName, self._caCert, '/tmp/session.dot', '/tmp/session.dot', allowNoTicket=True)) # reload the same keys - self.sendConsoleCommand("getTLSContext(0):loadTicketsKeys('/tmp/ticketKeys.1')") + self.sendConsoleCommand("getTLSFrontend(0):loadTicketsKeys('/tmp/ticketKeys.1')") # should still be able to resume self.assertTrue(self.checkSessionResumed('127.0.0.1', self._tlsServerPort, self._serverName, self._caCert, '/tmp/session.dot', '/tmp/session.dot', allowNoTicket=True)) # rotate the TLS session ticket keys several times, but keep the previously active one around so we can resume for _ in range(self._numberOfKeys - 1): - self.sendConsoleCommand("getTLSContext(0):rotateTicketsKey()") + self.sendConsoleCommand("getTLSFrontend(0):rotateTicketsKey()") # should still be able to resume self.assertTrue(self.checkSessionResumed('127.0.0.1', self._tlsServerPort, self._serverName, self._caCert, '/tmp/session.dot', '/tmp/session.dot')) # reload the same keys - self.sendConsoleCommand("getTLSContext(0):loadTicketsKeys('/tmp/ticketKeys.1')") + self.sendConsoleCommand("getTLSFrontend(0):loadTicketsKeys('/tmp/ticketKeys.1')") # since the last key was only present in memory, we should not be able to resume self.assertFalse(self.checkSessionResumed('127.0.0.1', self._tlsServerPort, self._serverName, self._caCert, '/tmp/session.dot', '/tmp/session.dot')) @@ -280,20 +280,20 @@ def testSessionResumption(self): # generate a file with only _numberOfKeys - 1 keys, so the last active one should still be around after loading that one self.generateTicketKeysFile(self._numberOfKeys - 1, '/tmp/ticketKeys.2') - self.sendConsoleCommand("getTLSContext(0):loadTicketsKeys('/tmp/ticketKeys.2')") + self.sendConsoleCommand("getTLSFrontend(0):loadTicketsKeys('/tmp/ticketKeys.2')") # we should be able to resume, and the ticket should be re-encrypted with the new key (NOTE THAT we store into a new file!!) self.assertTrue(self.checkSessionResumed('127.0.0.1', self._tlsServerPort, self._serverName, self._caCert, '/tmp/session.dot.2', '/tmp/session.dot')) self.assertTrue(self.checkSessionResumed('127.0.0.1', self._tlsServerPort, self._serverName, self._caCert, '/tmp/session.dot.2', '/tmp/session.dot.2', allowNoTicket=True)) # rotate all keys, we should not be able to resume for _ in range(self._numberOfKeys): - self.sendConsoleCommand("getTLSContext(0):rotateTicketsKey()") + self.sendConsoleCommand("getTLSFrontend(0):rotateTicketsKey()") self.assertFalse(self.checkSessionResumed('127.0.0.1', self._tlsServerPort, self._serverName, self._caCert, '/tmp/session.dot.3', '/tmp/session.dot.2')) # reload from file 1, the old session should resume - self.sendConsoleCommand("getTLSContext(0):loadTicketsKeys('/tmp/ticketKeys.1')") + self.sendConsoleCommand("getTLSFrontend(0):loadTicketsKeys('/tmp/ticketKeys.1')") self.assertTrue(self.checkSessionResumed('127.0.0.1', self._tlsServerPort, self._serverName, self._caCert, '/tmp/session.dot', '/tmp/session.dot', allowNoTicket=True)) # reload from file 2, the latest session should resume - self.sendConsoleCommand("getTLSContext(0):loadTicketsKeys('/tmp/ticketKeys.2')") + self.sendConsoleCommand("getTLSFrontend(0):loadTicketsKeys('/tmp/ticketKeys.2')") self.assertTrue(self.checkSessionResumed('127.0.0.1', self._tlsServerPort, self._serverName, self._caCert, '/tmp/session.dot.2', '/tmp/session.dot.2', allowNoTicket=True))