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:: pickwhashed(values)
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.
216 :param values: table of weight, string (such as IPv4 or IPv6 address).
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
222 This function also works for CNAME or TXT records.
226 mydomain.example.com IN LUA A ("pickwhashed({ "
227 " {15, "192.0.2.1"}, "
228 " {100, "198.51.100.5"} "
232 .. function:: pickwrandom(values)
234 Returns a random string from the list supplied, as weighted by the
235 various ``weight`` parameters. Performs no uptime checking.
237 :param values: table of weight, string (such as IPv4 or IPv6 address).
239 See :func:`pickwhashed` for an example.
241 This function also works for CNAME or TXT records.
243 Reverse DNS functions
244 ~~~~~~~~~~~~~~~~~~~~~
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.
250 .. function:: createReverse(format, [exceptions])
252 Used for generating default hostnames from IPv4 wildcard reverse DNS records, e.g. ``*.0.0.127.in-addr.arpa``
254 See :func:`createReverse6` for IPv6 records (ip6.arpa)
256 See :func:`createForward` for creating the A records on a wildcard record such as ``*.static.example.com``
258 Returns a formatted hostname based on the format string passed.
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``.
263 **Formatting options:**
265 - ``%1%`` to ``%4%`` are individual octets
266 - Example record query: ``1.0.0.127.in-addr.arpa``
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)
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')"
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.
294 .. function:: createForward()
296 Used to generate the reverse DNS domains made from :func:`createReverse`
298 Generates an A record for a dotted or hexadecimal IPv4 domain (e.g. 127.0.0.1.static.example.com)
300 It does not take any parameters, it simply interprets the zone record to find the IP address.
302 An example record for zone ``static.example.com``::
304 *.static.example.com IN LUA A "createForward()"
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``)
310 $ dig +short A 127.0.0.5.static.example.com @ns1.example.com
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).
315 .. function:: createReverse6(format[, exceptions])
317 Used for generating default hostnames from IPv6 wildcard reverse DNS records, e.g. ``*.1.0.0.2.ip6.arpa``
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**
322 See :func:`createReverse` for IPv4 records (in-addr.arpa)
324 See :func:`createForward6` for creating the AAAA records on a wildcard record such as ``*.static.example.com``
326 Returns a formatted hostname based on the format string passed.
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``.
333 - ``%1%`` to ``%32%`` are individual characters (nibbles)
334 - **Example PTR record query:** ``a.0.0.0.1.0.0.2.ip6.arpa``
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)
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')"
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
357 $ dig +short -x 2001:a:b::1 @ns1.example.com
358 2001-a-b--1.static6.example.com.
360 $ dig +short -x 2002:a:b::1 @ns1.example.com
361 2002.000a.static6.example.com
363 .. function:: createForward6()
365 Used to generate the reverse DNS domains made from :func:`createReverse6`
367 Generates an AAAA record for a dashed compressed IPv6 domain (e.g. ``2001-a-b--1.static6.example.com``)
369 It does not take any parameters, it simply interprets the zone record to find the IP address.
371 An example record for zone ``static.example.com``::
373 *.static6.example.com IN LUA AAAA "createForward6()"
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``)
379 $ dig +short AAAA 2001-a-b--1.static6.example.com @ns1.example.com
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.
384 .. function:: filterForward(address, masks[, fallback])
386 .. versionadded:: 4.5.0
388 Used for limiting the output of :func:`createForward` and :func:`createForward6` to a set of netmasks.
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 ``::``.
396 *.static4.example.com IN LUA A "filterForward(createForward(), newNMG({'192.0.2.0/24', '10.0.0.0/8'}))"
401 .. function:: asnum(number)
404 Returns true if the ``bestwho`` IP address is determined to be from
405 any of the listed AS numbers.
407 :param int number: An AS number
408 :param [int] numbers: A list of AS numbers
410 .. function:: country(country)
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`.
416 :param string country: A country code like "NL"
417 :param [string] countries: A list of country codes
419 .. function:: countryCode()
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.
424 .. function:: region(region)
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`.
430 :param string region: A region code like "CA"
431 :param [string] regions: A list of regions codes
433 .. function:: regionCode()
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.
438 .. function:: continent(continent)
439 continent(continents)
441 Returns true if the ``bestwho`` IP address of the client is within the
442 continent passed, as described in :doc:`../backends/geoip`.
444 :param string continent: A continent code like "EU"
445 :param [string] continents: A list of continent codes
447 .. function:: continentCode()
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.
452 .. function:: netmask(netmasks)
454 Returns true if ``bestwho`` is within any of the listed subnets.
456 :param [string] netmasks: The list of IP addresses to check against
458 .. function:: dblookup(name, type)
460 Does a database lookup for name and type, and returns a (possibly empty) array of string results.
462 Please keep the following in mind:
464 * it does not evaluate any LUA code found
465 * if you needed just one string, perhaps you want ``dblookup('www.example.org', 'A')[1]`` to take the first item from the array
466 * 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``
470 www IN LUA A "ifurlup('https://www.example.com/', {dblookup('www1.example.com', 'A'), dblookup('www2.example.com', 'A'), dblookup('www3.example.com', 'A')})"
472 :param string name: Name to look up in the database
473 :param string type: DNS type to look for