> bd = getBind(0)
> bd:attachFilter(bpf)
-:program:`dnsdist` also supports adding dynamic, expiring blocks to a BPF filter::
+:program:`dnsdist` also supports adding dynamic, expiring blocks to a BPF filter:
+.. code-block:: lua
+
+ bpf = newBPFFilter({ipv4MaxItems=1024, ipv6MaxItems=1024, qnamesMaxItems=1024})
+ setDefaultBPFFilter(bpf)
+ local dbr = dynBlockRulesGroup()
+ dbr:setQueryRate(20, 10, "Exceeded query rate", 60)
+
+ function maintenance()
+ dbr:apply()
+ end
+
+This will dynamically block all hosts that exceeded 20 queries/s as measured over the past 10 seconds, and the dynamic block will last for 60 seconds.
+
+Since 1.6.0, the default BPF filter set via :func:`setDefaultBPFFilter` will automatically get used when a "drop" dynamic block is inserted via a :ref:`DynBlockRulesGroup`, which provides a better way to combine dynamic blocks with eBPF filtering.
+Before that, it was possible to use the :func:`addBPFFilterDynBlocks` method instead:
+
+.. code-block:: lua
+
+ -- this is a legacy method, please see above for DNSdist >= 1.6.0
bpf = newBPFFilter({ipv4MaxItems=1024, ipv6MaxItems=1024, qnamesMaxItems=1024})
setDefaultBPFFilter(bpf)
dbpf = newDynBPFFilter(bpf)
dbpf:purgeExpired()
end
-This will dynamically block all hosts that exceeded 20 queries/s as measured over the past 10 seconds, and the dynamic block will last for 60 seconds.
-
The dynamic eBPF blocks and the number of queries they blocked can be seen in the web interface and retrieved from the API. Note however that eBPF dynamic objects need to be registered before they appear in the web interface or the API, using the :func:`registerDynBPFFilter` function::
registerDynBPFFilter(dbpf)
They can be unregistered at a later point using the :func:`unregisterDynBPFFilter` function.
-Since 1.6.0, the default BPF filter set via :func:`setDefaultBPFFilter` will automatically get used when a "drop" dynamic block is inserted via a :ref:`DynBlockRulesGroup`, which provides a better way to combine dynamic blocks with eBPF filtering.
-
Requirements
------------
It will get called every second, and from this function you can set rules to block traffic based on statistics.
More exactly, the thread handling the :func:`maintenance` function will sleep for one second between each invocation, so if the function takes several seconds to complete it will not be invoked exactly every second.
-As an example::
+As an example:
+
+.. code-block:: lua
+
+ local dbr = dynBlockRulesGroup()
+ dbr:setQueryRate(20, 10, "Exceeded query rate", 60)
function maintenance()
- addDynBlocks(exceedQRate(20, 10), "Exceeded query rate", 60)
+ dbr:apply()
end
This will dynamically block all hosts that exceeded 20 queries/s as measured over the past 10 seconds, and the dynamic block will last for 60 seconds.
+:ref:`DynBlockRulesGroup` is a very efficient way of processing dynamic blocks that was introduced in 1.3.0. Before that, it was possible to use :meth:`addDynBlocks` instead:
+
+.. code-block:: lua
+
+ -- this is a legacy method, please see above for DNSdist >= 1.3.0
+ function maintenance()
+ addDynBlocks(exceedQRate(20, 10), "Exceeded query rate", 60)
+ end
+
Dynamic blocks in force are displayed with :func:`showDynBlocks` and can be cleared with :func:`clearDynBlocks`.
They return a table whose key is a :class:`ComboAddress` object, representing the client's source address, and whose value is an integer representing the number of queries matching the corresponding condition (for example the qtype for :func:`exceedQTypeRate`, rcode for :func:`exceedServFails`).
designed to make the processing of multiple rate-limiting rules faster by walking the query and response buffers only once
for each invocation, instead of once per existing `exceed*()` invocation.
-For example, instead of having something like:
-
-.. code-block:: lua
-
- function maintenance()
- addDynBlocks(exceedQRate(30, 10), "Exceeded query rate", 60)
- addDynBlocks(exceedNXDOMAINs(20, 10), "Exceeded NXD rate", 60)
- addDynBlocks(exceedServFails(20, 10), "Exceeded ServFail rate", 60)
- addDynBlocks(exceedQTypeRate(DNSQType.ANY, 5, 10), "Exceeded ANY rate", 60)
- addDynBlocks(exceedRespByterate(1000000, 10), "Exceeded resp BW rate", 60)
- end
-
The new syntax would be:
.. code-block:: lua
dbr:apply()
end
+Before 1.3.0 the legacy syntax was:
+
+.. code-block:: lua
+
+ function maintenance()
+ -- this example is using legacy methods, please see above for DNSdist >= 1.3.0
+ addDynBlocks(exceedQRate(30, 10), "Exceeded query rate", 60)
+ addDynBlocks(exceedNXDOMAINs(20, 10), "Exceeded NXD rate", 60)
+ addDynBlocks(exceedServFails(20, 10), "Exceeded ServFail rate", 60)
+ addDynBlocks(exceedQTypeRate(DNSQType.ANY, 5, 10), "Exceeded ANY rate", 60)
+ addDynBlocks(exceedRespByterate(1000000, 10), "Exceeded resp BW rate", 60)
+ end
+
+
The old syntax would walk the query buffer 2 times and the response one 3 times, while the new syntax does it only once for each.
It also reuse the same internal table to keep track of the source IPs, reducing the CPU usage.