.. 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 ` 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/", "GET", "Retrieve a rule matching given ID." "/daf/", "DELETE", "Delete a rule matching given ID." "/daf///", "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