]> granicus.if.org Git - pdns/commitdiff
hook up TCAction() for use in addAction(). Add global MaxQPSLimit(), not just per...
authorbert hubert <bert.hubert@netherlabs.nl>
Fri, 4 Sep 2015 13:45:57 +0000 (15:45 +0200)
committerbert hubert <bert.hubert@netherlabs.nl>
Fri, 4 Sep 2015 13:45:57 +0000 (15:45 +0200)
pdns/README-dnsdist.md
pdns/dnsdist-lua.cc
pdns/dnsrulactions.hh

index efc11fdcade4942e617f13dd4f418fd3739dd8cd..cd4b667eeb4a5cd63767130aafcf1ddbea9a5390 100644 (file)
@@ -34,6 +34,7 @@ make
 
 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
@@ -41,7 +42,9 @@ 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.
@@ -195,6 +198,8 @@ Rules have selectors and actions. Current selectors are:
  * Source address
  * Query type
  * Query domain
+ * QPS Limit total
+ * QPS Limit per IP address or subnet
 
 Current actions are:
  * Drop
@@ -203,6 +208,7 @@ Current actions are:
  * 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
 ----------
@@ -228,6 +234,42 @@ servers that lack this feature.
 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
index 85f911132fe61a669e2b658d4acd1fcd21bc1690..be5d8496c3e41e5d14b95b1556c73cba85f135e1 100644 (file)
@@ -354,12 +354,24 @@ vector<std::function<void(void)>> setupLua(bool client, const std::string& confi
       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);
index 2eb64e31c94cdda9b39dd794141e4db75f8d74d1..6e16825cf23623d1d70827bcec48ec01d7d933d5 100644 (file)
@@ -32,6 +32,34 @@ private:
 
 };
 
+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
 {