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.

-- 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 = deny')

-- We also can reroute addresses in response to alternate target
-- This reroutes to localhost
daf.add('src = reroute')

-- Subnets work too, this reroutes a whole subnet
-- e.g. to
daf.add('src = reroute')

-- This rewrites all A answers for 'example.com' from
-- whatever the original address was to
daf.add('src = rewrite example.com A')

-- Mirror queries matching given name to DNS logger
daf.add('qname ~ %w+.example.com mirror')
daf.add('qname ~ example-%d.com mirror')

-- Forward queries from subnet
daf.add('src = forward')
-- Forward to multiple targets
daf.add('src = forward,')

-- Truncate queries based on destination IPs
daf.add('dst = truncate')

-- Disable a rule
-- Enable a rule
-- Delete a rule

-- Delete all rules and start from scratch


Only the first matching rule’s action is executed. Defining additional actions for the same matching rule, e.g. src =, will have no effect.

If you’re not sure what firewall rules are in effect, see daf.rules:

-- Show active rules
> daf.rules
[1] => {
    [rule] => {
        [count] => 42
        [id] => 1
        [cb] => function: 0x1a3eda38
    [info] => qname = example.com AND src = deny
    [policy] => function: 0x1a3eda38
[2] => {
    [rule] => {
        [suspended] => true
        [count] => 123522
        [id] => 2
        [cb] => function: 0x1a3ede88
    [info] => qname ~ %w+.facebook.com AND src = deny...
    [policy] => function: 0x1a3ede88

Web interface

If you have 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.






Return JSON list of active rules.



Insert new rule, rule string is expected in body. Returns rule information in JSON.



Retrieve a rule matching given ID.



Delete a rule matching given ID.



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.

# Get current rule set
$ curl -s -X GET http://localhost:8453/daf | jq .

# Create new rule
$ curl -s -X POST -d "src = pass" http://localhost:8453/daf | jq .
  "count": 0,
  "active": true,
  "info": "src = pass",
  "id": 1

# Disable rule
$ curl -s -X PATCH http://localhost:8453/daf/1/active/false | jq .

# Retrieve a rule information
$ curl -s -X GET http://localhost:8453/daf/1 | jq .
  "count": 4,
  "active": true,
  "info": "src = pass",
  "id": 1

# Delete a rule
$ curl -s -X DELETE http://localhost:8453/daf/1 | jq .