Packet Policies

dnsdist works in essence like any other loadbalancer:

It receives packets on one or several addresses it listens on, and determines whether it will process this packet based on the Access Control. Should the packet be processed, dnsdist attempts to match any of the configured rules in order and when one matches, the associated action is performed.

These rule and action combinations are considered policies.

Packet Actions

Each packet can be:

  • Dropped
  • Turned into an answer directly
  • Forwarded to a downstream server
  • Modified and forwarded to a downstream and be modified back
  • Be delayed

This decision can be taken at different times during the forwarding process.

Examples

Rules for traffic exceeding QPS limits

Traffic that exceeds a QPS limit, in total or per IP (subnet) can be matched by a rule.

For example:

addDelay(MaxQPSIPRule(5, 32, 48), 100)

This measures traffic per IPv4 address and per /48 of IPv6, and if traffic for such an address (range) exceeds 5 qps, it gets delayed by 100ms.

As another example:

addAction(MaxQPSIPRule(5), NoRecurseAction())

This strips the Recursion Desired (RD) bit from any traffic per IPv4 or IPv6 /64 that exceeds 5 qps. This means any those traffic bins is allowed to make a recursor do ‘work’ for only 5 qps.

If this is not enough, try:

addAction(MaxQPSIPRule(5), DropAction())

or:

addAction(MaxQPSIPRule(5), TCAction())

This will respectively drop traffic exceeding that 5 QPS limit per IP or range, or return it with TC=1, forcing clients to fall back to TCP.

To turn this per IP or range limit into a global limit, use NotRule(MaxQPSRule(5000)) instead of MaxQPSIPRule().

Regular Expressions

RegexRule() matches a regular expression on the query name, and it works like this:

addAction(RegexRule("[0-9]{5,}"), DelayAction(750)) -- milliseconds
addAction(RegexRule("[0-9]{4,}\\.example$"), DropAction())

This delays any query for a domain name with 5 or more consecutive digits in it. The second rule drops anything with more than 4 consecutive digits within a .example domain.

Note that the query name is presented without a trailing dot to the regex. The regex is applied case insensitively.

Alternatively, if compiled in, RE2Rule() provides similar functionality, but against libre2.

Rule Generators

dnsdist contains several functions that make it easier to add actions and rules.

addAnyTCRule()

Set the TC-bit (truncate) on all queries received over UDP. Forcing a retry over TCP. This is equivalent to doing:

addAction(AndRule(AllRule(), TCPRule(false)), TCAction())
addDelay(DNSrule, delay)

Delay the query for delay milliseconds before sending to a backend.

Parameters:
  • DNSRule – The DNSRule to match traffic
  • delay (int) – The delay time in milliseconds.
addDisableValidationRule(DNSrule)

Set the CD (Checking Disabled) flag to 1 for all queries matching the DNSRule. Using this function is equal to using the DisableValidationAction().

addDomainBlock(domain)

Drop all queries for domain and all names below it.

Parameters:domain (string) – The domain name to block
addDomainSpoof(domain, IPv4[, IPv6])
addDomainSpoof(domain, {IP[,...]})

Generate answers for A/AAAA/ANY queries.

Parameters:
  • domain (string) – Domain name to spoof for
  • IPv4 (string) – IPv4 address to spoof in the reply
  • IPv6 (string) – IPv6 address to spoof in the reply
  • IP (string) – IP address to spoof in the reply
addDomainCNAMESpoof(domain, cname)

Generate CNAME answers for queries.

Parameters:
  • domain (string) – Domain name to spoof for
  • cname (string) – Domain name to add CNAME to
addLuaAction(DNSrule, function)

Invoke a Lua function that accepts a DNSQuestion. This function works similar to using LuaAction().

The function should return a DNSAction.

Parameters:
  • DNSRule – match queries based on this rule
  • function (string) – the name of a Lua function
addLuaResponseAction(DNSrule, function)

Invoke a Lua function that accepts a DNSQuestion on the response. This function works similar to using LuaAction().

