WIP: modules/policy: add policy.slice function

parent 81d78f8f
......@@ -4,6 +4,7 @@ Knot Resolver 4.x.y (2019-0m-dd)
Improvements
------------
- DNS-over-HTTPS: answers include `access-control-allow-origin: *` (!823)
- TODO
Bugfixes
--------
......
......@@ -28,6 +28,9 @@ A *filter* selects which queries will be affected by specified *action*. There a
* :any:`policy.suffix_common`
* ``rpz(default_action, path)``
- implements a subset of RPZ_ in zonefile format. See below for details: :any:`policy.rpz`.
* ``slice(action, index, count)`` - splits the entire domain space into
``count`` slices and applies action if the domain belongs to the ``index``
slice. For details, see :any:`policy.slice`.
* custom filter function
.. _mod-policy-actions:
......@@ -266,6 +269,40 @@ Most properties (actions, filters) are described above.
"NSDNAME", "no"
"NS-IP", "no"
.. function:: policy.slice(action, index, count)
:param action: action if the QNAME belongs to slice
:param index: selected slice - ``1`` to ``count``
:param count: total number of slices
This function splits the entire domain space into ``count`` slices.
``action`` is applied if the QNAME belongs to the ``index`` slice.
For a given ``count``, the assignment of domains to slices is always
**stable** - domain will never change which slice it belongs to. In this
case, *domain* means a registrable domain, determined with the use of
`Public Suffix List`_.
The following example demonstrates a distribution among 3 slices:
.. code-block::
slice 1/3:
example.com
a.example.com
b.example.com
x.b.example.com
example3.com
slice 2/3:
example2.co.uk
slice 3/3:
example.co.uk
a.example.co.uk
This function requires `lua-psl` and `libpsl`.
.. function:: policy.todnames({name, ...})
:param: names table of domain names in textual format
......@@ -291,3 +328,4 @@ Most properties (actions, filters) are described above.
.. _`DNS Privacy Project`: https://dnsprivacy.org/
.. _`IETF draft dprive-dtls-and-tls-profiles`: https://tools.ietf.org/html/draft-ietf-dprive-dtls-and-tls-profiles
.. _SNI: https://en.wikipedia.org/wiki/Server_Name_Indication
.. _`Public Suffix List`: https://publicsuffix.org
......@@ -444,6 +444,52 @@ function policy.rpz(action, path, watch)
end
end
-- Get a stable subset of domains in an "index" slice out of "count" total slices
function policy.slice(action, index, count)
if index < 1 or index > count then
error('[poli] invalid slice index "' .. index .. '" (valid range: 1 to' ..
count .. ')')
end
local has_psl, psl_lib = pcall(require, 'psl')
if not has_psl then
error('[poli] lua-psl is required for policy.slice')
end
-- load psl
local has_latest, psl = pcall(psl_lib.latest)
if not has_latest then -- compatiblity with lua-psl < 0.15
psl = psl_lib.builtin()
end
return function(_, query)
local domain = kres.dname2str(query:name())
if domain:len() > 1 then --remove trailing dot
domain = domain:sub(0, -2)
end
-- do psl lookup for registrable domain
local reg_domain = psl:registrable_domain(domain)
if reg_domain == nil then -- fallback to unreg. domain
reg_domain = psl:unregistrable_domain(domain)
if reg_domain == nil then
return action
end
end
-- simple algorithm that maps string -> int in a stable way
local hash = 0
for i = 1, #reg_domain do
hash = hash + reg_domain:byte(i)
end
-- assign domain to a slice
if hash % count == (index - 1) then
return action
end
return nil
end
end
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')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment