]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
policy: add explanatory TXT record to zones blocked by default
authorPetr Špaček <petr.spacek@nic.cz>
Thu, 25 Jan 2018 11:26:50 +0000 (12:26 +0100)
committerPetr Špaček <petr.spacek@nic.cz>
Thu, 25 Jan 2018 16:35:39 +0000 (17:35 +0100)
modules/policy/README.rst
modules/policy/policy.lua

index 499d15f15623ae948ec8bfc48edd9a5a32e0e8db..934604ee441e3bc05ec7f0d277dbb9837f1af4bf 100644 (file)
@@ -26,6 +26,7 @@ There are several actions available in the ``policy.`` table:
 
 * ``PASS`` - let the query pass through; it's useful to make exceptions before wider rules
 * ``DENY`` - reply NXDOMAIN authoritatively
+* ``DENY_MSG(msg)`` - reply NXDOMAIN authoritatively and add explanatory message to additional section
 * ``DROP`` - terminate query resolution and return SERVFAIL to the requestor
 * ``TC`` - set TC=1 if the request came through UDP, forcing client to retry with TCP
 * ``FORWARD(ip)`` - resolve a query via forwarding to an IP while validating and caching locally;
index cd32181d236828044d800ce9257ce4c241463b2b..552731ed0ffc8404ff361ec3a2ce7409740d36e7 100644 (file)
@@ -464,15 +464,28 @@ function policy.rpz(action, path)
        end
 end
 
-function policy.DENY(_, req)
-       -- Write authority information
-       local answer = req.answer
-       ffi.C.kr_pkt_make_auth_header(answer)
-       answer:rcode(kres.rcode.NXDOMAIN)
-       answer:begin(kres.section.AUTHORITY)
-       mkauth_soa(answer, '\7blocked\0')
-       return kres.DONE
+function policy.DENY_MSG(msg)
+       if msg and (type(msg) ~= 'string' or #msg >= 255) then
+               error('DENY_MSG: optional msg must be string shorter than 256 characters')
+        end
+
+       return function (_, req)
+               -- Write authority information
+               local answer = req.answer
+               ffi.C.kr_pkt_make_auth_header(answer)
+               answer:rcode(kres.rcode.NXDOMAIN)
+               answer:begin(kres.section.AUTHORITY)
+               mkauth_soa(answer, '\7blocked\0')
+               if msg then
+                       answer:begin(kres.section.ADDITIONAL)
+                       answer:put('\11explanation\7invalid', 900, answer:qclass(), kres.type.TXT,
+                                  string.char(#msg) .. msg)
+
+               end
+               return kres.DONE
+       end
 end
+policy.DENY = policy.DENY_MSG() -- compatibility with < 2.0
 
 function policy.DROP(_, _)
        return kres.FAIL
@@ -603,7 +616,7 @@ local private_zones = {
        '100.51.198.in-addr.arpa.',
        '113.0.203.in-addr.arpa.',
        '255.255.255.255.in-addr.arpa.',
-       -- RFC7796
+       -- RFC7793
        '64.100.in-addr.arpa.',
        '65.100.in-addr.arpa.',
        '66.100.in-addr.arpa.',
@@ -686,14 +699,22 @@ policy.rules = {}
 policy.postrules = {}
 policy.special_names = {
        {
-               cb=policy.suffix_common(policy.DENY, private_zones, todname('arpa.')),
+               cb=policy.suffix_common(policy.DENY_MSG(
+                       'Blocking is mandated by standards, see references on '
+                       .. 'https://www.iana.org/assignments/'
+                       .. 'locally-served-dns-zones/locally-served-dns-zones.xhtml'),
+                       private_zones, todname('arpa.')),
                count=0
        },
        {
-               cb=policy.suffix(policy.DENY, {
-                       todname('test.'),
-                       todname('invalid.'),
-                       todname('onion.'), -- RFC7686, 2.4
+               cb=policy.suffix(policy.DENY_MSG(
+                       'Blocking is mandated by standards, see references on '
+                       .. 'https://www.iana.org/assignments/'
+                       .. 'special-use-domain-names/special-use-domain-names.xhtml'),
+                       {
+                               todname('test.'),
+                               todname('onion.'),
+                               todname('invalid.'),
                        }),
                count=0
        },