Commit 89aa8ab9 authored by Petr Špaček's avatar Petr Špaček Committed by Tomas Krizek

view: clarify docs

parent e2a83e67
......@@ -5,7 +5,9 @@ Query policies
This module can block, rewrite, or alter inbound queries based on user-defined policies.
Each policy *rule* has two parts: a *filter* and an *action*. A *filter* selects which queries will be affected by the policy, and *action* which modifies queries matching the associated filter. Typically a rule is defined as follows: ``filter(action(action parameters), filter parameters)``. For example, a filter can be ``suffix`` which matches queries whose suffix part is in specified set, and one of possible actions is ``DENY``, which denies resolution. These are combined together into ``policy.suffix(policy.DENY, {todname('badguy.example.')})``. The rule is effective when it is added into rule table using ``policy.add()``, please see `Policy examples`_.
Each policy *rule* has two parts: a *filter* and an *action*. A *filter* selects which queries will be affected by the policy, and *action* which modifies queries matching the associated filter.
Typically a rule is defined as follows: ``filter(action(action parameters), filter parameters)``. For example, a filter can be ``suffix`` which matches queries whose suffix part is in specified set, and one of possible actions is ``DENY``, which denies resolution. These are combined together into ``policy.suffix(policy.DENY, {todname('badguy.example.')})``. The rule is effective when it is added into rule table using ``policy.add()``, please see `Policy examples`_.
This module is enabled by default because it implements mandatory :rfc:`6761` logic.
When no rule applies to a query, built-in rules for `special-use <https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml>`_ and `locally-served <http://www.iana.org/assignments/locally-served-dns-zones>`_ domain names are applied.
......@@ -28,9 +30,17 @@ A *filter* selects which queries will be affected by specified *action*. There a
- implements a subset of RPZ_ in zonefile format. See below for details: :any:`policy.rpz`.
* custom filter function
.. _mod-policy-actions:
Actions
^^^^^^^
An *action* is function which modifies DNS query. There are several actions available in the ``policy.`` table:
An *action* is function which modifies DNS query, and is either of type *chain* or *non-chain*. So-called *chain* actions modify the query and allow other rules to evaluate and modify the same query. *Non-chain* actions have opposite behavior, i.e. modify the query and stop rule processing.
Resolver comes with several actions available in the ``policy.`` table:
**Non-chain actions**
Following actions stop the policy matching on the query, i.e. other rules are not evaluated once rule with following actions matches:
* ``PASS`` - let the query pass through; it's useful to make exceptions before wider rules
* ``DENY`` - reply NXDOMAIN authoritatively
......@@ -43,12 +53,17 @@ An *action* is function which modifies DNS query. There are several actions avai
the parameter can be a single IP (string) or a lua list of up to four IPs.
* ``STUB(ip)`` - similar to ``FORWARD(ip)`` but *without* attempting DNSSEC validation.
Each request may be either answered from cache or simply sent to one of the IPs with proxying back the answer.
* ``MIRROR(ip)`` - mirror query to given IP and continue solving it (useful for partial snooping); it's a chain action
* ``REROUTE({{subnet,target}, ...})`` - reroute addresses in response matching given subnet to given target, e.g. ``{'192.0.2.0/24', '127.0.0.0'}`` will rewrite '192.0.2.55' to '127.0.0.55', see :ref:`renumber module <mod-renumber>` for more information.
* ``QTRACE`` - pretty-print DNS response packets into the log for the query and its sub-queries. It's useful for debugging weird DNS servers. It's a chain action.
* ``FLAGS(set, clear)`` - set and/or clear some flags for the query. There can be multiple flags to set/clear. You can just pass a single flag name (string) or a set of names. It's a chain action.
Most actions stop the policy matching on the query, but "chain actions" allow to keep trying to match other rules, until a non-chain action is triggered.
**Chain actions**
Following actions allow to keep trying to match other rules, until a non-chain action is triggered:
* ``MIRROR(ip)`` - mirror query to given IP and continue solving it (useful for partial snooping).
* ``QTRACE`` - pretty-print DNS response packets into the log for the query and its sub-queries. It's useful for debugging weird DNS servers.
* ``FLAGS(set, clear)`` - set and/or clear some flags for the query. There can be multiple flags to set/clear. You can just pass a single flag name (string) or a set of names.
Also, it is possible to write your own action (i.e. Lua function). It is possible to implement complex heuristics, e.g. to deflect `Slow drip DNS attacks <https://secure64.com/water-torture-slow-drip-dns-ddos-attack>`_ or gray-list resolution of misbehaving zones.
......
......@@ -4,31 +4,31 @@ Views and ACLs
--------------
The :ref:`policy <mod-policy>` module implements policies for global query matching, e.g. solves "how to react to certain query".
This module combines it with query source matching, e.g. "who asked the query". This allows you to create personalized blacklists,
filters and ACLs, sort of like ISC BIND views.
This module combines it with query source matching, e.g. "who asked the query". This allows you to create personalized blacklists, filters and ACLs.
There are two identification mechanisms:
* ``addr``
- identifies the client based on his subnet
* ``tsig``
- identifies the client based on a TSIG key
- identifies the client based on a TSIG key name (only for testing purposes, TSIG signature is not verified!)
You can combine this information with :ref:`policy <mod-policy>` rules.
View module allows you to combine query source information with :ref:`policy <mod-policy>` rules.
.. code-block:: lua
view:addr('10.0.0.1', policy.suffix(policy.TC, {'\7example\3com'}))
view:addr('10.0.0.1', policy.suffix(policy.TC, policy.todnames({'example.com'})))
This fill force given client subnet to TCP for names in ``example.com``.
This example will force given client to TCP for names in ``example.com`` subtree.
You can combine view selectors with RPZ_ to create personalized filters for example.
.. warning::
Beware that cache is shared by *all* requests. For example, it is safe
to refuse answer based on who asks the resolver, but trying to serve
different data to different clients may result in surprises.
Such setups are usually called **split-horizon** or similarly.
different data to different clients will result in unexpected behavior.
Setups like **split-horizon** which depend on isolated DNS caches
are explicitly not supported.
Example configuration
......@@ -37,19 +37,19 @@ Example configuration
.. code-block:: lua
-- Load modules
modules = { 'policy', 'view' }
modules = { 'view' }
-- Whitelist queries identified by TSIG key
view:tsig('\5mykey', function (req, qry) return policy.PASS end)
view:tsig('\5mykey', policy.all(policy.PASS))
-- Block local clients (ACL like)
view:addr('127.0.0.1', function (req, qry) return policy.DENY end))
view:addr('127.0.0.1', policy.all(policy.DENY))
-- Drop queries with suffix match for remote client
view:addr('10.0.0.0/8', policy.suffix(policy.DROP, {'\3xxx'}))
view:addr('10.0.0.0/8', policy.suffix(policy.DROP, policy.todnames({'xxx'})))
-- RPZ for subset of clients
view:addr('192.168.1.0/24', policy.rpz(policy.PASS, 'whitelist.rpz'))
-- Forward all queries from given subnet to proxy
view:addr('10.0.0.0/8', policy.all(policy.FORWARD('2001:DB8::1')))
-- Do not try this - it will pollute cache and surprise you!
-- view:addr('10.0.0.0/8', policy.all(policy.FORWARD('2001:DB8::1')))
-- Drop everything that hasn't matched
view:addr('0.0.0.0/0', function (req, qry) return policy.DROP end)
view:addr('0.0.0.0/0', policy.all(policy.DROP))
Rule order
......@@ -57,11 +57,9 @@ Rule order
The current implementation is best understood as three separate rule chains:
vanilla ``policy.add``, ``view:tsig`` and ``view:addr``.
For each request the rules in these chains get tried one by one until a "non-chain" action gets executed.
It's possible to configure ``policy.add`` rules to execute after ``view:*`` rules,
but by default ``policy`` module acts before ``view`` module due to ``policy`` being loaded by default.
For each request the rules in these chains get tried one by one until a :ref:`non-chain policy action <mod-policy-actions>` gets executed.
If you want to intermingle universal rules with ``view:addr``, you may simply wrap the universal rules:
By default :ref:`policy module <mod-policy>` acts before ``view`` module due to ``policy`` being loaded by default. If you want to intermingle universal rules with ``view:addr``, you may simply wrap the universal policy rules in view closure like this:
.. code-block:: lua
......
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