]> git.ipfire.org Git - thirdparty/pdns.git/blob - docs/lua-records/functions.rst
dnsdist: Apply suggestions from code review, delint
[thirdparty/pdns.git] / docs / lua-records / functions.rst
1 Preset variables
2 ----------------
3
4 LUA rules run within the same environment as described in
5 :doc:`../modes-of-operation`.
6
7 The Lua snippets can query the following variables:
8
9 Query variables
10 ~~~~~~~~~~~~~~~
11 ``dh``
12 The :class:`DNSHeader` of the received query.
13 ``dnssecOK``
14 A boolean describing if the DNSSEC OK (DO) bit was set in the query.
15 ``ednsPKTSize``
16 The advertised EDNS buffer size.
17 ``qname``
18 The name of the requested record. This is a :class:`DNSName`.
19 ``zone``
20 The zone this LUA record is in. This is a :class:`DNSName`.
21 ``zoneid``
22 The id of the zone. This is an integer.
23 ``tcp``
24 Whether or not the query was received over TCP.
25
26 Client variables
27 ~~~~~~~~~~~~~~~~
28 ``ecswho``
29 The EDNS Client Subnet, should one have been set on the query. Unset
30 otherwise. This is a :class:`Netmask`.
31 ``bestwho``
32 In absence of ECS, this is set to the IP address of requesting resolver.
33 Otherwise set to the network part of the EDNS Client Subnet supplied by the
34 resolver. This is a :class:`ComboAddress`.
35 ``who``
36 IP address of requesting resolver as a :class:`ComboAddress`.
37 ``localwho``
38 IP address (including port) of socket on which the question arrived.
39
40 Functions available
41 -------------------
42
43 Record creation functions
44 ~~~~~~~~~~~~~~~~~~~~~~~~~
45
46 .. function:: ifportup(portnum, addresses[, options])
47
48 Simplistic test to see if an IP address listens on a certain port. This will
49 attempt a TCP connection on port ``portnum`` and consider it available if the
50 connection establishes. No data will be sent or read on that connection. Note
51 that both IPv4 and IPv6 addresses can be tested, but that it is an error to
52 list IPv4 addresses on an AAAA record, or IPv6 addresses on an A record.
53
54 Will return a single address from the set of available addresses. If
55 no address is available, will return a random element of the set of
56 addresses supplied for testing.
57
58 :param int portnum: The port number to test connections to.
59 :param {str} addresses: The list of addresses to check connectivity for.
60 :param options: Table of options for this specific check, see below.
61
62 Various options can be set in the ``options`` parameter:
63
64 - ``selector``: used to pick the address(es) from the list of available addresses. Choices include 'pickclosest', 'random', 'hashed', 'all' (default 'random').
65 - ``backupSelector``: used to pick the address(es) from all addresses if all addresses are down. Choices include 'pickclosest', 'random', 'hashed', 'all' (default 'random').
66 - ``source``: Source address to check from
67 - ``timeout``: Maximum time in seconds that you allow the check to take (default 2)
68
69
70 .. function:: ifurlup(url, addresses[, options])
71
72 More sophisticated test that attempts an actual http(s) connection to
73 ``url``. In addition, a list of sets of IP addresses can be supplied. The
74 first set with at least one available address is selected. The ``selector`` then
75 selects from the subset of available addresses of the selected set.
76 An URL is considered available if the HTTP response code is 200 and optionally if
77 the content matches the ``stringmatch`` option.
78
79 :param string url: The url to retrieve.
80 :param addresses: List of sets of addresses to check the URL on.
81 :param options: Table of options for this specific check, see below.
82
83 Various options can be set in the ``options`` parameter:
84
85 - ``selector``: used to pick the address(es) from the subset of available addresses of the selected set. Choices include 'pickclosest', 'random', 'hashed', 'all' (default 'random').
86 - ``backupSelector``: used to pick the address from all addresses if all addresses are down. Choices include 'pickclosest', 'random', 'hashed', 'all' (default 'random').
87 - ``source``: Source address to check from
88 - ``timeout``: Maximum time in seconds that you allow the check to take (default 2)
89 - ``stringmatch``: check ``url`` for this string, only declare 'up' if found
90 - ``useragent``: Set the HTTP "User-Agent" header in the requests. By default it is set to "PowerDNS Authoritative Server"
91 - ``byteslimit``: Limit the maximum download size to ``byteslimit`` bytes (default 0 meaning no limit).
92
93 An example of a list of address sets:
94
95 .. code-block:: lua
96
97 ifurlup("https://example.com/", { {"192.0.2.20", "203.0.113.4"}, {"203.0.113.2"} })
98
99 .. function:: ifurlextup(groups-of-address-url-pairs[, options])
100
101 Very similar to ``ifurlup``, but the returned IPs are decoupled from their external health check URLs.
102 This is useful when health checking already happens elsewhere, and that state is exposed over HTTP(S).
103 Health checks are considered positive if the HTTP response code is 200 and optionally if the content matches the ``stringmatch`` option.
104
105 Options are identical to those for ``ifurlup``.
106
107 Example:
108
109 .. code-block:: lua
110
111 ifurlextup({{['192.168.0.1']='https://example.com/',['192.168.0.2']='https://example.com/404'}})
112
113 Example with two groups:
114
115 .. code-block:: lua
116
117 ifurlextup({{['192.168.0.1']='https://example.net/404',['192.168.0.2']='https://example.com/404'}, {['192.168.0.3']='https://example.net/'}})"
118
119 The health checker will look up the first two URLs (using normal DNS resolution to find them - whenever possible, use URLs with IPs in them).
120 The 404s will cause the first group of IPs to get marked as down, after which the URL in the second group is tested.
121 The third IP will get marked up assuming ``https://example.net/`` responds with HTTP response code 200.
122
123 .. function:: pickrandom(values)
124
125 Returns a random value from the list supplied.
126
127 :param values: A list of strings such as IPv4 or IPv6 address.
128
129 This function also works for CNAME or TXT records.
130
131 .. function:: pickrandomsample(number, values)
132
133 Returns N random values from the list supplied.
134
135 :param number: Number of values to return
136 :param values: A list of strings such as IPv4 or IPv6 address.
137
138 This function also works for CNAME or TXT records.
139
140 .. function:: pickhashed(values)
141
142 Based on the hash of ``bestwho``, returns a random value from the list supplied.
143
144 :param values: A list of strings such as IPv4 or IPv6 address.
145
146 This function also works for CNAME or TXT records.
147
148 .. function:: pickclosest(addresses)
149
150 Returns IP address deemed closest to the ``bestwho`` IP address.
151
152 :param addresses: A list of strings with the possible IP addresses.
153
154 .. function:: latlon()
155
156 Returns text listing fractional latitude/longitude associated with the ``bestwho`` IP address.
157
158 .. function:: latlonloc()
159
160 Returns text in LOC record format listing latitude/longitude associated with the ``bestwho`` IP address.
161
162 .. function:: closestMagic()
163
164 Suitable for use as a wildcard LUA A record. Will parse the query name which should be in format::
165
166 192-0-2-1.192-0-2-2.198-51-100-1.magic.v4.powerdns.org
167
168 It will then resolve to an A record with the IP address closest to ``bestwho`` from the list
169 of supplied addresses.
170
171 In the ``magic.v4.powerdns.org`` this looks like::
172
173 *.magic.v4.powerdns.org IN LUA A "closestMagic()"
174
175
176 In another zone, a record is then present like this::
177
178 www-balanced.powerdns.org IN CNAME 192-0-2-1.192-0-2-2.198-51-100-1.magic.v4.powerdns.org
179
180 This effectively opens up your server to being a 'geographical load balancer as a service'.
181
182 Performs no uptime checking.
183
184 .. function:: all(values)
185
186 Returns all values.
187
188 :param values: A list of strings such as IPv4 or IPv6 address.
189
190 This function also works for CNAME or TXT records.
191
192 .. function:: view(pairs)
193
194 Shorthand function to implement 'views' for all record types.
195
196 :param pairs: A list of netmask/result pairs.
197
198 An example::
199
200 view.v4.powerdns.org IN LUA A ("view({ "
201 "{ {'192.168.0.0/16'}, {'192.168.1.54'}},"
202 "{ {'0.0.0.0/0'}, {'192.0.2.1'}} "
203 " }) " )
204
205 This will return IP address 192.168.1.54 for queries coming from
206 192.168.0.0/16, and 192.0.2.1 for all other queries.
207
208 This function also works for CNAME or TXT records.
209
210 .. function:: pickwhashed(values)
211
212 Based on the hash of ``bestwho``, returns a string from the list
213 supplied, as weighted by the various ``weight`` parameters.
214 Performs no uptime checking.
215
216 :param values: table of weight, string (such as IPv4 or IPv6 address).
217
218 Because of the hash, the same client keeps getting the same answer, but
219 given sufficient clients, the load is still spread according to the weight
220 factors.
221
222 This function also works for CNAME or TXT records.
223
224 An example::
225
226 mydomain.example.com IN LUA A ("pickwhashed({ "
227 " {15, "192.0.2.1"}, "
228 " {100, "198.51.100.5"} "
229 "}) ")
230
231
232 .. function:: pickwrandom(values)
233
234 Returns a random string from the list supplied, as weighted by the
235 various ``weight`` parameters. Performs no uptime checking.
236
237 :param values: table of weight, string (such as IPv4 or IPv6 address).
238
239 See :func:`pickwhashed` for an example.
240
241 This function also works for CNAME or TXT records.
242
243 Reverse DNS functions
244 ~~~~~~~~~~~~~~~~~~~~~
245
246 .. warning::
247 For :func:`createForward` and :func:`createForward6`, we recommend filtering with :func:`filterForward`, to prevent PowerDNS from generating A/AAAA responses to addresses outside of your network.
248 Not limiting responses like this may, in some situations, help attackers with impersonation and attacks like such as cookie stealing.
249
250 .. function:: createReverse(format, [exceptions])
251
252 Used for generating default hostnames from IPv4 wildcard reverse DNS records, e.g. ``*.0.0.127.in-addr.arpa``
253
254 See :func:`createReverse6` for IPv6 records (ip6.arpa)
255
256 See :func:`createForward` for creating the A records on a wildcard record such as ``*.static.example.com``
257
258 Returns a formatted hostname based on the format string passed.
259
260 :param format: A hostname string to format, for example ``%1%.%2%.%3%.%4%.static.example.com``.
261 :param exceptions: An optional table of overrides. For example ``{['10.10.10.10'] = 'quad10.example.com.'}`` would, when generating a name for IP ``10.10.10.10``, return ``quad10.example.com`` instead of something like ``10.10.10.10.example.com``.
262
263 **Formatting options:**
264
265 - ``%1%`` to ``%4%`` are individual octets
266 - Example record query: ``1.0.0.127.in-addr.arpa``
267 - ``%1%`` = 127
268 - ``%2%`` = 0
269 - ``%3%`` = 0
270 - ``%4%`` = 1
271 - ``%5%`` joins the four decimal octets together with dashes
272 - Example: ``%5%.static.example.com`` is equivalent to ``%1%-%2%-%3%-%4%.static.example.com``
273 - ``%6%`` converts each octet from decimal to hexadecimal and joins them together
274 - Example: A query for ``15.0.0.127.in-addr.arpa``
275 - ``%6`` would be ``7f00000f`` (127 is 7f, and 15 is 0f in hexadecimal)
276
277 Example records::
278
279 *.0.0.127.in-addr.arpa IN LUA PTR "createReverse('%1%.%2%.%3%.%4%.static.example.com')"
280 *.1.0.127.in-addr.arpa IN LUA PTR "createReverse('%5%.static.example.com')"
281 *.2.0.127.in-addr.arpa IN LUA PTR "createReverse('%6%.static.example.com')"
282
283 When queried::
284
285 # -x is syntactic sugar to request the PTR record for an IPv4/v6 address such as 127.0.0.5
286 # Equivalent to dig PTR 5.0.0.127.in-addr.arpa
287 $ dig +short -x 127.0.0.5 @ns1.example.com
288 127.0.0.5.static.example.com.
289 $ dig +short -x 127.0.1.5 @ns1.example.com
290 127-0-0-5.static.example.com.
291 $ dig +short -x 127.0.2.5 @ns1.example.com
292 7f000205.static.example.com.
293
294 .. function:: createForward()
295
296 Used to generate the reverse DNS domains made from :func:`createReverse`
297
298 Generates an A record for a dotted or hexadecimal IPv4 domain (e.g. 127.0.0.1.static.example.com)
299
300 It does not take any parameters, it simply interprets the zone record to find the IP address.
301
302 An example record for zone ``static.example.com``::
303
304 *.static.example.com IN LUA A "createForward()"
305
306 This function supports the forward dotted format (``127.0.0.1.static.example.com``), and the hex format, when prefixed by two ignored characters (``ip40414243.static.example.com``)
307
308 When queried::
309
310 $ dig +short A 127.0.0.5.static.example.com @ns1.example.com
311 127.0.0.5
312
313 Since 4.8.0: the hex format can be prefixed by any number of characters (within DNS label length limits), including zero characters (so no prefix).
314
315 .. function:: createReverse6(format[, exceptions])
316
317 Used for generating default hostnames from IPv6 wildcard reverse DNS records, e.g. ``*.1.0.0.2.ip6.arpa``
318
319 **For simplicity purposes, only small sections of IPv6 rDNS domains are used in most parts of this guide,**
320 **as a full ip6.arpa record is around 80 characters long**
321
322 See :func:`createReverse` for IPv4 records (in-addr.arpa)
323
324 See :func:`createForward6` for creating the AAAA records on a wildcard record such as ``*.static.example.com``
325
326 Returns a formatted hostname based on the format string passed.
327
328 :param format: A hostname string to format, for example ``%33%.static6.example.com``.
329 :param exceptions: An optional table of overrides. For example ``{['2001:db8::1'] = 'example.example.com.'}`` would, when generating a name for IP ``2001:db8::1``, return ``example.example.com`` instead of something like ``2001--db8.example.com``.
330
331 Formatting options:
332
333 - ``%1%`` to ``%32%`` are individual characters (nibbles)
334 - **Example PTR record query:** ``a.0.0.0.1.0.0.2.ip6.arpa``
335 - ``%1%`` = 2
336 - ``%2%`` = 0
337 - ``%3%`` = 0
338 - ``%4%`` = 1
339 - ``%33%`` converts the compressed address format into a dashed format, e.g. ``2001:a::1`` to ``2001-a--1``
340 - ``%34%`` to ``%41%`` represent the 8 uncompressed 2-byte chunks
341 - **Example:** PTR query for ``2001:a:b::123``
342 - ``%34%`` - returns ``2001`` (chunk 1)
343 - ``%35%`` - returns ``000a`` (chunk 2)
344 - ``%41%`` - returns ``0123`` (chunk 8)
345
346 Example records::
347
348 *.1.0.0.2.ip6.arpa IN LUA PTR "createReverse6('%33%.static6.example.com')"
349 *.2.0.0.2.ip6.arpa IN LUA PTR "createReverse6('%34%.%35%.static6.example.com')"
350
351 When queried::
352
353 # -x is syntactic sugar to request the PTR record for an IPv4/v6 address such as 2001::1
354 # Equivalent to dig PTR 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.b.0.0.0.a.0.0.0.1.0.0.2.ip6.arpa
355 # readable version: 1.0.0.0 .0.0.0.0 .0.0.0.0 .0.0.0.0 .0.0.0.0 .b.0.0.0 .a.0.0.0 .1.0.0.2 .ip6.arpa
356
357 $ dig +short -x 2001:a:b::1 @ns1.example.com
358 2001-a-b--1.static6.example.com.
359
360 $ dig +short -x 2002:a:b::1 @ns1.example.com
361 2002.000a.static6.example.com
362
363 .. function:: createForward6()
364
365 Used to generate the reverse DNS domains made from :func:`createReverse6`
366
367 Generates an AAAA record for a dashed compressed IPv6 domain (e.g. ``2001-a-b--1.static6.example.com``)
368
369 It does not take any parameters, it simply interprets the zone record to find the IP address.
370
371 An example record for zone ``static.example.com``::
372
373 *.static6.example.com IN LUA AAAA "createForward6()"
374
375 This function supports the dashed compressed format (i.e. ``2001-a-b--1.static6.example.com``), and the dot-split uncompressed format (``2001.db8.6.5.4.3.2.1.static6.example.com``)
376
377 When queried::
378
379 $ dig +short AAAA 2001-a-b--1.static6.example.com @ns1.example.com
380 2001:a:b::1
381
382 Since 4.8.0: a non-split full length format (``20010002000300040005000600070db8.example.com``) is also supported, optionally prefixed, in which case the last 32 characters will be considered.
383
384 .. function:: filterForward(address, masks[, fallback])
385
386 .. versionadded:: 4.5.0
387
388 Used for limiting the output of :func:`createForward` and :func:`createForward6` to a set of netmasks.
389
390 :param address: A string containing an address, usually taken directly from :func:`createForward: or :func:`createForward6`.
391 :param masks: A NetmaskGroup; any address not matching the NMG will be replaced by the fallback address.
392 :param fallback: A string containing the fallback address. Defaults to ``0.0.0.0`` or ``::``.
393
394 Example::
395
396 *.static4.example.com IN LUA A "filterForward(createForward(), newNMG({'192.0.2.0/24', '10.0.0.0/8'}))"
397
398 Helper functions
399 ~~~~~~~~~~~~~~~~
400
401 .. function:: asnum(number)
402 asnum(numbers)
403
404 Returns true if the ``bestwho`` IP address is determined to be from
405 any of the listed AS numbers.
406
407 :param int number: An AS number
408 :param [int] numbers: A list of AS numbers
409
410 .. function:: country(country)
411 country(countries)
412
413 Returns true if the ``bestwho`` IP address of the client is within the
414 two letter ISO country code passed, as described in :doc:`../backends/geoip`.
415
416 :param string country: A country code like "NL"
417 :param [string] countries: A list of country codes
418
419 .. function:: countryCode()
420
421 Returns two letter ISO country code based ``bestwho`` IP address, as described in :doc:`../backends/geoip`.
422 If the two letter ISO country code is unknown "--" will be returned.
423
424 .. function:: region(region)
425 region(regions)
426
427 Returns true if the ``bestwho`` IP address of the client is within the
428 two letter ISO region code passed, as described in :doc:`../backends/geoip`.
429
430 :param string region: A region code like "CA"
431 :param [string] regions: A list of regions codes
432
433 .. function:: regionCode()
434
435 Returns two letter ISO region code based ``bestwho`` IP address, as described in :doc:`../backends/geoip`.
436 If the two letter ISO region code is unknown "--" will be returned.
437
438 .. function:: continent(continent)
439 continent(continents)
440
441 Returns true if the ``bestwho`` IP address of the client is within the
442 continent passed, as described in :doc:`../backends/geoip`.
443
444 :param string continent: A continent code like "EU"
445 :param [string] continents: A list of continent codes
446
447 .. function:: continentCode()
448
449 Returns two letter ISO continent code based ``bestwho`` IP address, as described in :doc:`../backends/geoip`.
450 If the two letter ISO continent code is unknown "--" will be returned.
451
452 .. function:: netmask(netmasks)
453
454 Returns true if ``bestwho`` is within any of the listed subnets.
455
456 :param [string] netmasks: The list of IP addresses to check against