]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/README-dnsdist.md
eBPF: eBPF case-insensitive qname filtering
[thirdparty/pdns.git] / pdns / README-dnsdist.md
CommitLineData
773470ca 1dnsdist
2-------
773470ca 3`dnsdist` is a highly DNS-, DoS- and abuse-aware loadbalancer. Its goal in
4life is to route traffic to the best server, delivering top performance
5to legitimate users while shunting or blocking abusive traffic.
6
7`dnsdist` is dynamic, in the sense that its configuration can be changed at
8runtime, and that its statistics can be queried from a console-like
9interface.
10
539921be 11Compiling
12---------
13fe35db 13`dnsdist` depends on boost, Lua or LuaJIT and a pretty recent C++
ee52e6fa 14compiler (g++ 4.8 or higher, clang 3.5 or higher). It can optionally use libsodium
537524f8 15for encrypted communications with its client.
539921be 16
6ab65223
PL
17Should `dnsdist` be run on a system with systemd, it is highly recommended to have
18the systemd header files (`libsystemd-dev` on debian and `systemd-devel` on CentOS)
19installed to have `dnsdist` support systemd-notify.
20
1a5f0162 21To compile on CentOS 6 / RHEL6, use this script to install a working compiler:
260dd1c4 22
23```
24wget -O /etc/yum.repos.d/slc6-devtoolset.repo http://linuxsoft.cern.ch/cern/devtoolset/slc6-devtoolset.repo
25yum install devtoolset-2
26scl enable devtoolset-2 bash
27./configure
28make
29```
30
f2c0afef
PD
31To build on OS X, `./configure LIBEDIT_LIBS='-L/usr/lib -ledit' LIBEDIT_CFLAGS=-I/usr/include/editline`
32
1a5f0162 33On other recent platforms, installing a Lua and the system C++ compiler should be enough.
34
6715a732
PL
35`dnsdist` can drop privileges using the `--uid` and `--gid` commandline-switches
36to ensure it does not run with root privileges after binding its listen-sockets.
37It is highly recommended to create a system user and group for `dnsdist`. Note that
38most packaged versions of `dnsdist` already create this user.
39
0440c642 40Packaged
41--------
ee52e6fa
RG
42We build packages for `dnsdist` on our [repositories](https://repo.powerdns.com). In addition
43`dnsdist` has been packaged for FreeBSD and can be found on https://freshports.org/dns/dnsdist
0440c642 44
539921be 45Examples
46--------
e9ff40cd 47
537524f8 48The absolute minimum configuration:
49
1a5f0162 50```
537524f8 51# dnsdist 2001:4860:4860::8888 8.8.8.8
2332b03c 52```
537524f8 53
54This will listen on 0.0.0.0:53 and forward queries to the two listed IP
55addresses, with a sensible load balancing policy.
56
57Here is a more complete configuration:
773470ca 58
59```
1d637f62 60$ cat /etc/dnsdist.conf
bf9edc24
RG
61newServer({address="2001:4860:4860::8888", qps=1})
62newServer({address="2001:4860:4860::8844", qps=1})
63newServer({address="2620:0:ccc::2", qps=10})
64newServer({address="2620:0:ccd::2", name="dns1", qps=10})
773470ca 65newServer("192.168.1.2")
c9262563 66setServerPolicy(firstAvailable) -- first server within its QPS limit
773470ca 67
021e3aba 68$ dnsdist --local=0.0.0.0:5200
773470ca 69Marking downstream [2001:4860:4860::8888]:53 as 'up'
70Marking downstream [2001:4860:4860::8844]:53 as 'up'
71Marking downstream [2620:0:ccc::2]:53 as 'up'
72Marking downstream [2620:0:ccd::2]:53 as 'up'
73Marking downstream 192.168.1.2:53 as 'up'
74Listening on 0.0.0.0:5200
c9262563 75>
773470ca 76```
77
78We can now send queries to port 5200, and get answers:
79
80```
81$ dig -t aaaa powerdns.com @127.0.0.1 -p 5200 +short
822001:888:2000:1d::2
83```
84
ee52e6fa 85Note that `dnsdist` offered us a prompt above, and on it we can get some
773470ca 86statistics:
87
88```
cd29dcb1 89> showServers()
91c52b48
OS
90# Address State Qps Qlim Ord Wt Queries Drops Drate Lat Pools
910 [2001:4860:4860::8888]:53 up 0.0 1 1 1 1 0 0.0 0.0
921 [2001:4860:4860::8844]:53 up 0.0 1 1 1 0 0 0.0 0.0
932 [2620:0:ccc::2]:53 up 0.0 10 1 1 0 0 0.0 0.0
943 [2620:0:ccd::2]:53 up 0.0 10 1 1 0 0 0.0 0.0
954 192.168.1.2:53 up 0.0 0 1 1 0 0 0.0 0.0
96All 0.0 1 0
773470ca 97```
98
a6c02c23 99Here we also see our configuration. 5 downstream servers have been configured, of
773470ca 100which the first 4 have a QPS limit (of 1, 1, 10 and 10 queries per second,
a6c02c23 101respectively). The final server has no limit, which we can easily test:
773470ca 102
103```
104$ for a in {0..1000}; do dig powerdns.com @127.0.0.1 -p 5200 +noall > /dev/null; done
91c52b48
OS
105> showServers()
106# Address State Qps Qlim Ord Wt Queries Drops Drate Lat Pools
1070 [2001:4860:4860::8888]:53 up 1.0 1 1 1 7 0 0.0 1.6
1081 [2001:4860:4860::8844]:53 up 1.0 1 1 1 6 0 0.0 0.6
1092 [2620:0:ccc::2]:53 up 10.3 10 1 1 64 0 0.0 2.4
1103 [2620:0:ccd::2]:53 up 10.3 10 1 1 63 0 0.0 2.4
1114 192.168.1.2:53 up 125.8 0 1 1 671 0 0.0 0.4
112All 145.0 811 0
773470ca 113```
114
115Note that the first 4 servers were all limited to near their configured QPS,
116and that our final server was taking up most of the traffic. No queries were
117dropped, and all servers remain up.
118
119To force a server down, try:
120
121```
122> getServer(0):setDown()
91c52b48
OS
123> showServers()
124# Address State Qps Qlim Ord Wt Queries Drops Drate Lat Pools
1250 [2001:4860:4860::8888]:53 DOWN 0.0 1 1 1 8 0 0.0 0.0
773470ca 126...
127```
128
129The 'DOWN' in all caps means it was forced down. A lower case 'down'
ee52e6fa 130would've meant that `dnsdist` itself had concluded the server was down.
773470ca 131Similarly, setUp() forces a server to be up, and setAuto() returns it to the
132default availability-probing.
133
134To change the QPS for a server:
135```
136> getServer(0):setQPS(1000)
137```
138
66407d9e
RG
139By default, the availability of a downstream server is checked by regularly
140sending an A query for "a.root-servers.net.". A different query type and target
9e87dcb8 141can be specified by passing, respectively, the `checkType` and `checkName`
66407d9e 142parameters to `newServer`. The default behavior is to consider any valid response
9e87dcb8 143with a RCODE different from ServFail as valid. If the `mustResolve` parameter
66407d9e
RG
144of `newServer` is set to true, a response will only be considered valid if
145its RCODE differs from NXDomain, ServFail and Refused.
9e87dcb8
RG
146The number of health check failures before a server is considered down is
147configurable via the`maxCheckFailures` parameter, defaulting to 1.
66407d9e
RG
148
149```
bf9edc24 150newServer({address="192.0.2.1", checkType="AAAA", checkName="a.root-servers.net.", mustResolve=true})
66407d9e
RG
151```
152
ca404e94 153In order to provide the downstream server with the address of the real client,
a1400993 154or at least the one talking to `dnsdist`, the `useClientSubnet` parameter can be used
ca404e94
RG
155when declaring a new server. This parameter indicates whether an EDNS Client Subnet option
156should be added to the request. If the incoming request already contains an EDNS Client Subnet value,
a1400993
RG
157it will not be overriden unless `setECSOverride()` is set to true.
158The default source prefix-length is 24 for IPv4 and 56 for IPv6, meaning that for a query
159received from 192.0.2.42, the EDNS Client Subnet value sent to the backend will
160be 192.0.2.0. This can be changed with:
ca404e94
RG
161```
162> setECSSourcePrefixV4(24)
163> setECSSourcePrefixV6(56)
164```
165
3f6d07a4
RG
166TCP timeouts
167------------
168
169By default, a 2 seconds timeout is enforced on the TCP connection from the client,
170meaning that a connection will be closed if the query can't be read in less than 2s
171or if the answer can't be sent in less than 2s. This can be configured with:
172```
173> setTCPRecvTimeout(5)
174> setTCPSendTimeout(5)
175```
176
177The same kind of timeouts is enforced on the TCP connections to the downstream servers.
178The default value of 30s can be modified by passing the `tcpRecvTimeout` and `tcpSendTimeout`
9e87dcb8
RG
179parameters to `newServer`. If the TCP connection to a downstream server fails, `dnsdist`
180will try to establish a new one up to `retries` times before giving up.
3f6d07a4 181```
9e87dcb8 182newServer({address="192.0.2.1", tcpRecvTimeout=10, tcpSendTimeout=10, retries=5})
3f6d07a4
RG
183```
184
fbe2a2e0
RG
185Source address
186--------------
187
188In multi-homed setups, it can be useful to be able to select the source address or the outgoing
189interface used by `dnsdist` to contact a downstream server.
190This can be done by using the `source` parameter:
191```
192newServer({address="192.0.2.1", source="192.0.2.127"})
193newServer({address="192.0.2.1", source="eth1"})
194newServer({address="192.0.2.1", source="192.0.2.127@eth1"})
195```
196
197The supported values for `source` are:
a1400993 198
fbe2a2e0
RG
199 * an IPv4 or IPv6 address, which must exist on the system
200 * an interface name
201 * an IPv4 or IPv6 address followed by '@' then an interface name
202
203Specifying the interface name is only supported on system having IP_PKTINFO.
204
205
6149a8bf 206Configuration management
207------------------------
208At startup, configuration is read from the command line and the
209configuration file. The config can also be inspected and changed from the
210console. Sadly, our architecture does not allow us to serialize the running
211configuration for you. However, we do try to offer the next best thing:
212`delta()`.
213
214`delta()` shows all commands entered that changed the configuration. So
215adding a new downstream server with `newServer()` would show up, but
216`showServers()` or even `delta()` itself would not.
217
218It is suggested to study the output of `delta()` carefully before appending
219it to your configuration file.
220
bf9edc24
RG
221```
222> setACL("192.0.2.0/24")
223> showACL()
224192.0.2.0/24
225> delta()
2e439533 226-- Wed Dec 23 2015 15:15:35 CET
bf9edc24
RG
227setACL("192.0.2.0/24")
228> addACL("127.0.0.1/8")
229> showACL()
230192.0.2.0/24
231127.0.0.1/8
232> delta()
2e439533 233-- Wed Dec 23 2015 15:15:35 CET
bf9edc24 234setACL("192.0.2.0/24")
2e439533 235-- Wed Dec 23 2015 15:15:44 CET
bf9edc24
RG
236addACL("127.0.0.1/8")
237>
238```
239
240
b5735af6 241Webserver
242---------
ee52e6fa 243To visually interact with `dnsdist`, try adding:
b5735af6 244```
5ef0af18 245webserver("127.0.0.1:8083", "supersecretpassword", "supersecretAPIkey")
b5735af6 246```
247
248to the configuration, and point your browser at http://127.0.0.1:8083 and
249log in with any username, and that password. Enjoy!
250
002decab
RG
251By default, our web server sends some security-related headers:
252
253 * X-Content-Type-Options: nosniff
254 * X-Frame-Options: deny
255 * X-Permitted-Cross-Domain-Policies: none
256 * X-XSS-Protection: 1; mode=block
257 * Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'
258
259You can override those headers, or add custom headers by using the last parameter to
260`webserver()`. For example, to remove the `X-Frame-Options` header and add a
261`X-Custom` one:
262```
263webserver("127.0.0.1:8080", "supersecret", "apikey", {["X-Frame-Options"]= "", ["X-Custom"]="custom"})
264```
265
266
d95585af 267Server pools
268------------
773470ca 269Now for some cool stuff. Let's say we know we're getting a whole bunch of
270traffic for a domain used in DoS attacks, for example 'sh43354.cn'. We can
271do two things with this kind of traffic. Either we block it outright, like
272this:
273
274```
275> addDomainBlock("sh43354.cn.")
276```
277
22b2b326 278Or we configure a server pool dedicated to receiving the nasty stuff:
773470ca 279
280```
bf9edc24 281> newServer({address="192.168.1.3", pool="abuse"})
22b2b326 282> addPoolRule({"sh43353.cn.", "ezdns.it."}, "abuse")
773470ca 283```
284
285The wonderful thing about this last solution is that it can also be used for
286things where a domain might possibly be legit, but it is still causing load
287on the system and slowing down the internet for everyone. With such an abuse
288server, 'bad traffic' still gets a chance of an answer, but without
289impacting the rest of the world (too much).
290
291We can similarly add clients to the abuse server:
292
293```
22b2b326 294> addPoolRule({"192.168.12.0/24", "192.168.13.14"}, "abuse")
295```
296
20357a9a 297To define a pool that should receive only a QPS-limited amount of traffic, do:
fd010ca3 298
299```
300> addQPSPoolRule("com.", 10000, "gtld-cluster")
301```
302
20357a9a
RG
303Traffic exceeding the QPS limit will not match that rule, and subsequent
304rules will apply normally.
fd010ca3 305
0940e4eb 306Both `addDomainBlock` and `addPoolRule` end up the list of Rules
307and Actions (for which see below).
308
309Servers can be added or removed to pools with:
22b2b326 310```
311> getServer(7):addPool("abuse")
537524f8 312> getServer(4):rmPool("abuse")
773470ca 313```
314
0940e4eb 315
316Rules
317-----
318Rules can be inspected with `showRules()`, and can be deleted with
319`rmRule()`. Rules are evaluated in order, and this order can be changed
320with `mvRule(from, to)` (see below for exact semantics).
321
322Rules have selectors and actions. Current selectors are:
caec2956 323
0940e4eb 324 * Source address
325 * Query type
326 * Query domain
2332b03c 327 * QPS Limit total
328 * QPS Limit per IP address or subnet
df3e393a 329 * QClass (QClassRule)
b7860997 330 * QType (QTypeRule)
6eecd4c2 331 * RegexRule on query name
0bdb1955 332 * RE2Rule on query name (optional)
6eecd4c2 333 * Packet requests DNSSEC processing
490a29bb 334 * Query received over UDP or TCP
55baa1f2
RG
335 * Opcode (OpcodeRule)
336 * Number of entries in a given section (RecordsCountRule)
337 * Number of entries of a specific type in a given section (RecordsTypeCountRule)
338 * Presence of trailing data (TrailingDataRule)
0940e4eb 339
e7a1029c 340Special rules are:
caec2956 341
e7a1029c
RG
342 * `AndRule{rule1, rule2}`, which only matches if all of its subrules match
343 * `OrRule{rule1, rule2}`, which matches if at least one of its subrules match
344 * `NotRule(rule)`, which matches if its subrule does not match
b7860997 345
0940e4eb 346Current actions are:
caec2956 347
ecc8a33b 348 * Drop (DropAction)
349 * Route to a pool (PoolAction)
0940e4eb 350 * Return with TC=1 (truncated, ie, instruction to retry with TCP)
351 * Force a ServFail, NotImp or Refused answer
352 * Send out a crafted response (NXDOMAIN or "real" data)
1a2a4e68
RG
353 * Delay a response by n milliseconds (DelayAction), over UDP only
354 * Modify query to clear the RD or CD bit
355 * Add the source MAC address to the query (MacAddrAction)
886e2cf2 356 * Skip the cache, if any
27dfcc14
RG
357 * Log query content to a remote server (RemoteLogAction)
358
359Current response actions are:
360
361 * Log response content to a remote server (RemoteLogResponseAction)
0940e4eb 362
ee52e6fa 363Rules can be added via:
caec2956 364
ecc8a33b 365 * addAction(DNS rule, DNS Action)
ee52e6fa
RG
366 * addAnyTCRule()
367 * addDelay(DNS rule, delay in milliseconds)
368 * addDisableValidationRule(DNS rule)
369 * addDomainBlock(domain)
7b9d167c 370 * addDomainSpoof(domain, IPv4[, IPv6]) or addDomainSpoof(domain, {IP, IP, IP..})
87c605c4 371 * addDomainCNAMESpoof(domain, CNAME)
ee52e6fa
RG
372 * addLuaAction(DNS rule, lua function)
373 * addNoRecurseRule(DNS rule)
374 * addPoolRule(DNS rule, destination pool)
375 * addQPSLimit(DNS rule, qps limit)
376 * addQPSPoolRule(DNS rule, qps limit, destination pool)
377
27dfcc14
RG
378Response rules can be added via:
379
380 * addResponseAction(DNS rule, DNS Response Action)
381
ee52e6fa 382A DNS rule can be:
caec2956 383
ee52e6fa
RG
384 * an AllRule
385 * an AndRule
386 * a MaxQPSIPRule
387 * a MaxQPSRule
388 * a NetmaskGroupRule
e7a1029c 389 * a NotRule
55baa1f2 390 * an OpcodeRule
e7a1029c 391 * an OrRule
df3e393a 392 * a QClassRule
ee52e6fa
RG
393 * a QTypeRule
394 * a RegexRule
0bdb1955 395 * a RE2Rule
55baa1f2
RG
396 * a RecordsCountRule
397 * a RecordsTypeCountRule
ee52e6fa 398 * a SuffixMatchNodeRule
490a29bb 399 * a TCPRule
55baa1f2 400 * a TrailingDataRule
ee52e6fa 401
1a2a4e68 402Some specific actions do not stop the processing when they match, contrary to all other actions:
13fe35db 403
1a2a4e68
RG
404 * Delay
405 * Disable Validation
406 * Log
407 * MacAddr
408 * No Recurse
1a2a4e68
RG
409 * and of course None
410
ecc8a33b 411A convenience function `makeRule()` is supplied which will make a NetmaskGroupRule for you or a SuffixMatchNodeRule
412depending on how you call it. `makeRule("0.0.0.0/0")` will for example match all IPv4 traffic, `makeRule{"be","nl","lu"}` will
413match all Benelux DNS traffic.
414
773470ca 415More power
416----------
417More powerful things can be achieved by defining a function called
418`blockFilter()` in the configuration file, which can decide to drop traffic
2d1d4a16 419on any reason it wants. If you return 'true' from there, the query will get
420blocked.
421
422A demo on how to do this and many other things can be found on
ee52e6fa 423https://github.com/powerdns/pdns/blob/master/pdns/dnsdistconf.lua and
537524f8 424the exact definition of `blockFilter()` is at the end of this document.
2d1d4a16 425
426ANY or whatever to TC
427---------------------
490a29bb
RG
428The `blockFilter()` also gets passed read/writable copy of the DNS Header,
429via `dq.dh`.
ee52e6fa 430If you invoke setQR(1) on that, `dnsdist` knows you turned the packet into
2d1d4a16 431a response, and will send the answer directly to the original client.
432
433If you also called setTC(1), this will tell the remote client to move to
434TCP/IP, and in this way you can implement ANY-to-TCP even for downstream
435servers that lack this feature.
436
0940e4eb 437Note that calling `addAnyTCRule()` achieves the same thing, without
438involving Lua.
439
2332b03c 440Rules for traffic exceeding QPS limits
441--------------------------------------
442Traffic that exceeds a QPS limit, in total or per IP (subnet) can be matched by a rule.
443
444For example:
445
446```
447addDelay(MaxQPSIPRule(5, 32, 48), 100)
448```
449
450This measures traffic per IPv4 address and per /48 of IPv6, and if traffic for such
451an address (range) exceeds 5 qps, it gets delayed by 100ms.
452
453As another example:
454
455```
456addAction(MaxQPSIPRule(5), NoRecurseAction())
457```
458
459This strips the Recursion Desired (RD) bit from any traffic per IPv4 or IPv6 /64
460that exceeds 5 qps. This means any those traffic bins is allowed to make a recursor do 'work'
461for only 5 qps.
462
463If this is not enough, try:
464
465```
466addAction(MaxQPSIPRule(5), DropAction())
467-- or
468addAction(MaxQPSIPRule(5), TCAction())
469```
470
471This will respectively drop traffic exceeding that 5 QPS limit per IP or range, or return it with TC=1, forcing
472clients to fall back to TCP/IP.
473
20357a9a 474To turn this per IP or range limit into a global limit, use NotRule(MaxQPSRule(5000)) instead of MaxQPSIPRule.
2332b03c 475
379de8b0 476TeeAction
477---------
478This action sends off a copy of a UDP query to another server, and keeps statistics
479on the responses received. Sample use:
480
481```
482> addAction(AllRule(), TeeAction("192.168.1.54"))
483> getAction(0):printStats()
484refuseds 0
485nxdomains 0
486noerrors 0
487servfails 0
488recv-errors 0
489tcp-drops 0
490responses 0
491other-rcode 0
492send-errors 0
493queries 0
494```
495
496It is also possible to share a TeeAction between several rules. Statistics
497will be combined in that case.
498
d8d85a30 499Lua actions in rules
500--------------------
501While we can pass every packet through the `blockFilter()` functions, it is also
502possible to configure `dnsdist` to only hand off some packets for Lua inspection.
503If you think Lua is too slow for your query load, or if you are doing heavy processing in Lua,
504this may make sense.
505
506To select specific packets for Lua attention, use `addLuaAction(x, func)`,
507where x is either a netmask, or a domain suffix, or a table of netmasks or a
508table of domain suffixes. This is identical to how `addPoolRule()` selects.
509
510The function should look like this:
511```
497a6e3a
RG
512function luarule(dq)
513 if(dq.qtype==35) -- NAPTR
d8d85a30 514 then
515 return DNSAction.Pool, "abuse" -- send to abuse pool
516 else
517 return DNSAction.None, "" -- no action
518 end
519end
520```
521
ee52e6fa 522Valid return values for `LuaAction` functions are:
13fe35db 523
ee52e6fa 524 * DNSAction.Allow: let the query pass, skipping other rules
1a2a4e68 525 * DNSAction.Delay: delay the response for the specified milliseconds (UDP-only), continue to the next rule
ee52e6fa
RG
526 * DNSAction.Drop: drop the query
527 * DNSAction.HeaderModify: indicate that the query has been turned into a response
528 * DNSAction.None: continue to the next rule
529 * DNSAction.Nxdomain: return a response with a NXDomain rcode
88d05ca1 530 * DNSAction.Pool: use the specified pool to forward this query
7791f83a 531 * DNSAction.Spoof: spoof the response using the supplied IPv4 (A), IPv6 (AAAA) or string (CNAME) value
ee52e6fa 532
b4fd86c3 533DNSSEC
534------
535To provide DNSSEC service from a separate pool, try:
536```
bf9edc24
RG
537newServer({address="2001:888:2000:1d::2", pool="dnssec"})
538newServer({address="2a01:4f8:110:4389::2", pool="dnssec"})
b4fd86c3 539setDNSSECPool("dnssec")
540topRule()
541```
542
543This routes all queries with a DNSSEC OK (DO) or CD bit set to on to the "dnssec" pool.
544The final `topRule()` command moves this rule to the top, so it gets evaluated first.
545
6eecd4c2 546Regular Expressions
547-------------------
548`RegexRule()` matches a regular expression on the query name, and it works like this:
549
550```
551addAction(RegexRule("[0-9]{5,}"), DelayAction(750)) -- milliseconds
552addAction(RegexRule("[0-9]{4,}\\.cn$"), DropAction())
553```
554
555This delays any query for a domain name with 5 or more consecutive digits in it.
556The second rule drops anything with more than 4 consecutive digits within a .CN domain.
557
558Note that the query name is presented without a trailing dot to the regex.
559The regex is applied case insensitively.
560
0bdb1955 561Alternatively, if compiled in, RE2Rule provides similar functionality, but against libre2.
562
c9262563 563Inspecting live traffic
564-----------------------
565This is still much in flux, but for now, try:
566
2a05b4a9 567 * `grepq(Netmask|DNS Name|100ms [, n])`: shows the last n queries and responses matching the specified client address or range (Netmask), or the specified DNS Name, or slower than 100ms
568 * `grepq({"::1", "powerdns.com", "100ms"} [, n])`: shows the last n queries and responses matching the specified client address AND range (Netmask) AND the specified DNS Name AND slower than 100ms
569 * `topBandwidth(top)`: show top-`top` clients that consume the most bandwidth over length of ringbuffer
2e439533 570 * `topClients(n)`: show top-`n` clients sending the most queries over length of ringbuffer
bf9edc24
RG
571 * `topQueries(20)`: shows the top-20 queries
572 * `topQueries(20,2)`: shows the top-20 two-level domain queries (so `topQueries(20,1)` only shows TLDs)
573 * `topResponses(20, 2)`: top-20 servfail responses (use ,3 for NXDOMAIN)
2a05b4a9 574 * `topSlow([top][, limit][, labels])`: show `top` queries slower than `limit` milliseconds, grouped by last `labels` labels
c9262563 575
ee52e6fa
RG
576For example:
577```
578> grepq("127.0.0.1/24")
40df1b89
RG
579Time Client Server ID Name Type Lat. TC RD AA Rcode
580-11.9 127.0.0.1:52599 16127 nxdomain.powerdns.com. A RD Question
581-11.7 127.0.0.1:52599 127.0.0.1:53 16127 nxdomain.powerdns.com. A 175.6 RD Non-Existent domain
ee52e6fa 582> grepq("powerdns.com")
40df1b89
RG
583Time Client Server ID Name Type Lat. TC RD AA Rcode
584-38.7 127.0.0.1:52599 16127 nxdomain.powerdns.com. A RD Question
585-38.6 127.0.0.1:52599 127.0.0.1:53 16127 nxdomain.powerdns.com. A 175.6 RD Non-Existent domain
ee52e6fa 586```
7c0860e1 587
178c03ce 588Live histogram of latency
589-------------------------
590```
591> showResponseLatency()
8a47f4c5 592Average response latency: 78.84 msec
178c03ce 593 msec
594 0.10
595 0.20 .
596 0.40 **********************
597 0.80 ***********
598 1.60 .
599 3.20
600 6.40 .
601 12.80 *
602 25.60 *
603 51.20 *
604 102.40 **********************************************************************
605 204.80 *************************
606 409.60 **
607 819.20 :
6081638.40 .
609```
610
611Where : stands for 'half a star' and . for 'less than half a star, but
612something was there'.
613
7c0860e1 614Per domain or subnet QPS limiting
615---------------------------------
616If certain domains or source addresses are generating onerous amounts of
617traffic, you can put ceilings on the amount of traffic you are willing to
618forward:
619
620```
621> addQPSLimit("h4xorbooter.xyz.", 10)
622> addQPSLimit({"130.161.0.0/16", "145.14.0.0/16"} , 20)
623> addQPSLimit({"nl.", "be."}, 1)
0940e4eb 624> showRules()
625# Matches Rule Action
6260 0 h4xorbooter.xyz. qps limit to 10
6271 0 130.161.0.0/16, 145.14.0.0/16 qps limit to 20
6282 0 nl., be. qps limit to 1
7c0860e1 629```
630
0940e4eb 631To delete a limit (or a rule in general):
7c0860e1 632```
0940e4eb 633> rmRule(1)
634> showRules()
635# Matches Rule Action
6360 0 h4xorbooter.xyz. qps limit to 10
6371 0 nl., be. qps limit to 1
7c0860e1 638```
639
947f59ea 640Delaying answers
641----------------
642Sometimes, runaway scripts will hammer your servers with back-to-back
643queries. While it is possible to drop such packets, this may paradoxically
644lead to more traffic.
645
646An attractive middleground is to delay answers to such back-to-back queries,
647causing a slowdown on the side of the source of the traffic.
648
649To do so, use:
650```
651> addDelay("yourdomain.in.ua.", 500)
652> addDelay({"65.55.37.0/24"}, 500)
653```
654This will delay responses for questions to the mentioned domain, or coming
655from the configured subnet, by half a second.
656
657Like the QPSLimits and other rules, the delaying instructions can be
658inspected or edited using showRule(), rmRule(), topRule(), mvRule() etc.
659
2d1d4a16 660Dynamic load balancing
661----------------------
5efb31db
RG
662The default load balancing policy is called `leastOutstanding`, which means
663we pick the server with the least queries 'in the air' (and within those,
664the one with the lowest `order`, and within those, the one with the lowest latency).
c9262563 665
5efb31db
RG
666Another policy, `firstAvailable`, picks the server with the lowest `order` that has not
667exceeded its QPS limit. For now this is the only policy using the QPS limit.
c9262563 668
5efb31db
RG
669A further policy, `wrandom` assigns queries randomly, but based on the
670`weight` parameter passed to `newServer`. `whashed` is a similar weighted policy,
a7f3108c 671but assigns questions with identical hash to identical servers, allowing for
672better cache concentration ('sticky queries').
c9262563 673
674If you don't like the default policies you can create your own, like this
675for example:
773470ca 676
677```
678counter=0
497a6e3a 679function luaroundrobin(servers, dq)
a6c02c23 680 counter=counter+1
773470ca 681 return servers[1+(counter % #servers)]
682end
683
22b2b326 684setServerPolicyLua("luaroundrobin", luaroundrobin)
773470ca 685```
686
5f504638 687Incidentally, this is similar to setting: `setServerPolicy(roundrobin)`
688which uses the C++ based roundrobin policy.
689
6bb62841 690Lua server policies
691-------------------
692If the built in rules do not suffice to pick a server pool, full flexibility is available from Lua. For example:
75a2db75 693
694```
6bb62841 695newServer("192.168.1.2")
696newServer({address="8.8.4.4", pool="numbered"})
75a2db75 697
497a6e3a 698function splitSetup(servers, dq)
6bb62841 699 if(string.match(dq.qname:toString(), "%d"))
700 then
701 print("numbered pool")
702 return leastOutstanding.policy(getPoolServers("numbered"), dq)
703 else
704 print("standard pool")
705 return leastOutstanding.policy(servers, dq)
706 end
75a2db75 707end
c9262563 708
22b2b326 709setServerPolicyLua("splitsetup", splitSetup)
75a2db75 710```
711
6bb62841 712This will forward queries containing a number to the pool of "numbered"
0940e4eb 713servers, and will apply the default load balancing policy to all other
714queries.
75a2db75 715
60d836d0 716Dynamic Rule Generation
717-----------------------
718To set dynamic rules, based on recent traffic, define a function called `maintenance()` in Lua. It will
719get called every second, and from this function you can set rules to block traffic based on statistics.
720
721As an example:
722
723```
724function maintenance()
725 addDynBlocks(exceedQRate(20, 10), "Exceeded query rate", 60)
726end
727```
728
729This will dynamically block all hosts that exceeded 20 queries/s as measured
730over the past 10 seconds, and the dynamic block will last for 60 seconds.
731
732Dynamic blocks in force are displayed with `showDynBlocks()` and can be cleared
733with `clearDynBlocks()`. Full set of `exceed` functions is listed in the table of
734all functions below.
735
736
8c732ebf 737Running it for real
738-------------------
739First run on the command line, and generate a key:
740
741```
021e3aba 742# dnsdist
8c732ebf 743> makeKey()
744setKey("sepuCcHcQnSAZgNbNPCCpDWbujZ5esZJmrt/wh6ldkQ=")
745```
021e3aba 746
fa7d3e7c 747Now add this setKey line to `dnsdistconf.lua`, and also add:
8c732ebf 748
fa7d3e7c 749```
750controlSocket("0.0.0.0") -- or add portnumber too
751```
8c732ebf 752
fa7d3e7c 753Then start `dnsdist` as a daemon, and then connect to it:
8c732ebf 754```
021e3aba 755# dnsdist --daemon
8c732ebf 756# dnsdist --client
757>
758```
fa7d3e7c 759
107d4911
RG
760Please note that, without libsodium support, 'makeKey()' will return
761setKey("plaintext") and the communication between the client and the
762server will not be encrypted.
763
6d69b621
RG
764Some versions of libedit, notably the CentOS 6 one, may require the following
765addition to ~/.editrc in order to support searching through the history:
766
767```
768bind "^R" em-inc-search-prev
769```
770
a40df301 771ACL, who can use dnsdist
772------------------------
ee52e6fa 773For safety reasons, by default only private networks can use `dnsdist`, see below
a40df301 774how to query and change the ACL:
775
776```
777> showACL()
778127.0.0.0/8
77910.0.0.0/8
780(...)
781::1/128
782fc00::/7
783fe80::/10
784> addACL("130.161.0.0/16")
785> setACL({"::/0"}) -- resets the list to this array
786> showACL()
787::/0
788```
8a47f4c5 789
886e2cf2
RG
790Caching
791-------
886e2cf2
RG
792`dnsdist` implements a simple but effective packet cache, not enabled by default.
793It is enabled per-pool, but the same cache can be shared between several pools.
794The first step is to define a cache, then to assign that cache to the chosen pool,
795the default one being represented by the empty string:
796
797```
cc8cefe1 798pc = newPacketCache(10000, 86400, 0, 60, 60)
886e2cf2
RG
799getPool(""):setCache(pc)
800```
801
1ea747c0
RG
802The first parameter is the maximum number of entries stored in the cache, and is the
803only one required. All the others parameters are optional and in seconds.
804The second one is the maximum lifetime of an entry in the cache, the third one is
805the minimum TTL an entry should have to be considered for insertion in the cache,
806the fourth one is the TTL used for a Server Failure response. The last one is the
807TTL that will be used when a stale cache entry is returned.
808
809The `setStaleCacheEntriesTTL(n)` directive can be used to allow `dnsdist` to use
810expired entries from the cache when no backend is available. Only entries that have
811expired for less than `n` seconds will be used, and the returned TTL can be set
812when creating a new cache with `newPacketCache()`.
813
814A reference to the cache affected to a specific pool can be retrieved with:
815
816```
817getPool("poolname"):getCache()
818```
819
f87c4aff
RG
820And removed with:
821
822```
823getPool("poolname"):unsetCache()
824```
825
1ea747c0
RG
826Cache usage stats (hits, misses, deferred inserts and lookups, collisions)
827can be displayed by using the `printStats()` method:
828
829```
830getPool("poolname"):getCache():printStats()
831```
832
833Expired cached entries can be removed from a cache using the `purgeExpired(n)`
834method, which will remove expired entries from the cache until at least `n`
835entries remain in the cache. For example, to remove all expired entries:
836
837```
838getPool("poolname"):getCache():purgeExpired(0)
839```
840
841Specific entries can also be removed using the `expungeByName(DNSName [, qtype=ANY])`
842method.
843
844```
845getPool("poolname"):getCache():expungeByName(newDNSName("powerdns.com"), dnsdist.A)
846```
847
848Finally, the `expunge(n)` method will remove all entries until at most `n`
849entries remain in the cache:
850
851```
852getPool("poolname"):getCache():expunge(0)
853```
886e2cf2
RG
854
855
13fe35db
RG
856Performance tuning
857------------------
858First, a few words about `dnsdist` architecture:
859
860 * Each local bind has its own thread listening for incoming UDP queries
861 * and its own thread listening for incoming TCP connections,
862 dispatching them right away to a pool of threads
863 * Each backend has its own thread listening for UDP responses
864 * A maintenance thread calls the `maintenance()` Lua function every second
865 if any, and is responsible for cleaning the cache
866 * A health check thread checks the backends availability
867 * A control thread handles console connections
2e439533 868 * A carbon thread exports statistics to carbon servers if needed
13fe35db
RG
869 * One or more webserver threads handle queries to the internal webserver
870
871The maximum number of threads in the TCP pool is controlled by the
872`setMaxTCPClientThreads()` directive, and defaults to 10. This number can be
873increased to handle a large number of simultaneous TCP connections.
6c1ca990
RG
874If all the TCP threads are busy, new TCP connections are queued while
875they wait to be picked up. The maximum number of queued connections
876can be configured with `setMaxTCPQueuedConnections()`, and any value other
877than 0 (the default) will cause new connections to be dropped if there
878are already too many queued.
13fe35db
RG
879
880When dispatching UDP queries to backend servers, `dnsdist` keeps track of at
881most `n` outstanding queries for each backend. This number `n` can be tuned by
882the `setMaxUDPOutstanding()` directive, defaulting to 10240, with a maximum
883value of 65535. Large installations are advised to increase the default value
884at the cost of a slightly increased memory usage.
885
886Most of the query processing is done in C++ for maximum performance,
887but some operations are executed in Lua for maximum flexibility:
888
889 * the `blockfilter()` function
890 * rules added by `addLuaAction()`
891 * server selection policies defined via `setServerPolicyLua()` or `newServerPolicy()`
892
893While Lua is fast, its use should be restricted to the strict necessary in order
894to achieve maximum performance, it might be worth considering using LuaJIT instead
895of Lua. When Lua inspection is needed, the best course of action is to restrict
896the queries sent to Lua inspection by using `addLuaAction()` instead of inspecting
897all queries in the `blockfilter()` function.
898
899`dnsdist` design choices mean that the processing of UDP queries is done by only
900one thread per local bind. This is great to keep lock contention to a low level,
901but might not be optimal for setups using a lot of processing power, caused for
902example by a large number of complicated rules. To be able to use more CPU cores
903for UDP queries processing, it is possible to use the `reuseport` parameter of
904the `addLocal()` and `setLocal()` directives to be able to add several identical
905local binds to `dnsdist`:
906
907```
908addLocal("192.0.2.1:53", true, true)
909addLocal("192.0.2.1:53", true, true)
910addLocal("192.0.2.1:53", true, true)
911addLocal("192.0.2.1:53", true, true)
912```
913
914`dnsdist` will then add four identical local binds as if they were different IPs
915or ports, start four threads to handle incoming queries and let the kernel load
916balance those randomly to the threads, thus using four CPU cores for rules
917processing. Note that this require SO_REUSEPORT support in the underlying
918operating system (added for example in Linux 3.9).
919Please also be aware that doing so will increase lock contention and might not
920therefore scale linearly. This is especially true for Lua-intensive setups,
921because Lua processing in `dnsdist` is serialized by an unique lock for all
922threads.
923
924Another possibility is to use the reuseport option to run several `dnsdist`
925processes in parallel on the same host, thus avoiding the lock contention issue
926at the cost of having to deal with the fact that the different processes will
927not share informations, like statistics or DDoS offenders.
928
929The UDP threads handling the responses from the backends do not use a lot of CPU,
930but if needed it is also possible to add the same backend several times to the
931`dnsdist` configuration to distribute the load over several responder threads.
932
933```
934newServer({address="192.0.2.127:53", name="Backend1"})
935newServer({address="192.0.2.127:53", name="Backend2"})
936newServer({address="192.0.2.127:53", name="Backend3"})
937newServer({address="192.0.2.127:53", name="Backend4"})
938```
939
940
42fae326 941Carbon/Graphite/Metronome
942-------------------------
943To emit metrics to Graphite, or any other software supporting the Carbon protocol, use:
944```
945carbonServer('ip-address-of-carbon-server', 'ourname', 30)
946```
947
948Where 'ourname' can be used to override your hostname, and '30' is the
949reporting interval in seconds. The last two arguments can be omitted. The
950latest version of [PowerDNS
951Metronome](https://github.com/ahupowerdns/metronome) comes with attractive
ee52e6fa 952graphs for `dnsdist` by default.
42fae326 953
11e1e08b
RG
954DNSCrypt
955--------
956`dnsdist`, when compiled with --enable-dnscrypt, can be used as a DNSCrypt server,
957uncurving queries before forwarding them to downstream servers and curving responses back.
bf9edc24 958To make `dnsdist` listen to incoming DNSCrypt queries on 127.0.0.1 port 8443,
11e1e08b
RG
959with a provider name of "2.providername", using a resolver certificate and associated key
960stored respectively in the `resolver.cert` and `resolver.key` files, the `addDnsCryptBind()`
961directive can be used:
962
963```
964addDNSCryptBind("127.0.0.1:8443", "2.providername", "/path/to/resolver.cert", "/path/to/resolver.key")
965```
966
967To generate the provider and resolver certificates and keys, you can simply do:
968
969```
970> generateDNSCryptProviderKeys("/path/to/providerPublic.key", "/path/to/providerPrivate.key")
b8db58a2 971Provider fingerprint is: E1D7:2108:9A59:BF8D:F101:16FA:ED5E:EA6A:9F6C:C78F:7F91:AF6B:027E:62F4:69C3:B1AA
11e1e08b
RG
972> generateDNSCryptCertificate("/path/to/providerPrivate.key", "/path/to/resolver.cert", "/path/to/resolver.key", serial, validFrom, validUntil)
973```
974
975Ideally, the certificates and keys should be generated on an offline dedicated hardware and not on the resolver.
976The resolver key should be regularly rotated and should never touch persistent storage, being stored in a tmpfs
977with no swap configured.
978
979You can display the currently configured DNSCrypt binds with:
980```
981> showDNSCryptBinds()
982# Address Provider Name Serial Validity P. Serial P. Validity
9830 127.0.0.1:8443 2.name 14 2016-04-10 08:14:15 0 -
984```
985
b8db58a2
RG
986If you forgot to write down the provider fingerprint value after generating the provider keys, you can use `printDNSCryptProviderFingerprint()` to retrieve it later:
987```
988> printDNSCryptProviderFingerprint("/path/to/providerPublic.key")
989Provider fingerprint is: E1D7:2108:9A59:BF8D:F101:16FA:ED5E:EA6A:9F6C:C78F:7F91:AF6B:027E:62F4:69C3:B1AA
990```
991
548c8b66
RG
992AXFR, IXFR and NOTIFY
993---------------------
994When `dnsdist` is deployed in front of a master authoritative server, it might
995receive AXFR or IXFR queries destined to this master. There are two issues
996that can arise in this kind of setup:
997
998 * If the master is part of a pool of servers, the first SOA query can be directed
999 by `dnsdist` to a different server than the following AXFR/IXFR one. If all servers are not
1000 perfectly synchronised at all times, it might to synchronisation issues.
1001 * If the master only allows AXFR/IXFR based on the source address of the requestor,
1002 it might be confused by the fact that the source address will be the one from
1003 the `dnsdist` server.
1004
1005The first issue can be solved by routing SOA, AXFR and IXFR requests explicitely
1006to the master:
1007
1008```
1009> newServer({address="192.168.1.2", name="master", pool={"master", "otherpool"}})
1010> addAction(OrRule({QTypeRule(dnsdist.SOA), QTypeRule(dnsdist.AXFR), QTypeRule(dnsdist.IXFR)}), PoolAction("master"))
1011```
1012
1013The second one might requires allowing AXFR/IXFR from the `dnsdist` source address
1014and moving the source address check on `dnsdist`'s side:
1015
1016```
1017> addAction(AndRule({OrRule({QTypeRule(dnsdist.AXFR), QTypeRule(dnsdist.IXFR)}), NotRule(makeRule("192.168.1.0/24"))}), RCodeAction(dnsdist.REFUSED))
1018```
1019
1020When `dnsdist` is deployed in front of slaves, however, an issue might arise with NOTIFY
1021queries, because the slave will receive a notification coming from the `dnsdist` address,
1022and not the master's one. One way to fix this issue is to allow NOTIFY from the `dnsdist`
1023address on the slave side (for example with PowerDNS's `trusted-notification-proxy`) and
1024move the address check on `dnsdist`'s side:
1025
1026```
1027> addAction(AndRule({OpcodeRule(DNSOpcode.Notify), NotRule(makeRule("192.168.1.0/24"))}), RCodeAction(dnsdist.REFUSED))
1028```
1029
87b515ed
RG
1030eBPF Socket Filtering
1031---------------------
1032`dnsdist` can use eBPF socket filtering on recent Linux kernels (4.1+) built with eBPF
1033support (`CONFIG_BPF`, `CONFIG_BPF_SYSCALL`, ideally `CONFIG_BPF_JIT`).
d45189b7 1034This feature might require an increase of the memory limit associated to a socket, via
87b515ed
RG
1035`the sysctl` setting `net.core.optmem_max`. When attaching an eBPF program to a socket,
1036the size of the program is checked against this limit, and the default value might not be
1037enough. Large map sizes might also require an increase of `RLIMIT_MEMLOCK`.
1038
1039This feature allows `dnsdist` to ask the kernel to discard incoming packets in kernel-space
1040instead of them being copied to userspace just to be dropped, thus being a lot of faster.
1041
1042The BPF filter can be used to block incoming queries manually:
1043
1044```
1045> bpf = newBPFFilter(1024, 1024, 1024)
1046> bpf:attachToAllBinds()
d45189b7 1047> bpf:block(newCA("2001:DB8::42"))
87b515ed
RG
1048> bpf:blockQName(newDNSName("evildomain.com"), 255)
1049> bpf:getStats()
1050[2001:DB8::42]: 0
1051evildomain.com. 255: 0
d45189b7 1052> bpf:unblock(newCA("2001:DB8::42"))
87b515ed
RG
1053> bpf:unblockQName(newDNSName("evildomain.com"), 255)
1054> bpf:getStats()
1055>
1056```
1057
1058The `blockQName()` method can be used to block queries based on the exact qname supplied,
d45189b7
RG
1059in a case-insensitive way, and an optional qtype. Using the 255 (ANY) qtype will block all
1060queries for the qname, regardless of the qtype.
1061Contrary to source address filtering, qname filtering only works over UDP. TCP qname
1062filtering can be done the usual way:
87b515ed
RG
1063
1064```
1065> addAction(AndRule({TCPRule(true), makeRule("evildomain.com")}), DropAction())
1066```
1067
1068The `attachToAllBinds()` method attach the filter to every existing binds at runtime,
1069but it's also possible to define a default BPF filter at configuration time, so that
1070it's automatically attached to every binds:
1071
1072```
1073bpf = newBPFFilter(1024, 1024, 1024)
1074setDefaultBPFFilter(bpf)
1075```
1076
1077Finally, it's also possible to attach it to only specific binds at runtime:
1078
1079```
1080> bpf = newBPFFilter(1024, 1024, 1024)
1081> showBinds()
1082# Address Protocol Queries
10830 [::]:53 UDP 0
10841 [::]:53 TCP 0
1085> bd = getBind(0)
1086> bd:attachFilter(bpf)
1087```
1088
1089`dnsdist` also supports adding dynamic, expiring blocks to a BPF filter:
1090
1091```
1092bpf = newBPFFilter(1024, 1024, 1024)
1093setDefaultBPFFilter(bpf)
1094dbpf = newDynBPFFilter(bpf)
1095function maintenance()
1096 addBPFFilterDynBlocks(exceedQRate(20, 10), dbpf, 60)
1097 dbpf:purgeExpired()
1098end
1099```
1100
1101This will dynamically block all hosts that exceeded 20 queries/s as measured
1102over the past 10 seconds, and the dynamic block will last for 60 seconds.
1103
d45189b7
RG
1104This feature has been successfully tested on Arch Linux, Arch Linux ARM,
1105Fedora Core 23 and Ubuntu Xenial.
548c8b66 1106
8a47f4c5 1107All functions and types
1108-----------------------
1109Within `dnsdist` several core object types exist:
caec2956 1110
8a47f4c5 1111 * Server: generated with newServer, represents a downstream server
1112 * ComboAddress: represents an IP address and port
1113 * DNSName: represents a domain name
1114 * NetmaskGroup: represents a group of netmasks
1115 * QPSLimiter: implements a QPS-based filter
1116 * SuffixMatchNode: represents a group of domain suffixes for rapid testing of membership
1117 * DNSHeader: represents the header of a DNS packet
1118
1119The existence of most of these objects can mostly be ignored, unless you
1120plan to write your own hooks and policies, but it helps to understand an
1121expressions like:
1122
1123```
1124> getServer(0).order=12 -- set order of server 0 to 12
1125> getServer(0):addPool("abuse") -- add this server to the abuse pool
1126```
1127The '.' means 'order' is a data member, while the ':' meand addPool is a member function.
1128
1129Here are all functions:
1130
0940e4eb 1131 * Practical
caec2956
PL
1132 * `shutdown()`: shut down `dnsdist`
1133 * quit or ^D: exit the console
002decab 1134 * `webserver(address:port, password [, apiKey [, customHeaders ]])`: launch a webserver with stats on that address with that password
8a47f4c5 1135 * ACL related:
caec2956
PL
1136 * `addACL(netmask)`: add to the ACL set who can use this server
1137 * `setACL({netmask, netmask})`: replace the ACL set with these netmasks. Use `setACL({})` to reset the list, meaning no one can use us
1138 * `showACL()`: show our ACL set
87b515ed
RG
1139 * ClientState related:
1140 * function `showBinds()`: list every local binds
1141 * function `getBind(n)`: return the corresponding `ClientState` object
1142 * member `attachFilter(BPFFilter)`: attach a BPF Filter to this bind
1143 * member `toString()`: print the address this bind listens to
5949b95b 1144 * Network related:
4c34246d
RG
1145 * `addLocal(netmask, [false], [false])`: add to addresses we listen on. Second optional parameter sets TCP/IP or not. Third optional parameter sets SO_REUSEPORT when available.
1146 * `setLocal(netmask, [false], [false])`: reset list of addresses we listen on to this address. Second optional parameter sets TCP/IP or not. Third optional parameter sets SO_REUSEPORT when available.
8a47f4c5 1147 * Blocking related:
caec2956 1148 * `addDomainBlock(domain)`: block queries within this domain
42fae326 1149 * Carbon/Graphite/Metronome statistics related:
caec2956 1150 * `carbonServer(serverIP, [ourname], [interval])`: report statistics to serverIP using our hostname, or 'ourname' if provided, every 'interval' seconds
8a47f4c5 1151 * Control socket related:
caec2956
PL
1152 * `makeKey()`: generate a new server access key, emit configuration line ready for pasting
1153 * `setKey(key)`: set access key to that key.
1154 * `testCrypto()`: test of the crypto all works
1155 * `controlSocket(addr)`: open a control socket on this address / connect to this address in client mode
8a47f4c5 1156 * Diagnostics and statistics
caec2956
PL
1157 * `dumpStats()`: print all statistics we gather
1158 * `grepq(Netmask|DNS Name|100ms [, n])`: shows the last n queries and responses matching the specified client address or range (Netmask), or the specified DNS Name, or slower than 100ms
1159 * `grepq({"::1", "powerdns.com", "100ms"} [, n])`: shows the last n queries and responses matching the specified client address AND range (Netmask) AND the specified DNS Name AND slower than 100ms
1160 * `topQueries(n[, labels])`: show top 'n' queries, as grouped when optionally cut down to 'labels' labels
1161 * `topResponses(n, kind[, labels])`: show top 'n' responses with RCODE=kind (0=NO Error, 2=ServFail, 3=ServFail), as grouped when optionally cut down to 'labels' labels
1162 * `topSlow([top][, limit][, labels])`: show `top` queries slower than `limit` milliseconds, grouped by last `labels` labels
1163 * `topBandwidth(top)`: show top-`top` clients that consume the most bandwidth over length of ringbuffer
2e439533 1164 * `topClients(n)`: show top-`n` clients sending the most queries over length of ringbuffer
caec2956 1165 * `showResponseLatency()`: show a plot of the response time latency distribution
537524f8 1166 * Logging related
caec2956
PL
1167 * `infolog(string)`: log at level info
1168 * `warnlog(string)`: log at level warning
1169 * `errlog(string)`: log at level error
fd23d9bb 1170 * `setVerboseHealthChecks(bool)`: set whether health check errors will be logged
8a47f4c5 1171 * Server related:
caec2956 1172 * `newServer("ip:port")`: instantiate a new downstream server with default settings
9e87dcb8 1173 * `newServer({address="ip:port", qps=1000, order=1, weight=10, pool="abuse", retries=5, tcpSendTimeout=30, tcpRecvTimeout=30, checkName="a.root-servers.net.", checkType="A", maxCheckFailures=1, mustResolve=false, useClientSubnet=true, source="address|interface name|address@interface"})`:
66407d9e 1174instantiate a server with additional parameters
caec2956
PL
1175 * `showServers()`: output all servers
1176 * `getServer(n)`: returns server with index n
1177 * `getServers()`: returns a table with all defined servers
1178 * `rmServer(n)`: remove server with index n
1179 * `rmServer(server)`: remove this server object
8a47f4c5 1180 * Server member functions:
caec2956 1181 * `addPool(pool)`: add this server to that pool
46a839bf
RG
1182 * `getName()`: return the server name if any
1183 * `getNameWithAddr()`: return a string containing the server name if any plus the server address and port
caec2956
PL
1184 * `getOutstanding()`: this *returns* the number of outstanding queries (doesn't print it!)
1185 * `rmPool(pool)`: remove server from that pool
1186 * `setQPS(n)`: set the QPS setting to n
1187 * `setAuto()`: set this server to automatic availability testing
1188 * `setDown()`: force this server to be down
1189 * `setUp()`: force this server to be UP
1190 * `isUp()`: if this server is available
8a47f4c5 1191 * Server member data:
caec2956 1192 * `upStatus`: if `dnsdist` considers this server available (overridden by `setDown()` and `setUp()`)
46a839bf 1193 * `name`: name of the server
caec2956
PL
1194 * `order`: order of this server in order-based server selection policies
1195 * `weight`: weight of this server in weighted server selection policies
0940e4eb 1196 * Rule related:
caec2956
PL
1197 * `AllRule()`: matches all traffic
1198 * `AndRule()`: matches if all sub-rules matches
1199 * `DNSSECRule()`: matches queries with the DO flag set
1200 * `MaxQPSIPRule(qps, v4Mask=32, v6Mask=64)`: matches traffic exceeding the qps limit per subnet
20357a9a 1201 * `MaxQPSRule(qps)`: matches traffic **not** exceeding this qps limit
caec2956
PL
1202 * `NetmaskGroupRule()`: matches traffic from the specified network range
1203 * `NotRule()`: matches if the sub-rule does not match
1204 * `OrRule()`: matches if at least one of the sub-rules matches
55baa1f2 1205 * `OpcodeRule()`: matches queries with the specified opcode
caec2956
PL
1206 * `QClassRule(qclass)`: matches queries with the specified qclass (numeric)
1207 * `QTypeRule(qtype)`: matches queries with the specified qtype
1208 * `RegexRule(regex)`: matches the query name against the supplied regex
55baa1f2
RG
1209 * `RecordsCountRule(section, minCount, maxCount)`: matches if there is at least `minCount` and at most `maxCount` records in the `section` section
1210 * `RecordsTypeCountRule(section, type, minCount, maxCount)`: matches if there is at least `minCount` and at most `maxCount` records of type `type` in the `section` section
1211 * `RE2Rule(regex)`: matches the query name against the supplied regex using the RE2 engine
291729f3 1212 * `SuffixMatchNodeRule(smn, [quiet-bool])`: 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.
caec2956 1213 * `TCPRule(tcp)`: matches question received over TCP if `tcp` is true, over UDP otherwise
55baa1f2 1214 * `TrailingDataRule()`: matches if the query has trailing data
ee52e6fa 1215 * Rule management related:
379de8b0 1216 * `getAction(num)`: returns the Action associate with rule 'num'.
caec2956 1217 * `showRules()`: show all defined rules (Pool, Block, QPS, addAnyTCRule)
d4d5c5c3
RG
1218 * `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,
1219 in which case the rule will be moved to the last position.
caec2956 1220 * `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,
0940e4eb 1221 in which case the rule will be moved to the last position.
d4d5c5c3
RG
1222 * `rmResponseRule(n)`: remove response rule n
1223 * `rmRule(n)`: remove rule n
1224 * `topResponseRule()`: move the last response rule to the first position
caec2956 1225 * `topRule()`: move the last rule to the first position
8e50d605 1226 * Built-in Actions for Rules:
caec2956 1227 * `AllowAction()`: let these packets go through
b1bec9f0 1228 * `DelayAction(milliseconds)`: delay the response by the specified amount of milliseconds (UDP-only)
caec2956
PL
1229 * `DisableValidationAction()`: set the CD bit in the question, let it go through
1230 * `DropAction()`: drop these packets
18029431 1231 * `LogAction([filename], [binary])`: 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
caec2956 1232 * `NoRecurseAction()`: strip RD bit from the question, let it go through
b1bec9f0 1233 * `PoolAction(poolname)`: set the packet into the specified pool
20357a9a 1234 * `QPSPoolAction(maxqps, poolname)`: set the packet into the specified pool only if it **does not** exceed the specified QPS limits, letting the subsequent rules apply otherwise
b1bec9f0
RG
1235 * `QPSAction(rule, maxqps)`: drop these packets if the QPS limits are exceeded
1236 * `RCodeAction(rcode)`: reply immediatly by turning the query into a response with the specified rcode
27dfcc14
RG
1237 * `RemoteLogAction(RemoteLogger)`: send the content of this query to a remote logger via Protocol Buffer
1238 * `RemoteLogResponseAction(RemoteLogger)`: send the content of this response to a remote logger via Protocol Buffer
886e2cf2 1239 * `SkipCacheAction()`: don't lookup the cache for this query, don't store the answer
7b9d167c 1240 * `SpoofAction(ip[, ip])` or `SpoofAction({ip, ip, ..}): forge a response with the specified IPv4 (for an A query) or IPv6 (for an AAAA). If you specify multiple addresses, all that match the query type (A, AAAA or ANY) will get spoofed in
b1bec9f0 1241 * `SpoofCNAMEAction(cname)`: forge a response with the specified CNAME value
caec2956 1242 * `TCAction()`: create answer to query with TC and RD bits set, to move to TCP/IP
379de8b0 1243 * `TeeAction(remote)`: send copy of query to remote, keep stats on responses
b4fd86c3 1244 * Specialist rule generators
caec2956 1245 * `addAnyTCRule()`: generate TC=1 answers to ANY queries received over UDP, moving them to TCP
7b9d167c 1246 * `addDomainSpoof(domain, ip[, ip6])` or `addDomainSpoof(domain, {IP, IP, IP..})`: generate answers for A/AAAA/ANY queries using the ip parameters
caec2956
PL
1247 * `addDomainCNAMESpoof(domain, cname)`: generate CNAME answers for queries using the specified value
1248 * `addDisableValidationRule(domain)`: set the CD flags to 1 for all queries matching the specified domain
1249 * `addNoRecurseRule(domain)`: clear the RD flag for all queries matching the specified domain
1250 * `setDNSSECPool()`: move queries requesting DNSSEC processing to this pool
ee52e6fa 1251 * Policy member data:
caec2956
PL
1252 * `name`: the policy name
1253 * `policy`: the policy function
8a47f4c5 1254 * Pool related:
caec2956
PL
1255 * `addPoolRule(domain, pool)`: send queries to this domain to that pool
1256 * `addPoolRule({domain, domain}, pool)`: send queries to these domains to that pool
1257 * `addPoolRule(netmask, pool)`: send queries to this netmask to that pool
1258 * `addPoolRule({netmask, netmask}, pool)`: send queries to these netmasks to that pool
20357a9a 1259 * `addQPSPoolRule(x, limit, pool)`: like `addPoolRule`, but only select at most 'limit' queries/s for this pool, letting the subsequent rules apply otherwise
886e2cf2 1260 * `getPool(poolname)`: return the ServerPool named `poolname`
caec2956 1261 * `getPoolServers(pool)`: return servers part of this pool
886e2cf2 1262 * `showPools()`: list the current server pools
d8d85a30 1263 * Lua Action related:
caec2956 1264 * `addLuaAction(x, func)`: where 'x' is all the combinations from `addPoolRule`, and func is a
f659cc0c
PL
1265 function with the parameter `dq`, which returns an action to be taken on this packet.
1266 Good for rare packets but where you want to do a lot of processing.
8a47f4c5 1267 * Server selection policy related:
caec2956
PL
1268 * `setServerPolicy(policy)`: set server selection policy to that policy
1269 * `setServerPolicyLua(name, function)`: set server selection policy to one named 'name' and provided by 'function'
1270 * `showServerPolicy()`: show name of currently operational server selection policy
1271 * `newServerPolicy(name, function)`: create a policy object from a Lua function
8a47f4c5 1272 * Available policies:
caec2956
PL
1273 * `firstAvailable`: Pick first server that has not exceeded its QPS limit, ordered by the server 'order' parameter
1274 * `whashed`: Weighted hashed ('sticky') distribution over available servers, based on the server 'weight' parameter
1275 * `wrandom`: Weighted random over available servers, based on the server 'weight' parameter
1276 * `roundrobin`: Simple round robin over available servers
1277 * `leastOutstanding`: Send traffic to downstream server with least outstanding queries, with the lowest 'order', and within that the lowest recent latency
537524f8 1278 * Shaping related:
caec2956
PL
1279 * `addQPSLimit(domain, n)`: limit queries within that domain to n per second
1280 * `addQPSLimit({domain, domain}, n)`: limit queries within those domains (together) to n per second
1281 * `addQPSLimit(netmask, n)`: limit queries within that netmask to n per second
1282 * `addQPSLimit({netmask, netmask}, n)`: limit queries within those netmasks (together) to n per second
947f59ea 1283 * Delaying related:
caec2956
PL
1284 * `addDelay(domain, n)`: delay answers within that domain by n milliseconds
1285 * `addDelay({domain, domain}, n)`: delay answers within those domains (together) by n milliseconds
1286 * `addDelay(netmask, n)`: delay answers within that netmask by n milliseconds
1287 * `addDelay({netmask, netmask}, n)`: delay answers within those netmasks (together) by n milliseconds
6ad8b29a 1288 * Answer changing functions:
caec2956
PL
1289 * `truncateTC(bool)`: if set (default) truncate TC=1 answers so they are actually empty. Fixes an issue for PowerDNS Authoritative Server 2.9.22.
1290 * `fixupCase(bool)`: if set (default to no), rewrite the first qname of the question part of the answer to match the one from the query. It is only useful when you have a downstream server that messes up the case of the question qname in the answer
e35d713e 1291 * Dynamic Block related:
caec2956
PL
1292 * `maintenance()`: called every second by dnsdist if defined, call functions below from it
1293 * `clearDynBlocks()`: clear all dynamic blocks
1294 * `showDynBlocks()`: show dynamic blocks in force
1295 * `addDynBlocks(addresses, message[, seconds])`: block the set of addresses with message `msg`, for `seconds` seconds (10 by default)
87b515ed 1296 * `addBPFFilterDynBlocks(addresses, DynBPFFilter[, seconds])`: block the set of addresses using the supplied BPF Filter, for `seconds` seconds (10 by default)
caec2956
PL
1297 * `exceedServFails(rate, seconds)`: get set of addresses that exceed `rate` servails/s over `seconds` seconds
1298 * `exceedNXDOMAINs(rate, seconds)`: get set of addresses that exceed `rate` NXDOMAIN/s over `seconds` seconds
1299 * `exceedRespByterate(rate, seconds)`: get set of addresses that exeeded `rate` bytes/s answers over `seconds` seconds
1300 * `exceedQRate(rate, seconds)`: get set of address that exceed `rate` queries/s over `seconds` seconds
1301 * `exceedQTypeRate(type, rate, seconds)`: get set of address that exceed `rate` queries/s for queries of type `type` over `seconds` seconds
886e2cf2
RG
1302 * ServerPool related:
1303 * `getCache()`: return the current packet cache, if any
1304 * `setCache(PacketCache)`: set the cache for this pool
f87c4aff 1305 * `unsetCache()`: remove the packet cache from this pool
886e2cf2 1306 * PacketCache related:
4275aaba
RG
1307 * `expunge(n)`: remove entries from the cache, leaving at most `n` entries
1308 * `expungeByName(DNSName [, qtype=ANY])`: remove entries matching the supplied DNSName and type from the cache
886e2cf2 1309 * `isFull()`: return true if the cache has reached the maximum number of entries
cc8cefe1 1310 * `newPacketCache(maxEntries[, maxTTL=86400, minTTL=0, servFailTTL=60, stateTTL=60])`: return a new PacketCache
886e2cf2 1311 * `printStats()`: print the cache stats (hits, misses, deferred lookups and deferred inserts)
4275aaba 1312 * `purgeExpired(n)`: remove expired entries from the cache until there is at most `n` entries remaining in the cache
886e2cf2 1313 * `toString()`: return the number of entries in the Packet Cache, and the maximum number of entries
8a47f4c5 1314 * Advanced functions for writing your own policies and hooks
caec2956
PL
1315 * ComboAddress related:
1316 * `newCA(address)`: return a new ComboAddress
1317 * `getPort()`: return the port number
1318 * `tostring()`: return in human-friendly format
1319 * `toString()`: alias for `tostring()`
1320 * `tostringWithPort()`: return in human-friendly format, with port number
1321 * `toStringWithPort()`: alias for `tostringWithPort()`
1322 * DNSName related:
1323 * `newDNSName(name)`: make a DNSName based on this .-terminated name
1324 * member `isPartOf(dnsname)`: is this dnsname part of that dnsname
1325 * member `tostring()`: return as a human friendly . terminated string
1326 * member `toString()`: alias for `tostring()`
1327 * DNSQuestion related:
1328 * member `dh`: DNSHeader
1329 * member `len`: the question length
1330 * member `localaddr`: ComboAddress of the local bind this question was received on
55baa1f2 1331 * member `opcode`: the question opcode
caec2956
PL
1332 * member `qname`: DNSName of this question
1333 * member `qclass`: QClass (as an unsigned integer) of this question
1334 * member `qtype`: QType (as an unsigned integer) of this question
1335 * member `remoteaddr`: ComboAddress of the remote client
1336 * member `rcode`: RCode of this question
1337 * member `size`: the total size of the buffer starting at `dh`
a14c7f7b 1338 * member `skipCache`: whether to skip cache lookup / storing the answer for this question (settable)
caec2956
PL
1339 * member `tcp`: whether this question was received over a TCP socket
1340 * DNSHeader related
1341 * member `getRD()`: get recursion desired flag
1342 * member `setRD(bool)`: set recursion desired flag
1343 * member `setTC(bool)`: set truncation flag (TC)
1344 * member `setQR(bool)`: set Query Response flag (setQR(true) indicates an *answer* packet)
1345 * member `getCD()`: get checking disabled flag
1346 * member `setCD(bool)`: set checking disabled flag
1347 * NetmaskGroup related
1348 * function `newNMG()`: returns a NetmaskGroup
1349 * member `addMask(mask)`: adds `mask` to the NetmaskGroup
1350 * member `match(ComboAddress)`: checks if ComboAddress is matched by this NetmaskGroup
1351 * member `clear()`: clears the NetmaskGroup
1352 * member `size()`: returns number of netmasks in this NetmaskGroup
1353 * QPSLimiter related:
1354 * `newQPSLimiter(rate, burst)`: configure a QPS limiter with that rate and that burst capacity
1355 * member `check()`: check if this QPSLimiter has a token for us. If yes, you must use it.
1356 * SuffixMatchNode related:
1357 * `newSuffixMatchNode()`: returns a new SuffixMatchNode
1358 * member `check(DNSName)`: returns true if DNSName is matched by this group
1359 * member `add(DNSName)`: add this DNSName to the node
e41f8165 1360 * Tuning related:
caec2956
PL
1361 * `setTCPRecvTimeout(n)`: set the read timeout on TCP connections from the client, in seconds
1362 * `setTCPSendTimeout(n)`: set the write timeout on TCP connections from the client, in seconds
1363 * `setMaxTCPClientThreads(n)`: set the maximum of TCP client threads, handling TCP connections
6c1ca990 1364 * `setMaxTCPQueuedConnections(n)`: set the maximum number of TCP connections queued (waiting to be picked up by a client thread)
13fe35db 1365 * `setMaxUDPOutstanding(n)`: set the maximum number of outstanding UDP queries to a given backend server. This can only be set at configuration time and defaults to 10240
19109f73 1366 * `setCacheCleaningDelay(n)`: set the interval in seconds between two runs of the cache cleaning algorithm, removing expired entries
1ea747c0 1367 * `setStaleCacheEntriesTTL(n)`: allows using cache entries expired for at most `n` seconds when no backend available to answer for a query
bf9edc24 1368 * DNSCrypt related:
4c34246d 1369 * `addDNSCryptBind("127.0.0.1:8443", "provider name", "/path/to/resolver.cert", "/path/to/resolver.key", [false]):` listen to incoming DNSCrypt queries on 127.0.0.1 port 8443, with a provider name of "provider name", using a resolver certificate and associated key stored respectively in the `resolver.cert` and `resolver.key` files. The last optional parameter sets SO_REUSEPORT when available
caec2956
PL
1370 * `generateDNSCryptProviderKeys("/path/to/providerPublic.key", "/path/to/providerPrivate.key"):` generate a new provider keypair
1371 * `generateDNSCryptCertificate("/path/to/providerPrivate.key", "/path/to/resolver.cert", "/path/to/resolver.key", serial, validFrom, validUntil):` generate a new resolver private key and related certificate, valid from the `validFrom` timestamp until the `validUntil` one, signed with the provider private key
1372 * `printDNSCryptProviderFingerprint("/path/to/providerPublic.key")`: display the fingerprint of the provided resolver public key
1373 * `showDNSCryptBinds():`: display the currently configured DNSCrypt binds
87b515ed
RG
1374 * BPFFilter related:
1375 * function `newBPFFilter(maxV4, maxV6, maxQNames)`: return a new eBPF socket filter with a maximum of maxV4 IPv4, maxV6 IPv6 and maxQNames qname entries in the block tables
1376 * function `setDefaultBPFFilter(BPFFilter)`: when used at configuration time, the corresponding BPFFilter will be attached to every binds
1377 * member `attachToAllBinds()`: attach this filter to every binds already defined. This is the run-time equivalent of `setDefaultBPFFilter(bpf)`
1378 * member `block(ComboAddress)`: block this address
1379 * member `blockQName(DNSName [, qtype=255])`: block queries for this exact qname. An optional qtype can be used, default to 255
1380 * member `getStats()`: print the block tables
1381 * member `unblock(ComboAddress)`: unblock this address
1382 * member `unblockQName(DNSName [, qtype=255])`: remove this qname from the block list
1383 * DynBPFFilter related:
1384 * function `newDynBPFFilter(BPFFilter)`: return a new DynBPFFilter object using this BPF Filter
1385 * member `block(ComboAddress[, seconds]): add this address to the underlying BPF Filter for `seconds` seconds (default to 10 seconds)
1386 * member `purgeExpired()`: remove expired entries
27dfcc14 1387 * RemoteLogger related:
ec469dd7 1388 * `newRemoteLogger(address:port [, timeout=2, maxQueuedEntries=100, reconnectWaitTime=1])`: create a Remote Logger object, to use with `RemoteLogAction()` and `RemoteLogResponseAction()`
8a47f4c5 1389
1390All hooks
1391---------
1392`dnsdist` can call Lua per packet if so configured, and will do so with the following hooks:
1393
15e20e4b 1394 * `bool blockFilter(dq)`: if defined, called for every packet. If this
8a47f4c5 1395 returns true, the packet is dropped. If false is returned, `dnsdist` will check if the DNSHeader indicates
1396 the packet is now a query response. If so, `dnsdist` will answer the client directly with the modified packet.
497a6e3a 1397 * `server policy(candidates, DNSQuestion)`: if configured with `setServerPolicyLua()`
8a47f4c5 1398 gets called for every packet. Candidates is a table of potential servers to pick from, ComboAddress is the
1399 address of the requestor, DNSName and qtype describe name and type of query. DNSHeader meanwhile is available for
1400 your inspection.
1401
1402
1a5f0162 1403