From: Remi Gacogne Date: Fri, 3 Sep 2021 15:35:18 +0000 (+0200) Subject: dnsdist: Add an outgoing DoH workers setting, minimal documentation X-Git-Tag: dnsdist-1.7.0-alpha1~23^2~18 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=168ef5943e68881d9d39b913c2946e72e4438379;p=thirdparty%2Fpdns.git dnsdist: Add an outgoing DoH workers setting, minimal documentation --- diff --git a/pdns/dnsdist-console.cc b/pdns/dnsdist-console.cc index 4d6778460a..e4c0eb896a 100644 --- a/pdns/dnsdist-console.cc +++ b/pdns/dnsdist-console.cc @@ -663,6 +663,7 @@ const std::vector g_consoleKeywords{ { "SetECSPrefixLengthAction", true, "v4, v6", "Set the ECS prefix length. Subsequent rules are processed after this action" }, { "SetMacAddrAction", true, "option", "Add the source MAC address to the query as EDNS0 option option. This action is currently only supported on Linux. Subsequent rules are processed after this action" }, { "SetNoRecurseAction", true, "", "strip RD bit from the question, let it go through" }, + { "setOutgoingDoHWorkerThreads", true, "n", "Number of outgoing DoH worker threads" }, { "SetProxyProtocolValuesAction", true, "values", "Set the Proxy-Protocol values for this queries to 'values'" }, { "SetSkipCacheAction", true, "", "Don’t lookup the cache for this query, don’t store the answer" }, { "SetSkipCacheResponseAction", true, "", "Don’t store this response into the cache" }, diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 922e5e5786..b06ea8b8ee 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -536,6 +536,9 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) if (ret->d_tlsCtx) { setupDoHClientProtocolNegotiation(ret->d_tlsCtx); } + if (g_outgoingDoHWorkerThreads == 0) { + g_outgoingDoHWorkerThreads = 1; + } if (vars.count("addXForwardedHeaders")) { ret->d_addXForwardedHeaders = boost::get(vars.at("addXForwardedHeaders")); @@ -1258,6 +1261,14 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) setMaxCachedTCPConnectionsPerDownstream(max); }); + luaCtx.writeFunction("setOutgoingDoHWorkerThreads", [](uint64_t workers) { + if (!g_configurationDone) { + g_outgoingDoHWorkerThreads = workers; + } else { + g_outputBuffer="The amount of outgoing DoH worker threads cannot be altered at runtime!\n"; + } + }); + luaCtx.writeFunction("setOutgoingTLSSessionsCacheMaxTicketsPerBackend", [](uint16_t max) { if (g_configurationDone) { g_outputBuffer = "setOutgoingTLSSessionsCacheMaxTicketsPerBackend() cannot be called at runtime!\n"; diff --git a/pdns/dnsdistdist/dnsdist-nghttp2.cc b/pdns/dnsdistdist/dnsdist-nghttp2.cc index f99d6870d3..6b933168a2 100644 --- a/pdns/dnsdistdist/dnsdist-nghttp2.cc +++ b/pdns/dnsdistdist/dnsdist-nghttp2.cc @@ -40,6 +40,7 @@ std::atomic g_dohStatesDumpRequested{0}; std::unique_ptr g_dohClientThreads{nullptr}; +uint16_t g_outgoingDoHWorkerThreads{0}; #ifdef HAVE_NGHTTP2 class DoHConnectionToBackend : public TCPConnectionToBackend @@ -1067,8 +1068,8 @@ struct DoHClientCollection::DoHWorkerThread int d_crossProtocolQueryPipe{-1}; }; -DoHClientCollection::DoHClientCollection(size_t maxThreads) : - d_clientThreads(maxThreads), d_maxThreads(maxThreads) +DoHClientCollection::DoHClientCollection(size_t numberOfThreads) : + d_clientThreads(numberOfThreads) { } @@ -1134,7 +1135,7 @@ void DoHClientCollection::addThread() std::lock_guard lock(d_mutex); if (d_numberOfThreads >= d_clientThreads.size()) { - vinfolog("Adding a new DoH client thread would exceed the vector size (%d/%d), skipping. Consider increasing the maximum amount of DoH client threads with setMaxDoHClientThreads() in the configuration.", d_numberOfThreads.load(), d_clientThreads.size()); + vinfolog("Adding a new DoH client thread would exceed the vector size (%d/%d), skipping. Consider increasing the maximum amount of DoH client threads with setMaxDoHClientThreads() in the configuration.", d_numberOfThreads, d_clientThreads.size()); close(crossProtocolFDs[0]); close(crossProtocolFDs[1]); return; @@ -1165,8 +1166,7 @@ void DoHClientCollection::addThread() bool initDoHWorkers() { #ifdef HAVE_NGHTTP2 -#warning FIXME: number of DoH threads - g_dohClientThreads = std::make_unique(4); + g_dohClientThreads = std::make_unique(g_outgoingDoHWorkerThreads); g_dohClientThreads->addThread(); return true; #else diff --git a/pdns/dnsdistdist/dnsdist-nghttp2.hh b/pdns/dnsdistdist/dnsdist-nghttp2.hh index afc8737586..d36c9959f0 100644 --- a/pdns/dnsdistdist/dnsdist-nghttp2.hh +++ b/pdns/dnsdistdist/dnsdist-nghttp2.hh @@ -33,12 +33,7 @@ struct CrossProtocolQuery; class DoHClientCollection { public: - DoHClientCollection(size_t maxThreads); - - bool hasReachedMaxThreads() const - { - return d_numberOfThreads >= d_maxThreads; - } + DoHClientCollection(size_t numberOfThreads); uint64_t getThreadsCount() const { @@ -53,13 +48,13 @@ private: std::mutex d_mutex; std::vector d_clientThreads; - pdns::stat_t d_numberOfThreads{0}; pdns::stat_t d_pos{0}; - const uint64_t d_maxThreads{0}; + uint64_t d_numberOfThreads{0}; }; extern std::unique_ptr g_dohClientThreads; extern std::atomic g_dohStatesDumpRequested; +extern uint16_t g_outgoingDoHWorkerThreads; class TLSCtx; diff --git a/pdns/dnsdistdist/docs/advanced/tuning.rst b/pdns/dnsdistdist/docs/advanced/tuning.rst index 9afa06c7d0..c59fc46874 100644 --- a/pdns/dnsdistdist/docs/advanced/tuning.rst +++ b/pdns/dnsdistdist/docs/advanced/tuning.rst @@ -70,6 +70,13 @@ For DNS over HTTPS, every :func:`addDOHLocal` directive adds a new thread dealin When dealing with a large traffic load, it might happen that the internal pipe used to pass queries between the threads handling the incoming connections and the one getting a response from the backend become full too quickly, degrading performance and causing timeouts. This can be prevented by increasing the size of the internal pipe buffer, via the `internalPipeBufferSize` option of :func:`addDOHLocal`. Setting a value of `1048576` is known to yield good results on Linux. +Outgoing DoH +------------ + +Starting with 1.7.0, dnsdist supports communicating with the backend using DNS over HTTPS. The incoming queries, after the processing of rules if any, are passed to one of the DoH workers over a pipe. The DoH worker handles the communication with the backend, retrieves the response, and either responds directly to the client (queries coming over UDP) or pass it back over a pipe to the initial thread (queries coming over TCP, DoT or DoH). +The number of outgoing DoH worker threads can be configured using :func:`setOutgoingDoHWorkerThreads`. + + TCP and DNS over TLS -------------------- diff --git a/pdns/dnsdistdist/docs/guides/dns-over-https.rst b/pdns/dnsdistdist/docs/guides/dns-over-https.rst index b4035ab055..1feefa9997 100644 --- a/pdns/dnsdistdist/docs/guides/dns-over-https.rst +++ b/pdns/dnsdistdist/docs/guides/dns-over-https.rst @@ -75,3 +75,9 @@ dnsdist provides a lot of counters to investigate issues: * :func:`showTCPStats` will display a lot of information about current and passed connections * :func:`showTLSErrorCounters` some metrics about why TLS sessions failed to establish * :func:`showDOHResponseCodes` returns metrics about HTTP response codes sent by dnsdist + +Outgoing +-------- + +Support for securing the exchanges between dnsdist and the backend will be implemented in 1.7.0, and will lead to all queries, regardless of whether they were initially received by dnsdist over UDP, TCP, DoT or DoH, being forwarded over a secure DNS over HTTPS channel. +That support can be enabled via the ``dohPath`` parameter of the :func:`newServer` command. Additional parameters control the TLS provider used (``tls``), the validation of the certificate presented by the backend (``caStore``, ``validateCertificates``), the actual TLS ciphers used (``ciphers``, ``ciphersTLS13``) and the SNI value sent (``subjectName``). diff --git a/pdns/dnsdistdist/docs/reference/config.rst b/pdns/dnsdistdist/docs/reference/config.rst index 141c29b75a..5670c65072 100644 --- a/pdns/dnsdistdist/docs/reference/config.rst +++ b/pdns/dnsdistdist/docs/reference/config.rst @@ -489,7 +489,7 @@ Servers Added ``maxInFlight`` to server_table. .. versionchanged:: 1.7.0 - Added ``caStore``, ``checkTCP``, ``ciphers``, ``ciphers13``, ``subjectName``, ``tcpOnly``, ``tls`` and ``validateCertificates`` to server_table. + Added ``caStore``, ``checkTCP``, ``ciphers``, ``ciphers13``, ``dohPath``, ``subjectName``, ``tcpOnly``, ``tls`` and ``validateCertificates`` to server_table. Add a new backend server. Call this function with either a string:: @@ -539,12 +539,13 @@ Servers maxInFlight=NUM, -- Maximum number of in-flight queries. The default is 0, which disables out-of-order processing. It should only be enabled if the backend does support out-of-order processing. As of 1.6.0, out-of-order processing needs to be enabled on the frontend as well, via :func:`addLocal` and/or :func:`addTLSLocal`. Note that out-of-order is always enabled on DoH frontends. tcpOnly=BOOL, -- Always forward queries to that backend over TCP, never over UDP. Always enabled for TLS backends. Default is false. checkTCP=BOOL, -- Whether to do healthcheck queries over TCP, instead of UDP. Always enabled for DNS over TLS backend. Default is false. - tls=STRING, -- Enable DNS over TLS communications for this backend, using the TLS provider ("openssl" or "gnutls") passed in parameter. Default is an empty string, which means this backend is used for plain UDP and TCP. + tls=STRING, -- Enable DNS over TLS communications for this backend, or DNS over HTTPS if ``dohPath`` is set, using the TLS provider ("openssl" or "gnutls") passed in parameter. Default is an empty string, which means this backend is used for plain UDP and TCP. caStore=STRING, -- Specifies the path to the CA certificate file, in PEM format, to use to check the certificate presented by the backend. Default is an empty string, which means to use the system CA store. Note that this directive is only used if ``validateCertificates`` is set. ciphers=STRING, -- The TLS ciphers to use. The exact format depends on the provider used. When the OpenSSL provider is used, ciphers for TLS 1.3 must be specified via ``ciphersTLS13``. ciphersTLS13=STRING, -- The ciphers to use for TLS 1.3, when the OpenSSL provider is used. When the GnuTLS provider is used, ``ciphers`` applies regardless of the TLS protocol and this setting is not used. subjectName=STRING, -- The subject name passed in the SNI value of the TLS handshake, and against which to validate the certificate presented by the backend. Default is empty. - validateCertificates=BOOL -- Whether the certificate presented by the backend should be validated against the CA store (see ``caStore``). Default is true. + validateCertificates=BOOL,-- Whether the certificate presented by the backend should be validated against the CA store (see ``caStore``). Default is true. + dohPath=STRING -- Enable DNS over HTTPS communication for this backend, using POST queries to the HTTP host supplied as ``subjectName`` and the HTTP path supplied in this parameter. }) :param str server_string: A simple IP:PORT string. diff --git a/pdns/dnsdistdist/docs/reference/tuning.rst b/pdns/dnsdistdist/docs/reference/tuning.rst index c8911c26a2..d80be66d4a 100644 --- a/pdns/dnsdistdist/docs/reference/tuning.rst +++ b/pdns/dnsdistdist/docs/reference/tuning.rst @@ -68,6 +68,12 @@ Tuning related functions :param int num: +.. function:: setOutgoingDoHWorkerThreads(num) + + .. versionadded:: 1.7.0 + + Set the number of worker threads to use for outgoing DoH. That number defaults to 0 but is automatically raised to 1 when DoH is enabled on at least one backend. + .. function:: setStaleCacheEntriesTTL(num) Allows using cache entries expired for at most n seconds when no backend available to answer for a query