Packaged
--------
+We build packages for dnsdist on our [repositories](https://repo.powerdns.com). In addition
dnsdist has been packaged for FreeBSD and can be found on https://freshports.org/dns/dnsdist
Examples
The absolute minimum configuration:
+````
# dnsdist 2001:4860:4860::8888 8.8.8.8
+```
This will listen on 0.0.0.0:53 and forward queries to the two listed IP
addresses, with a sensible load balancing policy.
* Source address
* Query type
* Query domain
+ * QPS Limit total
+ * QPS Limit per IP address or subnet
Current actions are:
* Drop
* Force a ServFail, NotImp or Refused answer
* Send out a crafted response (NXDOMAIN or "real" data)
* Delay a response by n milliseconds
+ * Modify query to remove RD bit
More power
----------
Note that calling `addAnyTCRule()` achieves the same thing, without
involving Lua.
+Rules for traffic exceeding QPS limits
+--------------------------------------
+Traffic that exceeds a QPS limit, in total or per IP (subnet) can be matched by a rule.
+
+For example:
+
+```
+addDelay(MaxQPSIPRule(5, 32, 48), 100)
+```
+
+This measures traffic per IPv4 address and per /48 of IPv6, and if traffic for such
+an address (range) exceeds 5 qps, it gets delayed by 100ms.
+
+As another example:
+
+```
+addAction(MaxQPSIPRule(5), NoRecurseAction())
+```
+
+This strips the Recursion Desired (RD) bit from any traffic per IPv4 or IPv6 /64
+that exceeds 5 qps. This means any those traffic bins is allowed to make a recursor do 'work'
+for only 5 qps.
+
+If this is not enough, try:
+
+```
+addAction(MaxQPSIPRule(5), DropAction())
+-- or
+addAction(MaxQPSIPRule(5), TCAction())
+```
+
+This will respectively drop traffic exceeding that 5 QPS limit per IP or range, or return it with TC=1, forcing
+clients to fall back to TCP/IP.
+
+To turn this per IP or range limit into a global limt, use MaxQPSRule(5000) instead of MaxQPSIPRule.
+
Lua actions in rules
--------------------
While we can pass every packet through the `blockFilter()` functions, it is also
return std::shared_ptr<DNSAction>(new DropAction);
});
+ g_lua.writeFunction("TCAction", []() {
+ return std::shared_ptr<DNSAction>(new TCAction);
+ });
+
g_lua.writeFunction("MaxQPSIPRule", [](unsigned int qps, boost::optional<int> ipv4trunc, boost::optional<int> ipv6trunc) {
return std::shared_ptr<DNSRule>(new MaxQPSIPRule(qps, ipv4trunc.get_value_or(32), ipv6trunc.get_value_or(64)));
});
+ g_lua.writeFunction("MaxQPSRule", [](unsigned int qps, boost::optional<int> burst) {
+ if(!burst)
+ return std::shared_ptr<DNSRule>(new MaxQPSRule(qps));
+ else
+ return std::shared_ptr<DNSRule>(new MaxQPSRule(qps, *burst));
+ });
+
+
g_lua.writeFunction("addAction", [](luadnsrule_t var, std::shared_ptr<DNSAction> ea)
{
auto rule=makeRule(var);
};
+class MaxQPSRule : public DNSRule
+{
+public:
+ MaxQPSRule(unsigned int qps)
+ : d_qps(qps, qps)
+ {}
+
+ MaxQPSRule(unsigned int qps, unsigned int burst)
+ : d_qps(qps, burst)
+ {}
+
+
+ bool matches(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len) const override
+ {
+ return d_qps.check();
+ }
+
+ string toString() const override
+ {
+ return "Max " + std::to_string(d_qps.getRate()) + " qps";
+ }
+
+
+private:
+ mutable QPSLimiter d_qps;
+};
+
+
class NetmaskGroupRule : public DNSRule
{