+++ /dev/null
- <sect1 id="lua-policy-engine"><title>Lua Policy Engine</title>
- <para>
- Starting with release 3.4.0, the PowerDNS Authoritative Server has support for Lua scripting to
- make policy decisions. The most common usage for these hooks is to implement RRL or RRL-like policies.
- </para>
- <para>
- In the source tree, <filename>policy-example-rrl.lua</filename> contains an example RRL script
- that aims to faithfully implement <ulink url="http://ss.vix.su/~vixie/isc-tn-2012-1.txt">Vixie/Schryver's original draft</ulink>. The script demonstrates most aspects of the policy API. More information about the original (in BIND) and other implementations can be found on
- <ulink url="http://www.redbarn.org/dns/ratelimits">Vixie's RRL page</ulink>.
- </para>
- <para>
- If you set <command>experimental-lua-policy-script</command> in
- <filename>pdns.conf</filename>, PowerDNS will load one instance of your
- script, so your global state is exactly that -- global state. PowerDNS
- will call the <command>police</command> function with three arguments,
- up to two times per query. Before talking to the database, PowerDNS
- will call <command>police</command> with <command>req</command> set, but
- <command>resp</command> will be <command>nil</command>. For queries answered
- from cache, this step is skipped. Before sending out a response (either from database
- or from cache), we will call the function with all arguments filled.
- </para>
- <para>
- The prototype for <command>police</command> is:
-<programlisting>
-function police (req, resp, isTcp)
-</programlisting>
- <command>req</command> is always set. <command>resp</command> is set when we are about to send out
- a response. <command>isTcp</command> is a boolean that is set to true when the client is on TCP.
- You could use this to mark clients as 'real and legit'.
- </para>
- <para>
- <command>req</command> and <command>resp</command> are thin wrappers around the PowerDNS
- <command>DNSPacket</command> object. The following methods are supported, shown with suggested usage and return values/types:
-<programlisting>
-qname, qtype = resp:getQuestion() -- string, number
-remote = resp:getRemote() -- string (remote IPv4/v6 address)
-wild = resp:getWild() -- string (see below)
-zone = resp:getZone() -- string (see below)
-reqsize = req:getSize() -- number (in bytes)
-respsize = resp:getSize() -- number (in bytes)
-rcode = resp:getRcode() -- number
-an, ns, ar = resp:getRRCounts() -- number, number, number
-</programlisting>
- <command>getWild()</command> returns the name of the wildcard that was matched by <command>qname</command>,
- or the empty string if no wildcard was matched. <command>getZone()</command> yields the name of the
- authoritative zone holding the returned data. <command>getRRCounts()</command> tells you, respectively, the
- number of ANSWER, AUTHORITY and ADDITIONAL records in the response.
- </para>
- <para>
- <command>police</command> is expected to return <command>pdns.PASS</command> (tells PowerDNS to proceed
- as normal), <command>pdns.DROP</command> (tells PowerDNS to silently drop the query/response)
- or <command>pdns.TRUNCATE</command> (tells PowerDNS to send an empty response with TC=1, which should make
- legitimate clients switch to TCP for this query). Note that TCP queries/responses (with <command>isTcp</command> set to <command>true</command>) ignore this return value from <command>police</command>.
- </para>
-
- </sect1>