]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnsdistdist/docs/guides/downstreams.rst
Merge pull request #11431 from jroessler-ox/docs-kskzskroll-update
[thirdparty/pdns.git] / pdns / dnsdistdist / docs / guides / downstreams.rst
CommitLineData
20d81666
PL
1Configuring Downstream Servers
2==============================
3
4As dnsdist is a loadbalancer and does not do any DNS resolving or serving by itself, it needs downstream servers.
5To add downstream servers, either include them on the command line::
6
7 dnsdist -l 130.161.252.29 -a 130.161.0.0/16 8.8.8.8 208.67.222.222 2620:0:ccc::2 2620:0:ccd::2
8
9Or add them to the configuration file:
10
11.. code-block:: lua
12
13 setLocal("130.161.252.29:53")
14 setACL("130.161.0.0/16")
15 newServer("8.8.8.8")
16 newServer("208.67.222.222")
17 newServer("2620:0:ccc::2")
18 newServer("2620:0:0ccd::2")
19
20These two equivalent configurations give you sane load balancing using a very sensible distribution policy.
21Many users will simply be done with this configuration.
22It works as well for authoritative as for recursive servers.
23
98650fde
RG
24.. _Healthcheck:
25
20d81666
PL
26Healthcheck
27-----------
20d81666 28
e3ab12d9 29dnsdist uses health-check queries, sent once every second, to determine the availability of a backend server. Since 1.8.0, it also supports a ``lazy`` health-checking mode which only sends active health-check queries after a configurable threshold of regular queries have failed, see below.
20d81666 30
e3ab12d9 31By default, an ``A`` query for the "a.root-servers.net." name is sent. A different query type, class and target can be specified by passing, respectively, the ``checkType``, ``checkClass`` and ``checkName`` parameters to :func:`newServer`. The interval between two health-check queries can be set via the ``checkInterval`` interval parameter, and the amount of time for a response to be received via the ``checkTimeout`` one.
0fb7654e 32
98650fde
RG
33Since the 1.3.0 release, the ``checkFunction`` option is also supported, taking a ``Lua`` function as parameter. This function receives a DNSName, two integers and a ``DNSHeader`` object (:ref:`DNSHeader`)
34representing the QName, QType and QClass of the health check query as well as the DNS header, as they are defined before the function was called. The function must return a DNSName and two integers
35representing the new QName, QType and QClass, and can directly modify the ``DNSHeader`` object.
36
37The following example sets the CD flag to true and change the QName to "powerdns.com." and the QType to AAAA while keeping the initial QClass.
ad9344ba 38
98650fde
RG
39.. code-block:: lua
40
41 function myHealthCheck(qname, qtype, qclass, dh)
42 dh:setCD(true)
43
fc16b739 44 return newDNSName("powerdns.com."), DNSQType.AAAA, qclass
98650fde
RG
45 end
46
93ee0a27 47 newServer({address="2620:0:0ccd::2", checkFunction=myHealthCheck})
98650fde 48
e3ab12d9
RG
49The default behavior is to consider any valid response with an ``RCODE`` different from ``ServFail`` as valid.
50If the ``mustResolve`` parameter of :func:`newServer` is set to ``true``, a response will only be considered valid if its ``RCODE`` differs from ``NXDomain``, ``ServFail`` and ``Refused``.
51
52The number of health check failures before a server is considered down is configurable via the ``maxCheckFailures`` parameter, defaulting to 1. In the same way, the number of consecutive successful health checks needed for a server to be considered available can be set via the ``rise`` parameter, defaulting to 1.
53
54The ``CD`` flag can be set on the query by setting ``setCD`` to true.
55e.g.::
56
74c4cff1 57 newServer({address="192.0.2.1", checkType="AAAA", checkClass=DNSClass.CHAOS, checkName="a.root-servers.net.", mustResolve=true})
e3ab12d9
RG
58
59You can turn on logging of health check errors using the :func:`setVerboseHealthChecks` function.
60
61Lazy health-checking
62~~~~~~~~~~~~~~~~~~~~
63
64In some setups, especially on low-end devices, it might not make sense to actively send queries to the backend at a regular interval. Using the feedback from the results of regular queries can instead be used to infer if a backend might not be working properly.
65
d390a979 66Since 1.8.0, dnsdist implements a ``lazy`` mode that can be set via the ``healthCheckMode`` option on :func:`newServer`. In this mode, dnsdist will only send active health-check queries after seeing a configurable amount of regular queries failing. It will then place the backend in a ``PotentialFailure`` state, from the initial ``Healthy`` one, and send health-check queries every ``checkInterval`` seconds. If ``maxCheckFailures`` of these fail, the backend is then moved to a ``Failed`` state and marked as ``down``, and active health-check queries are sent every ``lazyHealthCheckFailedInterval`` seconds. After ``rise`` successful, consecutive queries, the backend will be moved back to the ``Healthy`` state and marked as ``up`` again, and health-check queries will stop.
e3ab12d9
RG
67
68.. figure:: ../imgs/DNSDistLazyHealthChecks.png
69 :align: center
70 :alt: DNSDist Lazy health checks
71
72The threshold of failed regular queries is configured via ``lazyHealthCheckThreshold``, indicating of percentage of regular queries that should have resulted in a failure over the last recent queries. Only the results of the last ``lazyHealthCheckSampleSize`` queries will be considered, as the results are kept in a in-memory circular buffer. The results of at least ``lazyHealthCheckMinSampleCount`` queries should be present for the threshold to be considered meaningful, to avoid an issue with a too small sample.
73
74By default both queries that resulted in a timeout and those that received a ``ServFail`` answer are considered failures, but it is possible to set ``lazyHealthCheckMode`` to ``TimeoutOnly`` so that only timeouts are considered failures.
75
76So for example, if we set ``healthCheckMode`` to ``lazy``, ``lazyHealthCheckSampleSize`` to 100, ``lazyHealthCheckMinSampleCount`` to 10, ``lazyHealthCheckThreshold`` to 30, ``maxCheckFailures`` to 2 and ``rise`` to 2:
77
78- nothing will happen until at least 10 queries have been received
79- only the results of the last 100 queries will be considered
80- if at least 30 of these last 100 have failed, the threshold will be reached and active health-check queries will be sent every ``checkInterval`` seconds
81- if the health-check query is successful, the backend will stay ``up`` and no more query will be sent
82- but if instead two consecutive queries fail, the backend will be marked as ``down`` and health-check queries will be sent every ``lazyHealthCheckFailedInterval`` seconds
412643ce
RG
83- it will take two consecutive, successful health-checks for the backend to go back to ``Healthy`` and be marked `up` again
84
85.. code-block:: lua
86
87 newServer({address="192.0.2.1", healthCheckMode='lazy', checkInterval=1, lazyHealthCheckFailedInterval=30, rise=2, maxCheckFailures=3, lazyHealthCheckThreshold=30, lazyHealthCheckSampleSize=100, lazyHealthCheckMinSampleCount=10, lazyHealthCheckMode='TimeoutOnly'})
e3ab12d9 88
93b395a5
RG
89The 'lazy' mode also supports using an exponential back-off time between health-check queries, once a backend has been moved to the 'down' state. This can be enabled by setting the ``lazyHealthCheckUseExponentialBackOff`` parameter to 'true'. Once the backend has been marked as 'down', the first query will be sent after ``lazyHealthCheckFailedInterval`` seconds, the second one after 2 times ``lazyHealthCheckFailedInterval`` seconds, the third after 4 times ``lazyHealthCheckFailedInterval`` seconds, and so on and so forth, until ``lazyHealthCheckMaxBackOff`` has been reached. Then probes will be sent every ``lazyHealthCheckMaxBackOff`` seconds (default is 3600 so one hour) until the backend comes 'up' again.
90
44f6dbd1
RG
91Source address selection
92------------------------
93
94In multi-homed setups, it can be useful to be able to select the source address or the outgoing
95interface used by dnsdist to contact a downstream server. This can be done by using the `source` parameter::
96
97 newServer({address="192.0.2.1", source="192.0.2.127"})
98 newServer({address="192.0.2.1", source="eth1"})
99 newServer({address="192.0.2.1", source="192.0.2.127@eth1"})
100
101The supported values for source are:
fc9a4408 102
44f6dbd1
RG
103- an IPv4 or IPv6 address, which must exist on the system
104- an interface name
105- an IPv4 or IPv6 address followed by '@' then an interface name
106
107Please note that specifying the interface name is only supported on system having `IP_PKTINFO`.
2f6dc9ee
RG
108
109Securing the channel
110--------------------
111
46297422
RG
112Securing the path to the backend
113--------------------------------
114
115As explained briefly in the quickstart guide, dnsdist has always been designed as a load-balancer placed in
116front of authoritative or recursive servers, assuming that the network path between dnsdist and these servers
117is trusted. This is particularly important because for performance reasons it uses a single connected socket
118for UDP exchanges by default, and easy to predict DNS query IDs, which makes it easy for an attacker to poison
119responses.
120
121If dnsdist is instead intended to be deployed in such a way that the path to its backend is not secure, the
122UDP protocol should not be used, and 'TCP-only', DNS over TLS and DNS over HTTPS protocols used instead, as
123supported since 1.7.0.
124
125Using these protocols leads to all queries, regardless of whether they were initially received by dnsdist over
126UDP, TCP, DoT or DoH, being forwarded over a TCP socket, a secure DNS over TLS channel or a secure DNS over HTTPS
127channel.
128
129The TCP-only mode for a backend can be enabled by using the ``tcpOnly`` parameter of the :func:`newServer` command.
130
6a1e987d 131The DNS over TLS mode via the ``tls`` parameter of the :func:`newServer` command. Additional parameters control the
46297422
RG
132validation of the certificate presented by the backend (``caStore``, ``validateCertificates``), the actual TLS ciphers
133used (``ciphers``, ``ciphersTLS13``) and the SNI value sent (``subjectName``).
134
135The DNS over HTTPS mode in the same way than DNS over TLS but with the additional ``dohPath`` keyword indicating that
136DNS over HTTPS should be used instead of DNS over TLS.
137
138If it is absolutely necessary to support UDP exchanges over an untrusted network, a few options have been introduced in
1391.8.0 to make spoofing attempts harder:
140
70f9051e 141- :func:`setRandomizedIdsOverUDP` will randomize the IDs in outgoing queries, at a small performance cost. :func:`setMaxUDPOutstanding`
dc81f76b 142 should be set at its highest possible value (default since 1.4.0) to make that setting fully efficient.
489bab55 143
46297422 144- :func:`setRandomizedOutgoingSockets` can be used to randomize the outgoing socket used when forwarding a query to a backend.
dc81f76b
RG
145 This requires configuring the backend to use more than one outgoing socket via the ``sockets`` parameter of :func:`newServer`
146 to be of any use.