The function should return a DNSAction.

Parameters:
  • DNSRule – match queries based on this rule
  • function (string) – the name of a Lua function
addNoRecurseRule(DNSrule)

Clear the RD flag for all queries matching the rule.

Parameters:DNSRule – match queries based on this rule
addPoolRule(DNSRule, pool)

Send queries matching the first argument to the pool pool. e.g.:

addPoolRule("example.com", "myPool")

This is equivalent to:

addAction("example.com", PoolAction("myPool"))
Parameters:
  • DNSRule – match queries based on this rule
  • pool (string) – The name of the pool to send the queries to
addQPSLimit(DNSrule, limit)

Limit queries matching the DNSRule to limit queries per second. All queries over the limit are dropped.

Parameters:
  • DNSRule – match queries based on this rule
  • limit (int) – QPS limit for this rule
addQPSPoolRule(DNSRule, limit, pool)

Send at most limit queries/s for this pool, letting the subsequent rules apply otherwise. This is a convience function for the following syntax:

addAction("192.0.2.0/24", QPSPoolAction(15, "myPool")
Parameters:
  • DNSRule – match queries based on this rule
  • limit (int) – QPS limit for this rule
  • pool (string) – The name of the pool to send the queries to

Managing Rules

Active Rules can be shown with showRules() and removed with rmRule():

> addQPSLimit("h4xorbooter.xyz.", 10)
> addQPSLimit({"130.161.0.0/16", "145.14.0.0/16"} , 20)
> addQPSLimit({"nl.", "be."}, 1)
> showRules()
#     Matches Rule                                               Action
0           0 h4xorbooter.xyz.                                   qps limit to 10
1           0 130.161.0.0/16, 145.14.0.0/16                      qps limit to 20
2           0 nl., be.                                           qps limit to 1

For Rules related to the incoming query:

addAction(DNSrule, action)

Add a Rule and Action to the existing rules.

Parameters:
  • rule (DNSrule) – A DNSRule, e.g. an allRule() or a compounded bunch of rules using e.g. AndRule()
  • action – The action to take
clearRules()

Remove all current rules.

getAction(n) → Action

Returns the Action associated with rule n.

Parameters:n (int) – The rule number
mvRule(from, to)

Move rule from to a position where it is in front of to. to can be one larger than the largest rule, in which case the rule will be moved to the last position.

Parameters:
  • from (int) – Rule number to move
  • to (int) – Location to more the Rule to
newRuleAction(rule, action)

Return a pair of DNS Rule and DNS Action, to be used with setRules().

Parameters:
  • rule (Rule) – A Rule
  • action (Action) – The Action to apply to the matched traffic
setRules(rules)

Replace the current rules with the supplied list of pairs of DNS Rules and DNS Actions (see newRuleAction())

Parameters:rules ([RuleAction]) – A list of RuleActions
showRules()

Show all defined rules for queries.

topRule()

Move the last rule to the first position.

rmRule(n)

Remove rule n.

Parameters:n (int) – Rule number to remove

For Rules related to responses:

addResponseAction(DNSRule, action)

Add a Rule and Action for responses to the existing rules.

Parameters:
  • DNSRule – A DNSRule, e.g. an allRule() or a compounded bunch of rules using e.g. AndRule()
  • action – The action to take
mvResponseRule(from, to)

Move response rule from to a position where it is in front of to. to can be one larger than the largest rule, in which case the rule will be moved to the last position.

Parameters:
  • from (int) – Rule number to move
  • to (int) – Location to more the Rule to
rmResponseRule(n)

Remove response rule n.

Parameters:n (int) – Rule number to remove
showResponseRules()

Show all defined response rules.

topResponseRule()

Move the last response rule to the first position.

Functions for manipulation Cache Hit Rules:

addCacheHitAction(DNSRule, action)

New in version 1.2.0.

Add a Rule and Action for Cache Hits to the existing rules.

Parameters:
  • DNSRule – A DNSRule, e.g. an allRule() or a compounded bunch of rules using e.g. AndRule()
  • action – The action to take
mvCacheHitResponseRule(from, to)

New in version 1.2.0.

Move cache hit response rule from to a position where it is in front of to. to can be one larger than the largest rule, in which case the rule will be moved to the last position.

Parameters:
  • from (int) – Rule number to move
  • to (int) – Location to more the Rule to
rmCacheHitResponseRule(n)

New in version 1.2.0.

Remove cache hit response rule n.

Parameters:n (int) – Rule number to remove
showCacheHitResponseRules()

New in version 1.2.0.

Show all defined cache hit response rules.

topCacheHitResponseRule()

New in version 1.2.0.

Move the last cache hit response rule to the first position.

Matching Packets (Selectors)

Packets can be matched by selectors, called a DNSRule. These DNSRules be one of the following items:

  • A string that is either a domain name or netmask
  • A list of strings that are either domain names or netmasks
  • A DNSName
  • A list of DNSNames
  • A (compounded) Rule

New in version 1.2.0: A DNSRule can also be a DNSName or a list of these

AllRule()

Matches all traffic

DNSSECRule()

Matches queries with the DO flag set

MaxQPSIPRule(qps[, v4Mask[, v6Mask]])

Matches traffic for a subnet specified by v4Mask or v6Mask exceeding qps queries per second

Parameters:
  • qps (int) – The number of queries per second allowed, above this number traffic is matched
  • v4Mask (int) – The IPv4 netmask to match on. Default is 32 (the whole address)
  • v6Mask (int) – The IPv6 netmask to match on. Default is 64
MaxQPSRule(qps)

Matches traffic exceeding this qps limit. If e.g. this is set to 50, starting at the 51st query of the current second traffic is matched. This can be used to enforce a global QPS limit.

Parameters:qps (int) – The number of queries per second allowed, above this number traffic is matched
NetmaskGroupRule(nmg[, src])

Matches traffic from/to the network range specified in nmg.

Set the src parameter to false to match nmg against destination address instead of source address. This can be used to differentiate between clients

Parameters:
  • nmg (NetMaskGroup) – The NetMaskGroup to match on
  • src (bool) – Whether to match source or destination address of the packet. Defaults to true (matches source)
OpcodeRule(code)

Matches queries with opcode code. code can be directly specified as an integer, or one of the built-in DNSOpcode.

Parameters:code (int) – The opcode to match
QClassRule(qclass)

Matches queries with the specified qclass. class can be specified as an integer or as one of the built-in QClass.

Parameters:qclass (int) – The Query Class to match on
QnameRule(qname)

New in version 1.2.0: Matches queries with the specified qname exactly.

param string qname:
 Qname to match
QNameLabelsCountRule(min, max)

Matches if the qname has less than min or more than max labels.

Parameters:
  • min (int) – Minimum number of labels
  • max (int) – Maximum nimber of labels
QNameWireLengthRule(min, max)

Matches if the qname’s length on the wire is less than min or more than max bytes.

Parameters:
  • min (int) – Minimum number of bytes
  • max (int) – Maximum nimber of bytes
QTypeRule(qtype)

Matches queries with the specified qtype qtype may be specified as an integer or as one of the built-in QTypes. For instance dnsdist.A, dnsdist.TXT and dnsdist.ANY.

Parameters:qtype (int) – The QType to match on
RCodeRule(rcode)

Matches queries or responses the specified rcode. rcode can be specified as an integer or as one of the built-in RCode.

Parameters:rcode (int) – The RCODE to match on
RDRule()

New in version 1.2.0.

Matches queries with the RD flag set.

RegexRule(regex)

Matches the query name against the regex.

addAction(RegexRule("[0-9]{5,}"), DelayAction(750)) -- milliseconds
addAction(RegexRule("[0-9]{4,}\\.example$"), DropAction())

This delays any query for a domain name with 5 or more consecutive digits in it. The second rule drops anything with more than 4 consecutive digits within a .EXAMPLE domain.

Note that the query name is presented without a trailing dot to the regex. The regex is applied case insensitively.

Parameters:regex (string) – A regular expression to match the traffic on
RecordsCountRule(section, minCount, maxCount)

Matches if there is at least minCount and at most maxCount records in the section section. section can be specified as an integer or as a DNS Section.

Parameters:
  • section (int) – The section to match on
  • minCount (int) – The minimum number of entries
  • maxCount (int) – The maximum number of entries
RecordsTypeCountRule(section, qtype, minCount, maxCount)

Matches if there is at least minCount and at most maxCount records of type type in the section section. section can be specified as an integer or as a ref:DNSSection. qtype may be specified as an integer or as one of the built-in QTypes, for instance dnsdist.A or dnsdist.TXT.

Parameters:
  • section (int) – The section to match on
  • qtype (int) – The QTYPE to match on
  • minCount (int) – The minimum number of entries
  • maxCount (int) – The maximum number of entries
RE2Rule(regex)

Matches the query name against the supplied regex using the RE2 engine.

For an example of usage, see RegexRule().

Note:Only available when dnsdist was built with libre2 support.
Parameters:regex (str) – The regular expression to match the QNAME.
SuffixMatchNodeRule(smn[, quiet])

Matches based on a group of domain suffixes for rapid testing of membership. Pass true as second parameter to prevent listing of all domains matched.

Parameters:
  • smb (SuffixMatchNode) – The SuffixMatchNode to match on
  • quiet (bool) – Do not return the list of matched domains. Default is false.
TCPRule([tcp])

Matches question received over TCP if tcp is true, over UDP otherwise.

Parameters:tcp (bool) – Match TCP traffic. Default is true.
TrailingDataRule()

Matches if the query has trailing data.

Combining Rules

andRule(selectors)

Matches traffic if all selectors match.

Parameters:selectors ({Rule}) – A table of Rules
NotRule(selector)

Matches the traffic if the selector rule does not match;

Parameters:selector (Rule) – A Rule
OrRule(selectors)

Matches the traffic if one or more of the the selectors Rules does match.

Parameters:selector ({Rule}) – A table of Rules

Convience Functions

makeRule(rule)

Make a NetmaskGroupRule() or a SuffixMatchNodeRule(), depending on it is called. makeRule("0.0.0.0/0") will for example match all IPv4 traffic, makeRule({"be","nl","lu"}) will match all Benelux DNS traffic.

Parameters:rule (string) – A string to convert to a rule.

Actions

Matching Packets (Selectors) need to be combined with an action for them to actually do something with the matched packets. Some actions allow further processing of rules, this is noted in their description. The following actions exist.

AllowAction()

Let these packets go through.

AllowResponseAction()

Let these packets go through.

DelayAction(milliseconds)

Delay the response by the specified amount of milliseconds (UDP-only). Subsequent rules are processed after this rule.

Parameters:milliseconds (int) – The amount of milliseconds to delay the response
DelayResponseAction(milliseconds)

Delay the response by the specified amount of milliseconds (UDP-only). Subsequent rules are processed after this rule.

Parameters:milliseconds (int) – The amount of milliseconds to delay the response
DisableECSAction()

Disable the sending of ECS to the backend. Subsequent rules are processed after this rule.

DisableValidationAction()

Set the CD bit in the query and let it go through.

DropAction()

Drop the packet.

DropResponseAction()

Drop the packet.

ECSOverrideAction(override)

Whether an existing EDNS Client Subnet value should be overridden (true) or not (false). Subsequent rules are processed after this rule.

Parameters:override (bool) – Whether or not to override ECS value
ECSPrefixLengthAction(v4, v6)

Set the ECS prefix length. Subsequent rules are processed after this rule.

Parameters:
  • v4 (int) – The IPv4 netmask length
  • v6 (int) – The IPv6 netmask length
LogAction([filename[, binary[, append[, buffered]]]])

Log a line for each query, to the specified file if any, to the console (require verbose) otherwise. When logging to a file, the binary optional parameter specifies whether we log in binary form (default) or in textual form. The append optional parameter specifies whether we open the file for appending or truncate each time (default). The buffered optional parameter specifies whether writes to the file are buffered (default) or not. Subsequent rules are processed after this rule.

Parameters:
  • filename (string) – File to log to
  • binary (bool) – Do binary logging. Default true
  • append (bool) – Append to the log. Default false
  • buffered (bool) – Use buffered I/O. default true
MacAddrAction(option)

Add the source MAC address to the query as EDNS0 option option. This action is currently only supported on Linux. Subsequent rules are processed after this rule.

Parameters:option (int) – The EDNS0 option number
NoneAction()

Does nothing. Subsequent rules are processed after this rule.

NoRecurseAction()

Strip RD bit from the question, let it go through. Subsequent rules are processed after this rule.

PoolAction(poolname)

Send the packet into the specified pool.

Parameters:poolname (string) – The name of the pool
QPSPoolAction(maxqps, poolname)

Send the packet into the specified pool only if it does not exceed the maxqps queries per second limits. Letting the subsequent rules apply otherwise.

Parameters:
  • maxqps (int) – The QPS limit for that pool
  • poolname (string) – The name of the pool
RCodeAction(rcode)

Reply immediatly by turning the query into a response with the specified rcode. rcode can be specified as an integer or as one of the built-in RCode.

Parameters:rcode (int) – The RCODE to respond with.
RemoteLogAction(remoteLogger[, alterFunction])

Send the content of this query to a remote logger via Protocol Buffer. alterFunction is a callback, receiving a DNSQuestion and a DNSDistProtoBufMessage, that can be used to modify the Protocol Buffer content, for example for anonymization purposes

Parameters:
  • remoteLogger (string) – An IP:PORT combo to send the remote log to
  • alterFunction (string) – Name of a function to modify the contents of the logs before sending
RemoteLogResponseAction(remoteLogger[, alterFunction[, includeCNAME]])

Send the content of this response to a remote logger via Protocol Buffer. alterFunction is the same callback that receiving a DNSQuestion and a DNSDistProtoBufMessage, that can be used to modify the Protocol Buffer content, for example for anonymization purposes includeCNAME indicates whether CNAME records inside the response should be parsed and exported. The default is to only exports A and AAAA records

Parameters:
  • remoteLogger (string) – An IP:PORT combo to send the remote log to
  • alterFunction (string) – Name of a function to modify the contents of the logs before sending
  • includeCNAME (bool) – Whether or not to parse and export CNAMEs. Default false
SkipCacheAction()

Don’t lookup the cache for this query, don’t store the answer.

SNMPTrapAction([message])

Send an SNMP trap, adding the optional message string as the query description. Subsequent rules are processed after this rule.

Parameters:message (string) – The message to include
SNMPTrapResponseAction([message])

Send an SNMP trap, adding the optional message string as the query description. Subsequent rules are processed after this rule.

Parameters:message (string) – The message to include
SpoofAction(ip[, ip[...]])
SpoofAction(ips)

Forge a response with the specified IPv4 (for an A query) or IPv6 (for an AAAA) addresses. If you specify multiple addresses, all that match the query type (A, AAAA or ANY) will get spoofed in.

Parameters:
  • ip (string) – An IPv4 and/or IPv6 address to spoof
  • ips ({string}) – A table of IPv4 and/or IPv6 addresses to spoof
SpoofCNAMEAction(cname)

Forge a response with the specified CNAME value.

Parameters:cname (string) – The name to respond with
TCAction()

Create answer to query with TC and RD bits set, to force the client to TCP.

TeeAction(remote[, addECS])

Send copy of query to remote, keep stats on responses. If addECS is set to true, EDNS Client Subnet information will be added to the query.

Parameters:
  • remote (string) – An IP:PORT conbination to send the copied queries to
  • addECS (bool) – Whether or not to add ECS information. Default false