diff options
Diffstat (limited to '')
-rw-r--r-- | modules/daf/README.rst | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/modules/daf/README.rst b/modules/daf/README.rst new file mode 100644 index 0000000..a5e025e --- /dev/null +++ b/modules/daf/README.rst @@ -0,0 +1,146 @@ +.. SPDX-License-Identifier: GPL-3.0-or-later + +.. _mod-daf: + +DNS Application Firewall +======================== + +This module is a high-level interface for other powerful filtering modules and DNS views. It provides an easy interface to apply and monitor DNS filtering rules and a persistent memory for them. It also provides a restful service interface and an HTTP interface. + +Example configuration +--------------------- + +Firewall rules are declarative and consist of filters and actions. Filters have ``field operator operand`` notation (e.g. ``qname = example.com``), and may be chained using AND/OR keywords. Actions may or may not have parameters after the action name. + +.. code-block:: lua + + -- Let's write some daft rules! + modules = { 'daf' } + + -- Block all queries with QNAME = example.com + daf.add('qname = example.com deny') + + -- Filters can be combined using AND/OR... + -- Block all queries with QNAME match regex and coming from given subnet + daf.add('qname ~ %w+.example.com AND src = 192.0.2.0/24 deny') + + -- We also can reroute addresses in response to alternate target + -- This reroutes 192.0.2.1 to localhost + daf.add('src = 127.0.0.0/8 reroute 192.0.2.1-127.0.0.1') + + -- Subnets work too, this reroutes a whole subnet + -- e.g. 192.0.2.55 to 127.0.0.55 + daf.add('src = 127.0.0.0/8 reroute 192.0.2.0/24-127.0.0.0') + + -- This rewrites all A answers for 'example.com' from + -- whatever the original address was to 127.0.0.2 + daf.add('src = 127.0.0.0/8 rewrite example.com A 127.0.0.2') + + -- Mirror queries matching given name to DNS logger + daf.add('qname ~ %w+.example.com mirror 127.0.0.2') + daf.add('qname ~ example-%d.com mirror 127.0.0.3@5353') + + -- Forward queries from subnet + daf.add('src = 127.0.0.1/8 forward 127.0.0.1@5353') + -- Forward to multiple targets + daf.add('src = 127.0.0.1/8 forward 127.0.0.1@5353,127.0.0.2@5353') + + -- Truncate queries based on destination IPs + daf.add('dst = 192.0.2.51 truncate') + + -- Disable a rule + daf.disable(2) + -- Enable a rule + daf.enable(2) + -- Delete a rule + daf.del(2) + + -- Delete all rules and start from scratch + daf.clear() + +.. warning:: Only the first matching rule's action is executed. Defining + additional actions for the same matching rule, e.g. ``src = 127.0.0.1/8``, + will have no effect. + +If you're not sure what firewall rules are in effect, see ``daf.rules``: + +.. code-block:: text + + -- Show active rules + > daf.rules + [1] => { + [rule] => { + [count] => 42 + [id] => 1 + [cb] => function: 0x1a3eda38 + } + [info] => qname = example.com AND src = 127.0.0.1/8 deny + [policy] => function: 0x1a3eda38 + } + [2] => { + [rule] => { + [suspended] => true + [count] => 123522 + [id] => 2 + [cb] => function: 0x1a3ede88 + } + [info] => qname ~ %w+.facebook.com AND src = 127.0.0.1/8 deny... + [policy] => function: 0x1a3ede88 + } + +Web interface +------------- + +If you have :ref:`HTTP/2 <mod-http>` loaded, the firewall automatically loads as a snippet. +You can create, track, suspend and remove firewall rules from the web interface. +If you load both modules, you have to load `daf` after `http`. + +RESTful interface +----------------- + +The module also exports a RESTful API for operations over rule chains. + + +.. csv-table:: + :header: "URL", "HTTP Verb", "Action" + + "/daf", "GET", "Return JSON list of active rules." + "/daf", "POST", "Insert new rule, rule string is expected in body. Returns rule information in JSON." + "/daf/<id>", "GET", "Retrieve a rule matching given ID." + "/daf/<id>", "DELETE", "Delete a rule matching given ID." + "/daf/<id>/<prop>/<val>", "PATCH", "Modify given rule, for example /daf/3/active/false suspends rule 3." + +This interface is used by the web interface for all operations, but you can also use it directly +for testing. + +.. code-block:: bash + + # Get current rule set + $ curl -s -X GET http://localhost:8453/daf | jq . + {} + + # Create new rule + $ curl -s -X POST -d "src = 127.0.0.1 pass" http://localhost:8453/daf | jq . + { + "count": 0, + "active": true, + "info": "src = 127.0.0.1 pass", + "id": 1 + } + + # Disable rule + $ curl -s -X PATCH http://localhost:8453/daf/1/active/false | jq . + true + + # Retrieve a rule information + $ curl -s -X GET http://localhost:8453/daf/1 | jq . + { + "count": 4, + "active": true, + "info": "src = 127.0.0.1 pass", + "id": 1 + } + + # Delete a rule + $ curl -s -X DELETE http://localhost:8453/daf/1 | jq . + true |