2023-09-23
Some questions about Unbound's domain-based rate limits (as of fall 2023)
Unbound is a common resolving DNS server; we use it ourselves on our local recursive DNS resolvers. For a long time, Unbound has had the ability to set ratelimits, as covered in the unbound.conf manual page. These ratelimits have historically been a little complicated to understand (for example), and the situation is still not completely clear in the current (September 2023) documentation.
Unbound can have both a global ratelimit, set with 'ratelimit
',
and one or more different rate limits for different areas of the
DNS. These days, there are two directives for ratelimits of specific
DNS areas, which I will quote more or less directly from the
documentation:
ratelimit-for-domain
- Override the global ratelimit for an exact match domain name with the listed number. You can give this for any number of names. For example, for a top-level-domain you may want to have a higher limit than other names. A value of 0 will disable ratelimiting for that domain.
ratelimit-below-domain
- Override the global ratelimit for a domain name that ends in this name. You can give this multiple times, it then describes different settings in different parts of the namespace. The closest matching suffix is used to determine the qps limit. The rate for the exact matching domain name is not changed, use ratelimit-for-domain to set that, you might want to use different settings for a top-level-domain and subdomains. A value of 0 will disable ratelimiting for domain names that end in this name.
There is also a sample configuration with commented examples that may be worth reading.
How 'ratelimit-below-domain
' works seems obvious from the text
of the documentation (which doesn't mean my impression is correct).
It presumably works by textual matching against the DNS name you
used in your query, where the query is 'below' this if its name
ends in '.<domain>'. As the documentation says, direct queries for
'<domain>' are not 'below' and aren't covered. However, it is
possible that this is incorrect and it's actually defined in terms
of DNS zones, where it applies to queries in DNS zones that are
below the DNS zone of the domain you list.
This leaves me with the question of what 'ratelimit-for-domain
'
really applies to, because there are two answers. The first is that
it is a purely textual match; if you have a ratelimit-for-domain
on example.com, only DNS queries where the query name is exactly
'example.com' match, which is generally not going to be too many
of them. The second answer, which is more natural in a DNS sense,
is that the ratelimit applies to everything in the 'example.com'
DNS zone, but not anything that requires following a NS record out
of it. Often, although not always, 'DNS zone' is what DNS people
mean when they say 'domain' in a DNS context.
(Reading my 2016 entry on the old state of ratelimit-for-domain suggests that at that point it was based on the zone, since it was logging messages about ratelimiting a query for 'www.utoronto.ca' when the ratelimit-for-domain was 'utoronto.ca'. That might have been changed when ratelimit-below-domain was added.)
Unfortunately I don't know of any good way to find out the answer (reading the Unbound source doesn't quality). I guess I could set up a test Unbound with extremely low limits for some test names and see what gets logged.
I suspect that this mostly doesn't matter in practice, and certainly it doesn't for us. In most situations you probably want to use either ratelimit-below-domain (which is probably what you mean) by itself, or set both to the same value (including setting no limit, which is explicitly supported these days but didn't used to be):
ratelimit-for-domain: utoronto.ca 0 ratelimit-below-domain: utoronto.ca 0
If 'ratelimit-for-domain' works by textually matching the DNS name in the query, I think you could also use it to mostly block DNS resolution for some specific name that clients are pounding on repeatedly:
ratelimit-for-domain: sync-debug.dev.example.org 1
If it works by DNS zone, I'm not sure this is possible unless the name you want to stop flooding you with is in its own DNS zone.