4 LUA rules run within the same environment as described in
5 :doc:`../modes-of-operation`.
7 The Lua snippets can query the following variables:
12 The :class:`DNSHeader` of the received query.
14 A boolean describing if the DNSSEC OK (DO) bit was set in the query.
16 The advertised EDNS buffer size.
18 The name of the requested record. This is a :class:`DNSName`.
20 The zone this LUA record is in. This is a :class:`DNSName`.
22 The id of the zone. This is an integer.
24 Whether or not the query was received over TCP.
29 The EDNS Client Subnet, should one have been set on the query. Unset
30 otherwise. This is a :class:`Netmask`.
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`.
36 IP address of requesting resolver as a :class:`ComboAddress`.
38 IP address (including port) of socket on which the question arrived.
43 Record creation functions
44 ~~~~~~~~~~~~~~~~~~~~~~~~~
46 .. function:: ifportup(portnum, addresses[, options])
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.
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.
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.
62 Various options can be set in the ``options`` parameter:
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)
70 .. function:: ifurlup(url, addresses[, options])
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.
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.
83 Various options can be set in the ``options`` parameter:
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).
93 An example of a list of address sets:
97 ifurlup("https://example.com/", { {"192.0.2.20", "203.0.113.4"}, {"203.0.113.2"} })
99 .. function:: ifurlextup(groups-of-address-url-pairs[, options])
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.
105 Options are identical to those for ``ifurlup``.
111 ifurlextup({{['192.168.0.1']='https://example.com/',['192.168.0.2']='https://example.com/404'}})
113 Example with two groups:
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/'}})"
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.
123 .. function:: pickrandom(values)
125 Returns a random value from the list supplied.
127 :param values: A list of strings such as IPv4 or IPv6 address.
129 This function also works for CNAME or TXT records.
131 .. function:: pickrandomsample(number, values)
133 Returns N random values from the list supplied.
135 :param number: Number of values to return
136 :param values: A list of strings such as IPv4 or IPv6 address.
138 This function also works for CNAME or TXT records.
140 .. function:: pickhashed(values)
142 Based on the hash of ``bestwho``, returns a random value from the list supplied.
144 :param values: A list of strings such as IPv4 or IPv6 address.
146 This function also works for CNAME or TXT records.
148 .. function:: pickclosest(addresses)
150 Returns IP address deemed closest to the ``bestwho`` IP address.
152 :param addresses: A list of strings with the possible IP addresses.
154 .. function:: latlon()
156 Returns text listing fractional latitude/longitude associated with the ``bestwho`` IP address.
158 .. function:: latlonloc()
160 Returns text in LOC record format listing latitude/longitude associated with the ``bestwho`` IP address.
162 .. function:: closestMagic()
164 Suitable for use as a wildcard LUA A record. Will parse the query name which should be in format::
166 192-0-2-1.192-0-2-2.198-51-100-1.magic.v4.powerdns.org
168 It will then resolve to an A record with the IP address closest to ``bestwho`` from the list
169 of supplied addresses.
171 In the ``magic.v4.powerdns.org`` this looks like::
173 *.magic.v4.powerdns.org IN LUA A "closestMagic()"
176 In another zone, a record is then present like this::
178 www-balanced.powerdns.org IN CNAME 192-0-2-1.192-0-2-2.198-51-100-1.magic.v4.powerdns.org
180 This effectively opens up your server to being a 'geographical load balancer as a service'.
182 Performs no uptime checking.
184 .. function:: all(values)
188 :param values: A list of strings such as IPv4 or IPv6 address.
190 This function also works for CNAME or TXT records.
192 .. function:: view(pairs)
194 Shorthand function to implement 'views' for all record types.
196 :param pairs: A list of netmask/result pairs.
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'}} "
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.
208 This function also works for CNAME or TXT records.
210 .. function:: pickchashed(values)
212 Based on the hash of ``bestwho``, returns a string from the list
213 supplied, as weighted by the various ``weight`` parameters and distributed consistently.
214 Performs no uptime checking.
216 :param values: table of weight, string (such as IPv4 or IPv6 address).
218 This function works almost like :func:`pickwhashed` while bringing the following properties:
219 - reordering the list of entries won't affect the distribution
220 - updating the weight of an entry will only affect a part of the distribution
221 - because of the previous properties, the CPU and memory cost is a bit higher than :func:`pickwhashed`
223 Hashes will be pre computed the first time such a record is hit and refreshed if needed. If updating the list is done often,
224 the cash may grow. A cleanup routine is performed every :ref:`setting-lua-consistent-hashes-cleanup-interval` seconds (default 1h)
225 and cleans cached entries for records that haven't been used for :ref:`setting-lua-consistent-hashes-expire-delay` seconds (default 24h)
229 mydomain.example.com IN LUA A ("pickchashed({ "
230 " {15, "192.0.2.1"}, "
231 " {100, "198.51.100.5"} "
235 .. function:: pickwhashed(values)
237 Based on the hash of ``bestwho``, returns a string from the list
238 supplied, as weighted by the various ``weight`` parameters.
239 Performs no uptime checking.
241 :param values: table of weight, string (such as IPv4 or IPv6 address).
243 Because of the hash, the same client keeps getting the same answer, but
244 given sufficient clients, the load is still spread according to the weight
247 This function also works for CNAME or TXT records.
251 mydomain.example.com IN LUA A ("pickwhashed({ "
252 " {15, "192.0.2.1"}, "
253 " {100, "198.51.100.5"} "
256 .. function:: picknamehashed(values)
258 Based on the hash of the DNS record name, returns a string from the list supplied, as weighted by the various ``weight`` parameters.
259 Performs no uptime checking.
261 :param values: table of weight, string (such as IPv4 or IPv6 address).
263 This allows basic persistent load balancing across a number of backends.
264 It means that ``test.mydomain.example.com`` will always resolve to the same IP, but ``test2.mydomain.example.com`` may go elsewhere.
265 This function is only useful for wildcard records.
267 This works similar to round-robin load balancing, but has the advantage of making traffic for the same domain always end up on the same server which can help cache hit rates.
269 This function also works for CNAME or TXT records.
273 *.mydomain.example.com IN LUA A ("picknamehashed({ "
274 " {15, "192.0.2.1"}, "
275 " {100, "198.51.100.5"} "
279 .. function:: pickwrandom(values)
281 Returns a random string from the list supplied, as weighted by the
282 various ``weight`` parameters. Performs no uptime checking.
284 :param values: table of weight, string (such as IPv4 or IPv6 address).
286 See :func:`pickwhashed` for an example.
288 This function also works for CNAME or TXT records.
290 Reverse DNS functions
291 ~~~~~~~~~~~~~~~~~~~~~
294 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.
295 Not limiting responses like this may, in some situations, help attackers with impersonation and attacks like such as cookie stealing.
297 .. function:: createReverse(format, [exceptions])
299 Used for generating default hostnames from IPv4 wildcard reverse DNS records, e.g. ``*.0.0.127.in-addr.arpa``
301 See :func:`createReverse6` for IPv6 records (ip6.arpa)
303 See :func:`createForward` for creating the A records on a wildcard record such as ``*.static.example.com``
305 Returns a formatted hostname based on the format string passed.
307 :param format: A hostname string to format, for example ``%1%.%2%.%3%.%4%.static.example.com``.
308 :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``.
310 **Formatting options:**
312 - ``%1%`` to ``%4%`` are individual octets
313 - Example record query: ``1.0.0.127.in-addr.arpa``
318 - ``%5%`` joins the four decimal octets together with dashes
319 - Example: ``%5%.static.example.com`` is equivalent to ``%1%-%2%-%3%-%4%.static.example.com``
320 - ``%6%`` converts each octet from decimal to hexadecimal and joins them together
321 - Example: A query for ``15.0.0.127.in-addr.arpa``
322 - ``%6`` would be ``7f00000f`` (127 is 7f, and 15 is 0f in hexadecimal)
326 *.0.0.127.in-addr.arpa IN LUA PTR "createReverse('%1%.%2%.%3%.%4%.static.example.com')"
327 *.1.0.127.in-addr.arpa IN LUA PTR "createReverse('%5%.static.example.com')"
328 *.2.0.127.in-addr.arpa IN LUA PTR "createReverse('%6%.static.example.com')"
332 # -x is syntactic sugar to request the PTR record for an IPv4/v6 address such as 127.0.0.5
333 # Equivalent to dig PTR 5.0.0.127.in-addr.arpa
334 $ dig +short -x 127.0.0.5 @ns1.example.com
335 127.0.0.5.static.example.com.
336 $ dig +short -x 127.0.1.5 @ns1.example.com
337 127-0-0-5.static.example.com.
338 $ dig +short -x 127.0.2.5 @ns1.example.com
339 7f000205.static.example.com.
341 .. function:: createForward()
343 Used to generate the reverse DNS domains made from :func:`createReverse`
345 Generates an A record for a dotted or hexadecimal IPv4 domain (e.g. 127.0.0.1.static.example.com)
347 It does not take any parameters, it simply interprets the zone record to find the IP address.
349 An example record for zone ``static.example.com``::
351 *.static.example.com IN LUA A "createForward()"
353 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``)
357 $ dig +short A 127.0.0.5.static.example.com @ns1.example.com
360 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).
362 .. function:: createReverse6(format[, exceptions])
364 Used for generating default hostnames from IPv6 wildcard reverse DNS records, e.g. ``*.1.0.0.2.ip6.arpa``
366 **For simplicity purposes, only small sections of IPv6 rDNS domains are used in most parts of this guide,**
367 **as a full ip6.arpa record is around 80 characters long**
369 See :func:`createReverse` for IPv4 records (in-addr.arpa)
371 See :func:`createForward6` for creating the AAAA records on a wildcard record such as ``*.static.example.com``
373 Returns a formatted hostname based on the format string passed.
375 :param format: A hostname string to format, for example ``%33%.static6.example.com``.
376 :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``.
380 - ``%1%`` to ``%32%`` are individual characters (nibbles)
381 - **Example PTR record query:** ``a.0.0.0.1.0.0.2.ip6.arpa``
386 - ``%33%`` converts the compressed address format into a dashed format, e.g. ``2001:a::1`` to ``2001-a--1``
387 - ``%34%`` to ``%41%`` represent the 8 uncompressed 2-byte chunks
388 - **Example:** PTR query for ``2001:a:b::123``
389 - ``%34%`` - returns ``2001`` (chunk 1)
390 - ``%35%`` - returns ``000a`` (chunk 2)
391 - ``%41%`` - returns ``0123`` (chunk 8)
395 *.1.0.0.2.ip6.arpa IN LUA PTR "createReverse6('%33%.static6.example.com')"
396 *.2.0.0.2.ip6.arpa IN LUA PTR "createReverse6('%34%.%35%.static6.example.com')"
400 # -x is syntactic sugar to request the PTR record for an IPv4/v6 address such as 2001::1
401 # 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
402 # 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
404 $ dig +short -x 2001:a:b::1 @ns1.example.com
405 2001-a-b--1.static6.example.com.
407 $ dig +short -x 2002:a:b::1 @ns1.example.com
408 2002.000a.static6.example.com
410 .. function:: createForward6()
412 Used to generate the reverse DNS domains made from :func:`createReverse6`
414 Generates an AAAA record for a dashed compressed IPv6 domain (e.g. ``2001-a-b--1.static6.example.com``)
416 It does not take any parameters, it simply interprets the zone record to find the IP address.
418 An example record for zone ``static.example.com``::
420 *.static6.example.com IN LUA AAAA "createForward6()"
422 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``)
426 $ dig +short AAAA 2001-a-b--1.static6.example.com @ns1.example.com
429 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.
431 .. function:: filterForward(address, masks[, fallback])
433 .. versionadded:: 4.5.0
435 Used for limiting the output of :func:`createForward` and :func:`createForward6` to a set of netmasks.
437 :param address: A string containing an address, usually taken directly from :func:`createForward: or :func:`createForward6`.
438 :param masks: A NetmaskGroup; any address not matching the NMG will be replaced by the fallback address.
439 :param fallback: A string containing the fallback address. Defaults to ``0.0.0.0`` or ``::``.
443 *.static4.example.com IN LUA A "filterForward(createForward(), newNMG({'192.0.2.0/24', '10.0.0.0/8'}))"
445 Since 4.9.0: if the fallback parameter is an empty string, ``filterForward`` returns an empty set, yielding a NODATA answer.
446 You cannot combine this feature with DNSSEC.
451 .. function:: asnum(number)
454 Returns true if the ``bestwho`` IP address is determined to be from
455 any of the listed AS numbers.
457 :param int number: An AS number
458 :param [int] numbers: A list of AS numbers
460 .. function:: country(country)
463 Returns true if the ``bestwho`` IP address of the client is within the
464 two letter ISO country code passed, as described in :doc:`../backends/geoip`.
466 :param string country: A country code like "NL"
467 :param [string] countries: A list of country codes
469 .. function:: countryCode()
471 Returns two letter ISO country code based ``bestwho`` IP address, as described in :doc:`../backends/geoip`.
472 If the two letter ISO country code is unknown "--" will be returned.
474 .. function:: region(region)
477 Returns true if the ``bestwho`` IP address of the client is within the
478 two letter ISO region code passed, as described in :doc:`../backends/geoip`.
480 :param string region: A region code like "CA"
481 :param [string] regions: A list of regions codes
483 .. function:: regionCode()
485 Returns two letter ISO region code based ``bestwho`` IP address, as described in :doc:`../backends/geoip`.
486 If the two letter ISO region code is unknown "--" will be returned.
488 .. function:: continent(continent)
489 continent(continents)
491 Returns true if the ``bestwho`` IP address of the client is within the
492 continent passed, as described in :doc:`../backends/geoip`.
494 :param string continent: A continent code like "EU"
495 :param [string] continents: A list of continent codes
497 .. function:: continentCode()
499 Returns two letter ISO continent code based ``bestwho`` IP address, as described in :doc:`../backends/geoip`.
500 If the two letter ISO continent code is unknown "--" will be returned.
502 .. function:: netmask(netmasks)
504 Returns true if ``bestwho`` is within any of the listed subnets.
506 :param [string] netmasks: The list of IP addresses to check against
508 .. function:: dblookup(name, type)
510 .. versionadded:: 4.9.0
512 Does a database lookup for name and type, and returns a (possibly empty) array of string results.
514 Please keep the following in mind:
516 * it does not evaluate any LUA code found
517 * if you needed just one string, perhaps you want ``dblookup('www.example.org', pdns.A)[1]`` to take the first item from the array
518 * some things, like ifurlup, don't like empty tables, so be careful not to accidentally look up a name that does not have any records of that type, if you are going to use the result in ``ifurlup``
522 www IN LUA A "ifurlup('https://www.example.com/', {dblookup('www1.example.com', pdns.A), dblookup('www2.example.com', pdns.A), dblookup('www3.example.com', pdns.A)})"
524 :param string name: Name to look up in the database
525 :param int type: DNS type to look for