Better ratelimiting? (again)

Hi,

(ip-)ratelimiting is a nice addition, but it's currently like a big hammer, since it's basically on/off for the unbound instance.
I'd like to have some sort of possibility to exclude a part of unbound from this, be it a interface, a dedicated port(listner) or configurable IP-network range(s).
(Ref [https://www.mail-archive.com/unbound-users@unbound.net/msg05119.html](https://www.mail-archive.com/unbound-users@unbound.net/msg05119.html))

Some alternative ideas to the earlier suggested per subnet ip-ratelimit:

1) Mimic what's common in the "networking world", allowing to configure a (higher) burst limit, could be a way of allowing bursty clients to finish all lookups without getting slowed down by dropped queries. 

ip-ratelimit-burst: <max-limit>
 or perhaps 
ip-ratelimit-burst: <max-limit/seconds>  # X seconds of burstiness allowed 

2) Another approach would be to allow to configure the ip-ratelimit-factor to be exponential over time (as an alternative to the fixed 1/X behavior), slowly dropping a bigger amount of the exceeding queries over time (by for instance increasing X +1 every second.)

I personally like the per-subnet option the most, as it gives full control over ip-ratelimiting. 
But 2) seems like a low hanging fruit implementation wise, and would be very helpful compared to the current state. It could be applied to ratelimit(-for-domain etc.) too (if that would be useful?)

Re,
/P

Hi Fredrik,

Top posting, sorry.

Probably it makes also sense to make this configuration option dynamic
via unbound-control (via setoption opt: val).

Cheers,

-- Benno

Hi,

I personally like the per-subnet option the most, as it gives full control over ip-ratelimiting.

  I believe that when we need such complicated rate-limiting feature
we should use other software component built for such purpose.

  dnsdist (https://dnsdist.org) can do per-subnet query rate-limiting
like below.

When I first read the code, I noticed that each IP has its own structure (in a hashtable), with the qps.
The source is using a global to store and lookup the limit (infra_ip_ratelimit).

In my case, ip-ratelimit need some filter by network prefix, like access-control does.

access-control: 192.168.0.0/16 allow
access-control: 192.168.1.0/24 deny
access-control: 192.168.2.0/24 deny

Using the low prefix to match cases.

ip-ratelimit: [prefix] /

ip-ratelimit: 192.168.0.0/16 5/1
ip-ratelimit: 192.168.1.0/24 10/1
ip-ratelimit: 192.168.2.0/24 20/1

This way, each /32 will have limits according with the match rule.

I know there are many source to be written, such as a rbtree_t to store limits like acl_list does, configs, lookups, etc.
As well as the main need to define how the functionality will be and what resources it will have.

I can write this code, but due to my projects, I will only have time after February or March 2019.

Until then, if someone has not written the functionality, we can define with the community and see if the unbound team approves the idea, since I do not know the impact that changes like these can bring.

Hi,

1) Mimic what's common in the "networking world", allowing to configure a (higher) burst limit, could be a way of allowing bursty clients to finish all lookups without getting slowed down by dropped queries. 

I like this idea:)
I observe lot of clients, that send a lot of queries in first second of data transmission.
Perfect solution (for me;) would be : If IP send more than X queries in Y seconds, deny all queries from this IP for Z seconds

example of my usecase:

second 1: Regular Client: 80qps
second 2: Regular Client: 10qps
second 3: Regular Client: 5qps
second 4: Regular Client: 4qps
second 5: Regular Client: 3qps

second 1: Malicious Client: 50qps
second 2: Malicious Client: 50qps
second 3: Malicious Client: 50qps
second 4: Malicious Client: 50qps
second 5: Malicious Client: 50qps

ip-ratelimit 40 might be perfect for malicious client, but it impacts regular client experience.

Even measuring number of queries for two seconds ( instead of 1 ) would make huge improvement.

BR
M