Skip to content

Commit

Permalink
dnsdist: Better documentation of the zero-scope feature
Browse files Browse the repository at this point in the history
  • Loading branch information
rgacogne committed Jul 19, 2024
1 parent 4d6b4d6 commit b0de808
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 10 deletions.
1 change: 1 addition & 0 deletions pdns/dnsdistdist/docs/advanced/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ These chapters contain information on the advanced features of dnsdist
internal-design
asynchronous-processing
xsk
zero-scope
7 changes: 1 addition & 6 deletions pdns/dnsdistdist/docs/advanced/passing-source-address.rst
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,7 @@ Influence on caching
--------------------

When dnsdist's packet cache is in use, it is important to note that the cache lookup is done **after** adding ECS, because it prevents serving the same response to clients from different subnets when ECS is passed to an authoritative server doing GeoIP, or to a backend doing custom filtering.
However that means that passing a narrow ECS source will effectively kill dnsdist's cache ratio, since a given answer will only be a cache hit for clients in the same ECS subnet. Therefore, unless a broad ECS source (greater than 24, for example) is used, it's better to disable caching.

One exception to that rule is the zero-scope feature, which allows dnsdist to detect that a response sent by the backend has a 0-scope ECS value, indicating that the answer is not ECS-specific and can be used for all clients. dnsdist will then store the answer in its packet cache using the initial query, before ECS has been added.
For that feature to work, dnsdist will look up twice into the packet cache when a query arrives, first without and then with ECS. That way, when most of the responses sent by a backend are not ECS-specific and can be served to all clients, dnsdist will still be able to have a great cache-hit ratio for non ECS-specific entries.

That feature is enabled by setting ``disableZeroScope=false`` on :func:`newServer` (default) and ``parseECS=true`` on :func:`newPacketCache` (not the default).
However that means that passing a narrow ECS source will effectively kill dnsdist's cache ratio, since a given answer will only be a cache hit for clients in the same ECS subnet. Therefore, unless a broad ECS source (greater than 24, for example) is used, it's better to disable caching. The zero-scope feature can be enabled to mitigate this drawback, as described in :doc:`zero-scope`.


Things are different for the proxy protocol, because dnsdist then does the cache lookup **before** adding the payload. It means that caching can still be enabled as long as the response is not source-dependent, but should be disabled otherwise.
Expand Down
13 changes: 13 additions & 0 deletions pdns/dnsdistdist/docs/advanced/zero-scope.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
EDNS Client Subnet Zero Scope
==================================

As described in :doc:`Passing the source address to the backend <passing-source-address>`, :program:`dnsdist` can add an ``EDNS`` Client Subnet option to an incoming query to provide the downstream server with the address of the client talking to it. The downstream server can then potentially use this knowledge to reply with a response that has been tailored for this specific client, and should not be served to any other client. By default :program:`dnsdist` ensures that such a response is only served to intendend client from its internal packet cache, including the added ``EDNS`` Client Subnet option in the data that is hashed to compute the cache key. This is the safest option, but is not optimal because some responses were not actually tied to a specific client and could have been used for all of them. The downstream server can signal this by setting the scope in the ``EDNS`` Client Subnet option included in the response.

This is where the zero-scope feature comes to play, allowing :program:`dnsdist` to parse the detect that a response sent by the backend has a scope value set to ``0``, indicating that the answer is not specific to a given client and can be used for allof them. :program:`dnsdist` will then store the answer in its packet cache using the initial query, before the ``EDNS`` Client Subnet option has been added.

The second step needed for that feature to work properly is for :program:`dnsdist` to look up twice into the packet cache when a query arrives, first without and then with the ``EDNS`` Client Subnet option. That way, when most of the responses sent by a backend are not specific and can be served to all clients, :program:`dnsdist` will still be able to have a great cache-hit ratio for non specific entries.

This feature is enabled when:

* ``disableZeroScope=true`` is not set on :func:`newServer` (the default is ``false``)
* and ``parseECS=true`` is set on :func:`newPacketCache` (which is not the default).
8 changes: 4 additions & 4 deletions pdns/dnsdistdist/docs/reference/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ EDNS Client Subnet

.. function:: setECSOverride(bool)

When ``useClientSubnet`` in :func:`newServer` is set and dnsdist adds an EDNS Client Subnet Client option to the query, override an existing option already present in the query, if any.
When ``useClientSubnet`` in :func:`newServer` is set and dnsdist adds an EDNS Client Subnet Client option to the query, override an existing option already present in the query, if any. Please see :doc:`../advanced/passing-source-address` for more information.
Note that it's not recommended to enable ``setECSOverride`` in front of an authoritative server responding with EDNS Client Subnet information as mismatching data (ECS scopes) can confuse clients and lead to SERVFAIL responses on downstream nameservers.

