diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/_static/config.schema.json | 48 | ||||
-rw-r--r-- | doc/user/config-performance.rst | 1 | ||||
-rw-r--r-- | doc/user/config-rate-limiting.rst | 147 |
3 files changed, 195 insertions, 1 deletions
diff --git a/doc/_static/config.schema.json b/doc/_static/config.schema.json index 036a3ce0..a0572813 100644 --- a/doc/_static/config.schema.json +++ b/doc/_static/config.schema.json @@ -1515,7 +1515,8 @@ "renum", "exterr", "rules", - "prlayr" + "prlayr", + "defer" ] }, "description": "List of groups for which 'debug' logging level is set.", @@ -1667,6 +1668,51 @@ "graphite": false } }, + "rate-limiting": { + "description": "Configuration of rate limiting.", + "type": [ + "object", + "null" + ], + "properties": { + "capacity": { + "type": "integer", + "minimum": 1, + "description": "Expected maximal number of blocked networks/hosts at the same time.", + "default": 524288 + }, + "rate-limit": { + "type": "integer", + "minimum": 1, + "description": "Maximal number of allowed queries per second from a single host." + }, + "instant-limit": { + "type": "integer", + "minimum": 1, + "description": "Maximal number of allowed queries at a single point in time from a single host.", + "default": 50 + }, + "slip": { + "type": "integer", + "minimum": 0, + "maximum": 32, + "description": "Number of restricted responses out of which one is sent as truncated, the others are dropped.", + "default": 2 + }, + "log-period": { + "type": "string", + "pattern": "^(\\d+)(us|ms|s|m|h|d)$", + "description": "Minimal time between two log messages, or '0s' to disable.", + "default": "0s" + }, + "dry-run": { + "type": "boolean", + "description": "Perform only classification and logging but no restrictions.", + "default": false + } + }, + "default": null + }, "lua": { "description": "Custom Lua configuration.", "type": "object", diff --git a/doc/user/config-performance.rst b/doc/user/config-performance.rst index dbd8d12d..b09b4a92 100644 --- a/doc/user/config-performance.rst +++ b/doc/user/config-performance.rst @@ -32,3 +32,4 @@ impact than cache settings and number of instances. config-rfc7706 config-priming config-edns-keepalive + config-rate-limiting diff --git a/doc/user/config-rate-limiting.rst b/doc/user/config-rate-limiting.rst new file mode 100644 index 00000000..35342bf9 --- /dev/null +++ b/doc/user/config-rate-limiting.rst @@ -0,0 +1,147 @@ +.. SPDX-License-Identifier: GPL-3.0-or-later + +.. _config-rate-limiting: + +Rate limiting +============= + +Rate limiting is a method to combat DNS reflection amplification +attacks. These attacks rely on the fact that the source address of a UDP query +can be forged, and without a worldwide deployment of `BCP38 +<https://tools.ietf.org/html/bcp38>`_, such a forgery cannot be prevented. +An attacker can use a DNS server (or multiple servers) as an amplification +source to flood a victim with a large number of unsolicited DNS responses. +Rate limiting lowers the amplification factor of these attacks by sending some +responses as truncated or by dropping them altogether. + +See the `operator's overview blogpost <https://en.blog.nic.cz/2024/07/15/knot-resolver-6-news-dos-protection-operators-overview/>`_ +for more in depth introduction to this section, +but beware that the *soft limit* was dropped in favor of the *slip* mechanism +that's common in other DNS servers. + + +.. option:: rate-limiting/rate-limit: <int> + + Maximal allowed number of UDP queries per second from a single IPv6 or IPv4 address. + To be set according to the server performance. + Setting the value enables rate limiting as the rest of the configuration is optional. + + Rate limiting is performed for the whole address and several chosen prefixes. + The limits of prefixes are constant multiples of :option:`rate-limit <rate-limiting/rate-limit: <int>`. + The specific prefixes and multipliers, which might be adjusted in the future, are as follows: + + .. table:: + + +------+------+------+------+------+------+ + | IPv6 | /128 | /64 | /56 | /48 | /32 | + +======+======+======+======+======+======+ + | | 1 | 2 | 3 | 4 | 64 | + +------+------+------+------+------+------+ + + .. table:: + + +------+------+------+------+------+ + | IPv4 | /32 | /24 | /20 | /18 | + +======+======+======+======+======+ + | | 1 | 32 | 256 | 768 | + +------+------+------+------+------+ + + With each host/network, a counter of unrestricted responses is associated; + if the counter would exceed its capacity, it is not incremented and the response is restricted. + Counters use exponential decay for lowering their values, + i.e. they are lowered by a constant fraction of their value each millisecond. + The specified rate limit is reached, when the number of queries is the same every millisecond; + sending many queries once a second or even a larger timespan leads to a more strict limiting. + + +.. option:: rate-limiting/instant-limit: <int> + + :default: 50 + + Maximal allowed number of queries at a single point in time from a single IPv6 or IPv4 address. + To be set according to the expected normal behaviour of clients; likely not needed to be alterered. + The limits for prefixes use the same multipliers as for :option:`rate-limit <rate-limiting/rate-limit: <int>`. + + This limit is relevant for bursts of queries, + e.g. when a recently inactive host/network suddenly starts sending many queries. + + The :option:`instant-limit <rate-limiting/instant-limit: <int>` + sets the actual capacity of each counter of responses, + and together with the :option:`rate-limit <rate-limiting/rate-limit: <int>` + they set the fraction by which the counter is periodically lowered. + The :option:`instant-limit <rate-limiting/instant-limit: <int>` may be at least + :option:`rate-limit <rate-limiting/rate-limit: <int>` **/ 1000**, at which point the + counters are zeroed each millisecond. + + +.. option:: rate-limiting/slip: <int> + + :default: 2 + + Number of restricted responses out of which one is sent as truncated, the others are dropped. + + As attacks using DNS/UDP are usually based on a forged source address, + an attacker could deny services to the victim's netblock if all + responses would be completely blocked. The idea behind SLIP mechanism + is to send each N\ :sup:`th` response as truncated, thus allowing client to + reconnect via TCP for at least some degree of service. It is worth + noting, that some responses can't be truncated (e.g. SERVFAIL). + + - Setting the value to **0** will cause all rate-limited responses to + be dropped. The outbound bandwidth and packet rate will be strictly capped + by the :option:`rate-limit <rate-limiting/rate-limit: <int>` option. + All legitimate requestors affected + by the limit will face denial of service and will observe excessive timeouts. + Therefore this setting is not recommended. + + - Setting the value to **1** will cause all rate-limited responses to + be sent as truncated. The amplification factor of the attack will be reduced, + but the outbound data bandwidth won't be lower than the incoming bandwidth. + Also the outbound packet rate will be the same as without rate limiting. + + - Setting the value to **2** will cause approximately half of the rate-limited responses + to be dropped, and the other half will be sent as truncated. With this + configuration, both outbound bandwidth and packet rate will be lower than the + inbound. On the other hand, the dropped responses enlarge the time window + for possible cache poisoning attack on the resolver. + + - Setting the value to anything **larger than 2** will keep on decreasing + the outgoing rate-limited bandwidth, packet rate, and chances to notify + legitimate requestors to reconnect using TCP. These attributes are inversely + proportional to the configured value. Setting the value high is not advisable. + + +.. option:: rate-limiting/capacity: <int> + + :default: 524288 + + Maximal number of stored hosts/networks with their counters. + The data structure tries to store only the most frequent sources, + so it is safe to set it according to the expected maximal number of limited ones. + + Use **1.4 *** ``maximum-qps`` **/** :option:`rate-limit <rate-limiting/rate-limit: <int>`, + where ``maximum-qps`` is the number of queries which can be handled by the server per second. + There is at most ``maximum-qps`` **/** :option:`rate-limit <rate-limiting/rate-limit: <int>` limited hosts; + larger networks have higher limits, so they require only a fraction of the value (handled by the **1.4** multiplier). + The value will be rounded up to the nearest power of two. + + The memory occupied by one table structure is **8 *** :option:`capacity <rate-limiting/capacity: <int>` Bytes. + + +.. option:: rate-limiting/log-period: <time ms|s|m|h|d> + + :default: 0s + + Minimal time between two log messages, or ``0s`` to disable logging. + + If a response is limited, the address and the prefix on which it was blocked is logged + and logging is disabled for the :option:`log-period <rate-limiting/log-period: <time ms|s|m|h|d>`. + As long as limiting is needed, one source is logged each period + and sources with more blocked queries have greater probability to be chosen. + + +.. option:: rate-limiting/dry-run: true|false + + :default: false + + Perform only classification and logging but no restrictions. |