]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Handle policy (if needed) after postresolve and document the hooks better.
authorOtto <otto.moerbeek@open-xchange.com>
Wed, 17 Feb 2021 07:45:50 +0000 (08:45 +0100)
committerOtto <otto.moerbeek@open-xchange.com>
Mon, 22 Feb 2021 10:37:08 +0000 (11:37 +0100)
Fixes #10080

pdns/dns.hh
pdns/lua-base4.cc
pdns/pdns_recursor.cc
pdns/recursordist/docs/lua-scripting/hooks.rst

index 2201f7392626aaac8c9ad3c197a8c1e1fd66a9c8..608d61ccd7dd63beb86eb6295e19289693678f8f 100644 (file)
@@ -76,9 +76,6 @@ public:
   static std::string to_s(uint8_t opcode);
 };
 
-// enum for policy decisions, used by both auth and recursor. Not all values supported everywhere.
-namespace PolicyDecision { enum returnTypes { PASS=-1, DROP=-2, TRUNCATE=-3 }; };
-
 //! This class represents a resource record
 class DNSResourceRecord
 {
index d36fc1e8c08cba30f2c73fec6388fabbeea1a4bf..c67e6d8a102c647707f28fba27f54a4e09a71a48 100644 (file)
@@ -199,9 +199,6 @@ void BaseLua4::prepareContext() {
   d_lw->writeFunction("pdnsrandom", [](boost::optional<uint32_t> maximum) { return dns_random(maximum.get_value_or(0xffffffff)); });
 
   // certain constants
-  d_pd.push_back({"PASS", (int)PolicyDecision::PASS});
-  d_pd.push_back({"DROP", (int)PolicyDecision::DROP});
-  d_pd.push_back({"TRUNCATE", (int)PolicyDecision::TRUNCATE});
 
   vector<pair<string, int> > rcodes = {{"NOERROR",  RCode::NoError  },
                                        {"FORMERR",  RCode::FormErr  },
index 595892a68047111b5fd746e3aec2c494d6bed425..dcd7223bdcb5cd1d6e3fec3264074f256166c34f 100644 (file)
@@ -1806,6 +1806,11 @@ static void startDoResolve(void *p)
 
        if (t_pdl && t_pdl->postresolve(dq, res)) {
           shouldNotValidate = true;
+          auto policyResult = handlePolicyHit(appliedPolicy, dc, sr, res, ret, pw);
+          // haveAnswer case redundant
+          if (policyResult == PolicyResult::Drop) {
+            return;
+          }
         }
       }
     }
index 1d7d679a7ad04688c8d17cef3e5b4be0ac43064c..62ef797d98b600c39ebd682628a8a554c67b5ec1 100644 (file)
@@ -24,8 +24,13 @@ It also means that to print such names, the ``:toString`` method must be used (o
 Once a script is loaded, PowerDNS looks for the interception functions in the loaded script.
 All of these functions are optional.
 
-If a function returns true, it will indicate that it handled a query.
-If it returns false, the Recursor will continue processing unchanged (with one minor exception).
+If ``ipfilter`` returns ``true``, the query is dropped.
+If ``preresolve`` returns ``true``, it will indicate it handled a query, and the recursor will send to result as constructed in the functions to the client.
+If it returns ``false``, the Recursor will continue processing.
+For the other functions, the return value will indicate if DNSSEC validation should take place.
+For modified results, the functions should return ``true`` to avoid failing DNSSEC validations.
+At specific points the Recursor will check if policy handling should take place.
+These points are immediatly after ``preresolve``, after resolving and after ``postresolve``.
 
 Interception Functions
 ----------------------
@@ -115,7 +120,7 @@ Interception Functions
     It accepts a single, scalable parameter which can be accessed using FFI accessors.
     Like the non-FFI version, it has the ability to set a tag for the packetcache, policy tags, a routing tag, the :attr:`DNSQuestion.requestorId` and :attr:`DNSQuestion.deviceId`values and to fill the :attr:`DNSQuestion.data` table. It also offers ways to mark the answer as variable so it's not inserted into the packetcache, to set a cap on the TTL of the returned records, and to generate a response by adding records and setting the RCode. It can also instruct the recursor to do a proper resolution in order to follow any `CNAME` records added in this step.
 
-.. function:: prerpz(dq)
+.. function:: prerpz(dq) -> bool
 
   This hook is called before any filtering policy have been applied,  making it possible to completely disable filtering by setting  :attr:`dq.wantsRPZ <DNSQuestion.wantsRPZ>` to false.
   Using the :meth:`dq:discardPolicy() <DNSQuestion:discardPolicy>` function, it is also possible to selectively disable one or more filtering policy, for example RPZ zones, based on the content of the ``dq`` object.
@@ -134,44 +139,44 @@ Interception Functions
 
   :param DNSQuestion dq: The DNS question to handle
 
-.. function:: preresolve(dq)
+.. function:: preresolve(dq) -> bool
 
   This function is called before any DNS resolution is attempted, and if this function indicates it, it can supply a direct answer to the DNS query, overriding the internet.
   This is useful to combat botnets, or to disable domains unacceptable to an organization for whatever reason.
 
   :param DNSQuestion dq: The DNS question to handle
 
-.. function:: postresolve(dq)
+.. function:: postresolve(dq) -> bool
 
   is called right before returning a response to a client (and, unless :attr:`dq.variable <DNSQuestion.variable>` is set, to the packet cache too).
   It allows inspection and modification of almost any detail in the return packet.
 
   :param DNSQuestion dq: The DNS question to handle
 
-.. function:: nxdomain(dq)
+.. function:: nxdomain(dq) -> bool
 
   is called after the DNS resolution process has run its course, but ended in an 'NXDOMAIN' situation, indicating that the domain does not exist.
   Works entirely like :func:`postresolve`, but saves a trip through Lua for answers which are not NXDOMAIN.
 
   :param DNSQuestion dq: The DNS question to handle
 
-.. function:: nodata(dq)
+.. function:: nodata(dq) -> bool
 
   is just like :func:`nxdomain`, except it gets called when a domain exists, but the requested type does not.
   This is where one would implement :doc:`DNS64 <../dns64>`.
 
   :param DNSQuestion dq: The DNS question to handle
 
-.. function:: preoutquery(dq)
+.. function:: preoutquery(dq) -> bool
 
   This hook is not called in response to a client packet, but fires when the Recursor wants to talk to an authoritative server.
-  When this hook sets the special result code -3, the whole DNS client query causing this outquery gets dropped.
+  When this hook sets the special result code -3, the whole DNS client query causing this outquery gets a `ServFail`.
 
   However, this function can also return records like :func:`preresolve`.
 
   :param DNSQuestion dq: The DNS question to handle
 
-.. function:: policyEventFilter(event)
+.. function:: policyEventFilter(event) -> bool
 
     .. versionadded:: 4.4.0
 
@@ -210,7 +215,7 @@ Interception Functions
 
 Semantics
 ^^^^^^^^^
-The functions must return ``true`` if they have taken over the query and wish that the nameserver should not proceed with its regular query-processing.
+The `ipfilter` and `preresolve` must return ``true`` if they have taken over the query and wish that the nameserver should not proceed with its regular query-processing.
 When a function returns ``false``, the nameserver will process the query normally until a new function is called.
 
 If a function has taken over a request, it should set an rcode (usually 0), and specify a table with records to be put in the answer section of a packet.
@@ -238,9 +243,24 @@ A minimal sample script:
 **Warning**: Please do NOT use the above sample script in production!
 Responsible NXDomain redirection requires more attention to detail.
 
-Useful 'rcodes' include 0 for "no error", ``pdns.NXDOMAIN`` for "NXDOMAIN", ``pdns.DROP`` to drop the question from further processing.
+Useful 'rcodes' include 0 for "no error" and ``pdns.NXDOMAIN`` for "NXDOMAIN", ``pdns.DROP`` to drop the question from further processing.
 Such a drop is accounted in the 'policy-drops' metric.
 
+Starting with recursor 4.4.0, the method to drop a request is to set the ``dq.appliedPolicy.policyKind`` to the value ``pdns.policykinds.Drop``.
+
+.. code-block:: Lua
+
+    function nxdomain(dq)
+        print("Intercepting and dropping NXDOMAIN for: ",dq.qname:toString())
+        if dq.qtype == pdns.A
+        then
+            dq.appliedPolicy.policyKind = pdns.policykinds.Drop
+        end
+        return false
+    end
+
+**Note**: to drop a query from ``preresolve``, set ``policyKind`` and return false, to indicate the Recursor should process the Drop action.
+
 DNS64
 -----