:param bool: Whether to override an existing EDNS Client Subnet option present in the query. Defaults to false
Expand Down Expand Up @@ -684,15 +684,15 @@ Servers
``maxCheckFailures`` ``number`` "Allow ``number`` check failures before declaring the backend down, default: 1"
``checkInterval`` ``number`` "The time in seconds between health checks"
``mustResolve`` ``bool`` "Set to true when the health check MUST return a RCODE different from NXDomain, ServFail and Refused. Default is false, meaning that every RCODE except ServFail is considered valid"
``useClientSubnet`` ``bool`` "Add the client's IP address in the EDNS Client Subnet option when forwarding the query to this backend"
``useClientSubnet`` ``bool`` "Add the client's IP address in the EDNS Client Subnet option when forwarding the query to this backend. Default is false. Please see :doc:`../advanced/passing-source-address` for more information"
``source`` ``string`` "The source address or interface to use for queries to this backend, by default this is left to the kernel's address selection.
The following formats are supported:

- address, e.g. ``""192.0.2.2""``
- interface name, e.g. ``""eth0""``
- address@interface, e.g. ``""192.0.2.2@eth0""`` "
``sockets`` ``number`` "Number of UDP sockets (and thus source ports) used toward the backend server, defaults to a single one. Note that for backends which are multithreaded, this setting will have an effect on the number of cores that will be used to process traffic from dnsdist. For example you may want to set 'sockets' to a number somewhat higher than the number of worker threads configured in the backend, particularly if the Linux kernel is being used to distribute traffic to multiple threads listening on the same socket (via `reuseport`). See also :func:`setRandomizedOutgoingSockets`."
``disableZeroScope`` ``bool`` "Disable the EDNS Client Subnet 'zero scope' feature, which does a cache lookup for an answer valid for all subnets (ECS scope of 0) before adding ECS information to the query and doing the regular lookup. This requires the ``parseECS`` option of the corresponding cache to be set to true"
``disableZeroScope`` ``bool`` "Disable the EDNS Client Subnet :doc:`../advanced/zero-scope` feature, which does a cache lookup for an answer valid for all subnets (ECS scope of 0) before adding ECS information to the query and doing the regular lookup. Default is false. This requires the ``parseECS`` option of the corresponding cache to be set to true"
``rise`` ``number`` "Require ``number`` consecutive successful checks before declaring the backend up, default: 1"
``useProxyProtocol`` ``bool`` "Add a proxy protocol header to the query, passing along the client's IP address and port along with the original destination address and port. Default is disabled."
``reconnectOnUp`` ``bool`` "Close and reopen the sockets when a server transits from Down to Up. This helps when an interface is missing when dnsdist is started. Default is disabled."
Expand Down Expand Up @@ -979,7 +979,7 @@ See :doc:`../guides/cache` for a how to.
* ``maxTTL=86400``: int - Cap the TTL for records to his number.
* ``minTTL=0``: int - Don't cache entries with a TTL lower than this.
* ``numberOfShards=20``: int - Number of shards to divide the cache into, to reduce lock contention. Used to be 1 (no shards) before 1.6.0, and is now 20.
* ``parseECS=false``: bool - Whether any EDNS Client Subnet option present in the query should be extracted and stored to be able to detect hash collisions involving queries with the same qname, qtype and qclass but a different incoming ECS value. Enabling this option adds a parsing cost and only makes sense if at least one backend might send different responses based on the ECS value, so it's disabled by default. Enabling this option is required for the 'zero scope' option to work
* ``parseECS=false``: bool - Whether any EDNS Client Subnet option present in the query should be extracted and stored to be able to detect hash collisions involving queries with the same qname, qtype and qclass but a different incoming ECS value. Enabling this option adds a parsing cost and only makes sense if at least one backend might send different responses based on the ECS value, so it's disabled by default. Enabling this option is required for the :doc:`../advanced/zero-scope` option to work
* ``staleTTL=60``: int - When the backend servers are not reachable, and global configuration ``setStaleCacheEntriesTTL`` is set appropriately, TTL that will be used when a stale cache entry is returned.
* ``temporaryFailureTTL=60``: int - On a SERVFAIL or REFUSED from the backend, cache for this amount of seconds..
* ``cookieHashing=false``: bool - If true, EDNS Cookie values will be hashed, resulting in separate entries for different cookies in the packet cache. This is required if the backend is sending answers with EDNS Cookies, otherwise a client might receive an answer with the wrong cookie.
Expand Down

0 comments on commit b0de808

Please sign in to comment.