From 35cafa616eae6282d9169afd10f1ae16a07e31c0 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Thu, 10 Apr 2025 11:13:49 +0200 Subject: [PATCH] dnsdist: Document how STEKs are managed in frontend groups --- pdns/dnsdistdist/dnsdist-settings-definitions.yml | 2 +- .../dnsdistdist/docs/advanced/tls-sessions-management.rst | 8 +++++--- pdns/dnsdistdist/docs/reference/yaml-settings.rst | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/pdns/dnsdistdist/dnsdist-settings-definitions.yml b/pdns/dnsdistdist/dnsdist-settings-definitions.yml index 754ccf0cd8..018ad8580c 100644 --- a/pdns/dnsdistdist/dnsdist-settings-definitions.yml +++ b/pdns/dnsdistdist/dnsdist-settings-definitions.yml @@ -1084,7 +1084,7 @@ bind: - name: "threads" type: "u32" default: "1" - description: "Number of listening threads to create for this frontend" + description: "Number of listening threads to create for this frontend. Note that each listening thread will have its own metrics, but identical DoT and DoH threads will share the same TLS Session Ticket Encryption Keys to improve session resumption rates. One side-effect is that rotating / altering the STEKs on all threads in a frontend group except the first one will be ignored, to prevent unwanted actions by existing code. :func:`reloadAllCertificates` properly handles frontend groups." - name: "interface" type: "String" default: "" diff --git a/pdns/dnsdistdist/docs/advanced/tls-sessions-management.rst b/pdns/dnsdistdist/docs/advanced/tls-sessions-management.rst index 6700b91003..9f03285ace 100644 --- a/pdns/dnsdistdist/docs/advanced/tls-sessions-management.rst +++ b/pdns/dnsdistdist/docs/advanced/tls-sessions-management.rst @@ -28,14 +28,16 @@ Keys management for incoming connections in dnsdist dnsdist supports both server's side (sessions) and client's side (tickets) resumption for incoming connections (client to dnsdist). -Since server-side sessions cannot be shared between several instances, and pretty much all clients support tickets anyway, we do recommend disabling the sessions by passing ``numberOfStoredSessions=0`` to the :func:`addDOHLocal` (for DNS over HTTPS) and :func:`addTLSLocal` (for DNS over TLS) functions. +Since server-side sessions cannot be shared between several instances, and pretty much all clients support tickets anyway, we do recommend disabling the sessions by passing ``numberOfStoredSessions=0`` to the :func:`addDOHLocal` (for DNS over HTTPS) and :func:`addTLSLocal` (for DNS over TLS) functions, or setting ``tls.number_of_stored_sessions=0`` on a :ref:`frontend configuration ` when using YAML. -By default, dnsdist will generate a new, random STEK at startup for each :func:`addTLSLocal` and :func:`addDOHLocal` directive, and rotate these STEKs every 12 hours. For each frontend it will keep 5 keys in memory, with only the last one marked as active and used to encrypt new tickets while the remaining ones can still be used to decrypt existing tickets after a rotation. The rotation time and the number of keys to keep in memory can be configured via the ``numberOfTicketsKeys`` and ``ticketsKeysRotationDelay`` parameters of the :func:`addDOHLocal` (for DNS over HTTPS) and :func:`addTLSLocal` (for DNS over TLS) functions. +By default, dnsdist will generate a new, random STEK at startup for each frontend created via :func:`addTLSLocal` and :func:`addDOHLocal` directive, and rotate these STEKs every 12 hours. For each frontend it will keep 5 keys in memory, with only the last one marked as active and used to encrypt new tickets while the remaining ones can still be used to decrypt existing tickets after a rotation. The rotation time and the number of keys to keep in memory can be configured via the ``numberOfTicketsKeys`` and ``ticketsKeysRotationDelay`` parameters of the :func:`addDOHLocal` (for DNS over HTTPS) and :func:`addTLSLocal` (for DNS over TLS) functions. 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:`getTLSFrontend` (DoT) functions to retrieve the bind object, and calling its ``rotateTicketsKey`` method (:meth:`DOHFrontend:rotateTicketsKey`, :meth:`TLSFrontend:rotateTicketsKey`). +There is an important difference when the YAML configuration is used: groups of identical frontends can be created via the ``threads`` parameter of a :ref:`frontend configuration `. Identical frontends then share the same STEKs, even after an automatic or manual rotation. In addition to that, any operation on the STEKs should be done on the first frontend of the group, as attempting to alter the STEKs of the other frontends in a group will be ignored to avoid unwanted side-effects. + 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. In that case it is possible to generate the STEK outside of dnsdist, write it to a file, distribute it to all instances using something like rsync over SSH, and load that file from dnsdist. Please remember that the STEK contains very sensitive data, and should be well-protected from access by unauthorized users. It means that special care should be taken to setting the right permissions on that file. Automatic rotation should then be disabled by setting ``ticketsKeysRotationDelay`` to 0. @@ -48,7 +50,7 @@ For the GnuTLS provider (DoT), the operation is the same but requires only 64 cr dd if=/dev/urandom of=/secure-tmp-fs/tickets.key bs=64 count=1 -The file can then be loaded at startup by using the ``ticketKeyFile`` parameter of the :func:`addDOHLocal` (for DNS over HTTPS) and :func:`addTLSLocal` (for DNS over TLS) functions. +The file can then be loaded at startup by using the ``ticketKeyFile`` parameter of the :func:`addDOHLocal` (for DNS over HTTPS) and :func:`addTLSLocal` (for DNS over TLS) functions, or the ``tls.ticket_key_file`` of a :ref:`frontend configuration ` when using YAML. 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. diff --git a/pdns/dnsdistdist/docs/reference/yaml-settings.rst b/pdns/dnsdistdist/docs/reference/yaml-settings.rst index ede608b6c1..5ac476f506 100644 --- a/pdns/dnsdistdist/docs/reference/yaml-settings.rst +++ b/pdns/dnsdistdist/docs/reference/yaml-settings.rst @@ -112,7 +112,7 @@ General settings for frontends - **listen_address**: String - Address and port to listen to - **reuseport**: Boolean ``(false)`` - Set the ``SO_REUSEPORT`` socket option, allowing several sockets to be listening on this address and port - **protocol**: String ``(Do53)`` - The DNS protocol for this frontend. Supported values are: Do53, DoT, DoH, DoQ, DoH3, DNSCrypt -- **threads**: Unsigned integer ``(1)`` - Number of listening threads to create for this frontend +- **threads**: Unsigned integer ``(1)`` - Number of listening threads to create for this frontend. Note that each listening thread will have its own metrics, but identical DoT and DoH threads will share the same TLS Session Ticket Encryption Keys to improve session resumption rates. One side-effect is that rotating / altering the STEKs on all threads in a frontend group except the first one will be ignored, to prevent unwanted actions by existing code. :func:`reloadAllCertificates` properly handles frontend groups. - **interface**: String ``("")`` - Set the network interface to use - **cpus**: String ``("")`` - Set the CPU affinity for this listener thread, asking the scheduler to run it on a single CPU id, or a set of CPU ids. This parameter is only available if the OS provides the ``pthread_setaffinity_np()`` function - **enable_proxy_protocol**: Boolean ``(false)`` - Whether to expect a proxy protocol v2 header in front of incoming queries coming from an address allowed by the ACL in :ref:`yaml-settings-ProxyProtocolConfiguration`. Default is ``true``, meaning that queries are expected to have a proxy protocol payload if they come from an address present in the proxy protocol ACL -- 2.47.2