To get a quick start, we have supplied a sample script that showcases all functionality described below. Please find it here.
Queries can be intercepted in many places:
ipfilter()
)prerpz()
)preresolve()
)nodata()
, nxdomain()
)postresolve()
)preoutquery()
)Addresses and DNS Names are not passed as strings but as native objects.
This allows for easy checking against Netmasks and domain sets.
It also means that to print such names, the :toString
method must be used (or even :toStringWithPort
for addresses).
Once a script is loaded, PowerDNS looks for several functions in the loaded script. All of these functions are optional.
If a function returns true, it will indicate that it handled a query. If it returns false, the Recursor will continue processing unchanged (with one minor exception).
ipfilter
(remoteip, localip, dh) → bool¶This hook gets queried immediately after consulting the packet cache, but before parsing the DNS packet. If this hook returns something else than false, the packet is dropped. However, because this check is after the packet cache, the IP address might still receive answers that require no packet parsing.
With this hook, undesired traffic can be dropped rapidly before using precious CPU cycles for parsing. As an example, to filter all queries coming from 1.2.3.0/24, or with the AD bit set:
badips = newNMG()
badips:addMask("1.2.3.0/24")
function ipfilter(rem, loc, dh)
return badips:match(rem) or dh:getAD()
end
This hook does not get the full DNSQuestion
object, since filling out the fields would require packet parsing, which is what we are trying to prevent with this function.
Parameters: |
|
---|
gettag
(remote, ednssubnet, localip, qname, qtype, ednsoptions, tcp) → int¶gettag
(remote, ednssubnet, localip, qname, qtype, ednsoptions) → intChanged in version 4.1.0: The tcp
parameter was added.
The gettag
function is invoked when the Recursor attempts to discover in which packetcache an answer is available.
This function must return an integer, which is the tag number of the packetcache.
In addition to this integer, this function can return a table of policy tags.
The resulting tag number can be accessed via dq.tag
in the preresolve()
hook, and the policy tags via dq:getPolicyTags()
in every hook.
New in version 4.1.0: It can also return a table whose keys and values are strings to fill the DNSQuestion.data
table, as well as a requestorId
value to fill the DNSQuestion.requestorId
field and a deviceId
value to fill the DNSQuestion.deviceId
field.
The tagged packetcache can e.g. be used to answer queries from cache that have e.g. been filtered for certain IPs (this logic should be implemented in gettag()
).
This ensure that queries are answered quickly compared to setting dq.variable
to true.
In the latter case, repeated queries will pass through the entire Lua script.
Parameters: |
|
---|
prerpz
(dq)¶This hook is called before any filtering policy have been applied, making it possible to completely disable filtering by setting dq.wantsRPZ
to false.
Using the dq:discardPolicy()
function, it is also possible to selectively disable one or more filtering policy, for example RPZ zones, based on the content of the dq
object.
As an example, to disable the “malware” policy for example.com queries:
function prerpz(dq)
-- disable the RPZ policy named 'malware' for example.com
if dq.qname:equal('example.com') then
dq:discardPolicy('malware')
end
return false
end
Parameters: | dq (DNSQuestion) – The DNS question to handle |
---|
preresolve
(dq)¶This function is called before any DNS resolution is attempted, and if this function indicates it, it can supply a direct answer to the DNS query, overriding the internet. This is useful to combat botnets, or to disable domains unacceptable to an organization for whatever reason.
Parameters: | dq (DNSQuestion) – The DNS question to handle |
---|
postresolve
(dq)¶is called right before returning a response to a client (and, unless dq.variable
is set, to the packet cache too).
It allows inspection and modification of almost any detail in the return packet.
Parameters: | dq (DNSQuestion) – The DNS question to handle |
---|
nxdomain
(dq)¶is called after the DNS resolution process has run its course, but ended in an ‘NXDOMAIN’ situation, indicating that the domain does not exist.
Works entirely like postresolve()
, but saves a trip through Lua for answers which are not NXDOMAIN.
Parameters: | dq (DNSQuestion) – The DNS question to handle |
---|
nodata
(dq)¶is just like nxdomain()
, except it gets called when a domain exists, but the requested type does not.
This is where one would implement DNS64.
Parameters: | dq (DNSQuestion) – The DNS question to handle |
---|
preoutquery
(dq)¶This hook is not called in response to a client packet, but fires when the Recursor wants to talk to an authoritative server. When this hook sets the special result code -3, the whole DNS client query causing this outquery gets dropped.
However, this function can also return records like preresolve()
.
Parameters: | dq (DNSQuestion) – The DNS question to handle |
---|
The functions must return true
if they have taken over the query and wish that the nameserver should not proceed with its regular query-processing.
When a function returns false
, the nameserver will process the query normally until a new function is called.
If a function has taken over a request, it should set an rcode (usually 0), and specify a table with records to be put in the answer section of a packet.
An interesting rcode is NXDOMAIN (3, or pdns.NXDOMAIN
), which specifies the non-existence of a domain.
The ipfilter()
and preoutquery()
hooks are different, in that ipfilter()
can only return a true of false value, and that preoutquery()
can also set rcode -3 to signify that the whole query should be terminated.
A minimal sample script:
function nxdomain(dq)
print("Intercepting NXDOMAIN for: ",dq.qname:toString())
if dq.qtype == pdns.A
then
dq.rcode=0 -- make it a normal answer
dq:addAnswer(pdns.A, "192.168.1.1")
return true
end
return false
end
Warning: Please do NOT use the above sample script in production! Responsible NXDomain redirection requires more attention to detail.
Useful ‘rcodes’ include 0 for “no error”, pdns.NXDOMAIN
for “NXDOMAIN”, pdns.DROP
to drop the question from further processing.
Such a drop is accounted in the ‘policy-drops’ metric.
The getFakeAAAARecords
and getFakePTRRecords
followupFunctions
can be used to implement DNS64. See DNS64 support for more information.
To get fake AAAA records for DNS64 usage, set dq.followupFunction to
getFakeAAAARecords
, dq.followupPrefix to e.g. “64:ff9b::” and
dq.followupName to the name you want to synthesize an IPv6 address for.
For fake reverse (PTR) records, set dq.followupFunction to
getFakePTRRecords
and set dq.followupName to the name to look up and
dq.followupPrefix to the same prefix as used with
getFakeAAAARecords
.
When modifying queries, it might be needed that the Recursor does some extra work after the function returns.
The dq.followupFunction
can be set in this case.
It may be useful to return a CNAME record for Lua, and then have the PowerDNS Recursor continue resolving that CNAME.
This can be achieved by setting dq.followupFunction to followCNAMERecords
and dq.followupDomain to “www.powerdns.com”.
PowerDNS will do the rest.
The udpQueryResponse
dq.followupFunction
allows you to query a simple key-value store over UDP asynchronously.
Several dq variables can be set:
dq.udpQueryDest
: destination IP address to send the UDP packet todq.udpQuery
: The content of the UDP payloaddq.udpCallback
: The name of the callback function that is called when an answer is receivedThe callback function must accept the dq
object and can find the response to the UDP query in dq.udpAnswer
.
In this callback function, dq.followupFunction
can be set again to any of the available functions for further processing.
This example script queries a simple key/value store over UDP to decide on whether or not to filter a query:
--[[
This implements a two-step domain filtering solution where the status of an IP address
and a domain name need to be looked up.
To do so, we use the udpQuestionResponse answers which generically allows us to do asynchronous
lookups via UDP.
Such lookups can be slow, but they won't block PowerDNS while we wait for them.
To benefit from this hook,
..
To test, use the 'kvresp' example program provided.
--]]
function preresolve (dq)
print ("prereesolve handler called for: "..dq.remoteaddr:toString().. ", local: ".. dq.localaddr:toString()..", ".. dq.qname:toString()..", ".. dq.qtype)
dq.followupFunction="udpQueryResponse"
dq.udpCallback="gotdomaindetails"
dq.udpQueryDest=newCA("127.0.0.1:5555")
dq.udpQuery = "DOMAIN "..dq.qname:toString()
return true;
end
function gotdomaindetails(dq)
print("gotdomaindetails called, got: "..dq.udpAnswer)
if(dq.udpAnswer == "0")
then
print("This domain needs no filtering, not looking up this domain")
dq.followupFunction=""
return false
end
print("Domain might need filtering for some users")
dq.variable = true -- disable packet cache
local data={}
data["domaindetails"]= dq.udpAnswer
dq.data=data
dq.udpQuery="IP "..dq.remoteaddr:toString()
dq.udpCallback="gotipdetails"
print("returning true in gotipdetails")
return true
end
function gotipdetails(dq)
dq.followupFunction=""
print("So status of IP is "..dq.udpAnswer.." and status of domain is "..dq.data.domaindetails)
if(dq.data.domaindetails=="1" and dq.udpAnswer=="1")
then
print("IP wants filtering and domain is of the filtered kind")
dq:addAnswer(pdns.CNAME, "blocked.powerdns.com")
return true
else
print("Returning false (normal resolution should proceed, for this user)")
return false
end
end
pdnslog("pdns-recursor Lua script starting!", pdns.loglevels.Warning)
blockset = newDS()
blockset:add{"powerdns.org", "xxx"}
dropset = newDS();
dropset:add("123.cn")
malwareset = newDS()
malwareset:add("nl")
magic2 = newDN("www.magic2.com")
magicMetric = getMetric("magic")
-- shows the various ways of blocking, dropping, changing questions
-- return false to say you did not take over the question, but we'll still listen to 'variable'
-- to selectively disable the cache
function preresolve(dq)
print("Got question for "..dq.qname:toString().." from "..dq.remoteaddr:toString().." to "..dq.localaddr:toString())
local ednssubnet=dq:getEDNSSubnet()
if(ednssubnet) then
print("Packet EDNS subnet source: "..ednssubnet:toString()..", "..ednssubnet:getNetwork():toString())
end
local a=dq:getEDNSOption(3)
if(a) then
print("There is an EDNS option 3 present: "..a)
end
loc = newCA("127.0.0.1")
if(dq.remoteaddr:equal(loc))
then
print("Query from loopback")
end
-- note that the comparisons below are CaSe InSensiTivE and you don't have to worry about trailing dots
if(dq.qname:equal("magic.com"))
then
magicMetric:inc()
print("Magic!")
else
print("not magic..")
end
if(dq.qname:__eq(magic2)) -- we hope to improve this syntax
then
print("Faster magic") -- compares against existing DNSName
end -- sadly, dq.qname == magic2 won't work yet
if blockset:check(dq.qname) then
dq.variable = true -- disable packet cache in any case
if dq.qtype == pdns.A then
dq:addAnswer(pdns.A, "1.2.3.4")
dq:addAnswer(pdns.TXT, "\"Hello!\"", 3601) -- ttl
return true;
end
end
if dropset:check(dq.qname) then
dq.rcode = pdns.DROP
return true;
end
if malwareset:check(dq.qname) then
dq:addAnswer(pdns.CNAME, "xs.powerdns.com.")
dq.rcode = 0
dq.followupFunction="followCNAMERecords" -- this makes PowerDNS lookup your CNAME
return true;
end
return false;
end
-- this implements DNS64
function nodata(dq)
if dq.qtype == pdns.AAAA then
dq.followupFunction="getFakeAAAARecords"
dq.followupName=dq.qname
dq.followupPrefix="fe80::"
return true
end
if dq.qtype == pdns.PTR then
dq.followupFunction="getFakePTRRecords"
dq.followupName=dq.qname
dq.followupPrefix="fe80::"
return true
end
return false
end
badips = newNMG()
badips:addMask("127.1.0.0/16")
-- this check is applied before any packet parsing is done
function ipfilter(rem, loc, dh)
print("ipfilter called, rem: ", rem:toStringWithPort(), "loc: ",loc:toStringWithPort(),"match:", badips:match(rem))
print("id: ",dh:getID(), "aa: ", dh:getAA(), "ad: ", dh:getAD(), "arcount: ", dh:getARCOUNT())
print("ports: ",rem:getPort(),loc:getPort())
return badips:match(rem)
end
-- postresolve runs after the packet has been answered, and can be used to change things
-- or still drop
function postresolve(dq)
print("postresolve called for ",dq.qname:toString())
local records = dq:getRecords()
for k,v in pairs(records) do
print(k, v.name:toString(), v:getContent())
if v.type == pdns.A and v:getContent() == "185.31.17.73"
then
print("Changing content!")
v:changeContent("130.161.252.29")
v.ttl=1
end
end
dq:setRecords(records)
return true
end
nxdomainsuffix=newDN("com")
function nxdomain(dq)
print("Hooking: ",dq.qname:toString())
if dq.qname:isPartOf(nxdomainsuffix)
then
dq.rcode=0 -- make it a normal answer
dq:addAnswer(pdns.CNAME, "ourhelpfulservice.com")
dq:addAnswer(pdns.A, "1.2.3.4", 60, "ourhelpfulservice.com")
return true
end
return false
end
Frequently, DoS attacks are performed where specific IP addresses are attacked, often by queries coming in from open resolvers. These queries then lead to a lot of queries to ‘authoritative servers’ which actually often aren’t nameservers at all, but just targets of attack.
The following script will add a requestor’s IP address to a blocking set if they’ve sent a query that caused PowerDNS to attempt to talk to a certain subnet.
This specific script is, as of January 2015, useful to prevent traffic to ezdns.it related traffic from creating CPU load. This script requires PowerDNS Recursor 4.x or later.
lethalgroup=newNMG()
lethalgroup:addMask("192.121.121.0/24") -- touch these nameservers and you die
function preoutquery(dq)
print("pdns wants to ask "..dq.remoteaddr:toString().." about "..dq.qname:toString().." "..dq.qtype.." on behalf of requestor "..dq.localaddr:toString())
if(lethalgroup:match(dq.remoteaddr))
then
print("We matched the group "..lethalgroup:tostring().."!", "killing query dead & adding requestor "..dq.localaddr:toString().." to block list")
dq.rcode = -3 -- "kill"
return true
end
return false
end
The PowerDNS Recursor has a policy engine based on Response Policy Zones (RPZ). Starting with version 4.0.1 of the recursor, it is possible to alter this decision inside the Lua hooks.
If the decision is modified in a Lua hook, false
should be returned, as the query is not actually handled by Lua so the decision is picked up by the Recursor.
The result of the policy decision is checked after preresolve()
and postresolve()
.
For example, if a decision is set to pdns.policykinds.NODATA
by the policy engine and is unchanged in preresolve()
, the query is replied to with a NODATA response immediately after preresolve()
.
-- Dont ever block my own domain and IPs
myDomain = newDN("example.com")
myNetblock = newNMG()
myNetblock:addMasks({"192.0.2.0/24"})
function preresolve(dq)
if dq.qname:isPartOf(myDomain) and dq.appliedPolicy.policyKind ~= pdns.policykinds.NoAction then
pdnslog("Not blocking our own domain!")
dq.appliedPolicy.policyKind = pdns.policykinds.NoAction
end
return false
end
function postresolve(dq)
if dq.appliedPolicy.policyKind ~= pdns.policykinds.NoAction then
local records = dq:getRecords()
for k,v in pairs(records) do
if v.type == pdns.A then
local blockedIP = newCA(v:getContent())
if myNetblock:match(blockedIP) then
pdnslog("Not blocking our IP space")
dq.appliedPolicy.policyKind = pdns.policykinds.NoAction
end
end
end
end
return false
end
PowerDNS Recursor, when compiled with SNMP support, has the ability to act as a SNMP agent to provide SNMP statistics and to be able to send traps from Lua.
For example, to send a custom SNMP trap containing the qname from the
preresolve
hook:
function preresolve(dq)
sendCustomSNMPTrap('Trap from preresolve, qname is '..dq.qname:toString())
return false
end
-- -*- snmpv2 -*-
-- ----------------------------------------------------------------------
-- MIB file for PowerDNS Recursor
-- ----------------------------------------------------------------------
PDNSRECURSOR-MIB DEFINITIONS ::= BEGIN
IMPORTS
OBJECT-TYPE, MODULE-IDENTITY, enterprises,
Counter64, NOTIFICATION-TYPE
FROM SNMPv2-SMI
CounterBasedGauge64
FROM HCNUM-TC
OBJECT-GROUP, MODULE-COMPLIANCE, NOTIFICATION-GROUP
FROM SNMPv2-CONF;
rec MODULE-IDENTITY
LAST-UPDATED "201812240000Z"
ORGANIZATION "PowerDNS BV"
CONTACT-INFO "support@powerdns.com"
DESCRIPTION
"This MIB module describes information gathered through PowerDNS Recursor."
REVISION "201611290000Z"
DESCRIPTION "Initial revision."
REVISION "201812240000Z"
DESCRIPTION "Added the dnssecAuthenticDataQueries and dnssecCheckDisabledQueries stats."
::= { powerdns 2 }
powerdns OBJECT IDENTIFIER ::= { enterprises 43315 }
stats OBJECT IDENTIFIER ::= { rec 1 }
questions OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of questions"
::= { stats 1 }
ipv6Questions OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of IPv6 questions"
::= { stats 2 }
tcpQuestions OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of TCP questions"
::= { stats 3 }
cacheHits OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of cache hits"
::= { stats 4 }
cacheMisses OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of cache misses"
::= { stats 5 }
cacheEntries OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of cache entries"
::= { stats 6 }
cacheBytes OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Size of the cache in bytes"
::= { stats 7 }
packetcacheHits OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of packetcache hits"
::= { stats 8 }
packetcacheMisses OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of packetcache misses"
::= { stats 9 }
packetcacheEntries OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of packetcache entries"
::= { stats 10 }
packetcacheBytes OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Size of the packetcache in bytes"
::= { stats 11 }
mallocBytes OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of bytes allocated by malloc"
::= { stats 12 }
servfailAnswers OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of servfail answers"
::= { stats 13 }
nxdomainAnswers OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of nxdomain answers"
::= { stats 14 }
noerrorAnswers OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of noerror answers"
::= { stats 15 }
unauthorizedUdp OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of unauthorized UDP queries"
::= { stats 16 }
unauthorizedTcp OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of unauthorized TCP queries"
::= { stats 17 }
tcpClientOverflow OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of TCP client connections refused because of too many connections"
::= { stats 18 }
clientParseErrors OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of client parse errors"
::= { stats 19 }
serverParseErrors OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of server parse errors"
::= { stats 20 }
tooOldDrops OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of queries dropped because of a timeout"
::= { stats 21 }
answers01 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of queries answered in less than 1 ms"
::= { stats 22 }
answers110 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of queries answered in 1-10 ms"
::= { stats 23 }
answers10100 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of queries answered in 10-100 ms"
::= { stats 24 }
answers1001000 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of queries answered in 100-1000 ms"
::= { stats 25 }
answersSlow OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of queries answered in more than 1000 ms"
::= { stats 26 }
auth4Answers01 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of IPv4 queries answered in less than 1 ms"
::= { stats 27 }
auth4Answers110 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of IPv4 queries answered in 1-10 ms"
::= { stats 28 }
auth4Answers10100 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of IPv4 queries answered in 10-100 ms"
::= { stats 29 }
auth4Answers1001000 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of IPv4 queries answered in 100-1000 ms"
::= { stats 30 }
auth4Answersslow OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of IPv4 queries answered in more than 1000 ms"
::= { stats 31 }
auth6Answers01 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of IPv6 queries answered in less than 1 ms"
::= { stats 32 }
auth6Answers110 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of IPv6 queries answered in 1-10 ms"
::= { stats 33 }
auth6Answers10100 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of IPv6 queries answered in 10-100 ms"
::= { stats 34 }
auth6Answers1001000 OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of IPv6 queries answered in 100-1000 ms"
::= { stats 35 }
auth6AnswersSlow OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of IPv6 queries answered in more than 1000 ms"
::= { stats 36 }
qaLatency OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Average latency in microseconds"
::= { stats 37 }
unexpectedPackets OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of unexpected packets"
::= { stats 38 }
caseMismatches OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of case mismatches"
::= { stats 39 }
spoofPrevents OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of spoof prevents"
::= { stats 40 }
nssetInvalidations OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of nsset invalidations"
::= { stats 41 }
resourceLimits OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of resolution aborted because of a local resource limit"
::= { stats 42 }
overCapacityDrops OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of queries dropped because the threads limit was reached"
::= { stats 43 }
policyDrops OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of queries dropped because of a policy"
::= { stats 44 }
noPacketError OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of calls to recvmsg() that returned no packet even though the socket was ready"
::= { stats 45 }
dlgOnlyDrops OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of records dropped because of they belonged to a delegation-only zone"
::= { stats 46 }
ignoredPackets OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of ignored packets"
::= { stats 47 }
maxMthreadStack OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Maximum size of the Mthread stack"
::= { stats 48 }
negcacheEntries OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of negcache entries"
::= { stats 49 }
throttleEntries OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of throttle entries"
::= { stats 50 }
nsspeedsEntries OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of nsspeeds entries"
::= { stats 51 }
failedHostEntries OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of failed host entries"
::= { stats 52 }
concurrentQueries OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of concurrent queries"
::= { stats 53 }
securityStatus OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Current security status"
::= { stats 54 }
outgoingTimeouts OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of outgoing timeouts"
::= { stats 55 }
outgoing4Timeouts OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of IPv4 outgoing timeouts"
::= { stats 56 }
outgoing6Timeouts OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of IPv6 outgoing timeouts"
::= { stats 57 }
tcpOutqueries OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of outgoing TCP queries sent"
::= { stats 58 }
allOutqueries OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of outgoing queries sent"
::= { stats 59 }
ipv6Outqueries OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of IPv6 outgoing queries sent"
::= { stats 60 }
throttledOutqueries OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of throttled outgoing queries"
::= { stats 61 }
dontOutqueries OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of outgoing queries not sent because of a 'dont-query' setting"
::= { stats 62 }
unreachables OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of errors due to an unreachable server"
::= { stats 63 }
chainResends OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of chain resends"
::= { stats 64 }
tcpClients OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of TCP clients"
::= { stats 65 }
udpRecvbufErrors OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of UDP recvbuf errors (Linux only)"
::= { stats 66 }
udpSndbufErrors OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of UDP sndbuf errors (Linux only)"
::= { stats 67 }
udpNoportErrors OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of UDP noport errors (Linux only)"
::= { stats 68 }
udpinErrors OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of UDP in errors (Linux only)"
::= { stats 69 }
ednsPingMatches OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of EDNS Ping matches"
::= { stats 70 }
ednsPingMismatches OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of EDNS Ping mismatches"
::= { stats 71 }
dnssecQueries OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of DNSSEC queries"
::= { stats 72 }
nopingOutqueries OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of outgoing queries w/o ping"
::= { stats 73 }
noednsOutqueries OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of outgoing queries w/o EDNS"
::= { stats 74 }
uptime OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Process uptime in seconds"
::= { stats 75 }
realMemoryUsage OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Memory usage"
::= { stats 76 }
fdUsage OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"File descriptors usage"
::= { stats 77 }
userMsec OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"CPU usage (user) in ms"
::= { stats 78 }
sysMsec OBJECT-TYPE
SYNTAX CounterBasedGauge64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"CPU usage (system) in ms"
::= { stats 79 }
dnssecValidations OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of DNSSEC validations"
::= { stats 80 }
dnssecResultInsecure OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of DNSSEC insecure results"
::= { stats 81 }
dnssecResultSecure OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of DNSSEC secure results"
::= { stats 82 }
dnssecResultBogus OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of DNSSEC bogus results"
::= { stats 83 }
dnssecResultIndeterminate OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of DNSSEC indeterminate results"
::= { stats 84 }
dnssecResultNta OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of DNSSEC NTA results"
::= { stats 85 }
policyResultNoaction OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of policy-mandated no-action results"
::= { stats 86 }
policyResultDrop OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of policy-mandated drops"
::= { stats 87 }
policyResultNxdomain OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of policy-mandated NXdomain results"
::= { stats 88 }
policyResultNodata OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of policy-mandated nodata results"
::= { stats 89 }
policyResultTruncate OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of policy-mandated truncate results"
::= { stats 90 }
policyResultCustom OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of policy-mandated custom results"
::= { stats 91 }
queryPipeFullDrops OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of queries dropped because the query distribution pipe was full"
::= { stats 92 }
truncatedDrops OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of queries dropped because they were larger than 512 bytes"
::= { stats 93 }
emptyQueries OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of queries dropped because they had a QD count of 0"
::= { stats 94 }
dnssecAuthenticDataQueries OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of queries received with the AD bit set"
::= { stats 95 }
dnssecCheckDisabledQueries OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of queries received with the CD bit set"
::= { stats 96 }
variableResponses OBJECT-TYPE
SYNTAX Counter64
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Number of variable responses"
::= { stats 97 }
---
--- Traps / Notifications
---
trap OBJECT IDENTIFIER ::= { rec 10 }
traps OBJECT IDENTIFIER ::= { trap 0 } --- reverse-mappable
trapObjects OBJECT IDENTIFIER ::= { rec 11 }
trapReason OBJECT-TYPE
SYNTAX OCTET STRING
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Reason for this trap"
::= { trapObjects 1 }
customTrap NOTIFICATION-TYPE
OBJECTS {
trapReason
}
STATUS current
DESCRIPTION "Trap sent by sendCustomTrap"
::= { traps 1 }
---
--- Conformance
---
recConformance OBJECT IDENTIFIER ::= { rec 100 }
recCompliances MODULE-COMPLIANCE
STATUS current
DESCRIPTION "PowerDNS Recursor compliance statement"
MODULE
MANDATORY-GROUPS {
recGroup,
recTrapsGroup
}
::= { recConformance 1 }
recGroup OBJECT-GROUP
OBJECTS {
questions,
ipv6Questions,
tcpQuestions,
cacheHits,
cacheMisses,
cacheEntries,
cacheBytes,
packetcacheHits,
packetcacheMisses,
packetcacheEntries,
packetcacheBytes,
mallocBytes,
servfailAnswers,
nxdomainAnswers,
noerrorAnswers,
unauthorizedUdp,
unauthorizedTcp,
tcpClientOverflow,
clientParseErrors,
serverParseErrors,
tooOldDrops,
answers01,
answers110,
answers10100,
answers1001000,
answersSlow,
auth4Answers01,
auth4Answers110,
auth4Answers10100,
auth4Answers1001000,
auth4Answersslow,
auth6Answers01,
auth6Answers110,
auth6Answers10100,
auth6Answers1001000,
auth6AnswersSlow,
qaLatency,
unexpectedPackets,
caseMismatches,
spoofPrevents,
nssetInvalidations,
resourceLimits,
overCapacityDrops,
policyDrops,
noPacketError,
dlgOnlyDrops,
ignoredPackets,
maxMthreadStack,
negcacheEntries,
throttleEntries,
nsspeedsEntries,
failedHostEntries,
concurrentQueries,
securityStatus,
outgoingTimeouts,
outgoing4Timeouts,
outgoing6Timeouts,
tcpOutqueries,
allOutqueries,
ipv6Outqueries,
throttledOutqueries,
dontOutqueries,
unreachables,
chainResends,
tcpClients,
udpRecvbufErrors,
udpSndbufErrors,
udpNoportErrors,
udpinErrors,
ednsPingMatches,
ednsPingMismatches,
dnssecQueries,
nopingOutqueries,
noednsOutqueries,
uptime,
realMemoryUsage,
fdUsage,
userMsec,
sysMsec,
dnssecValidations,
dnssecResultInsecure,
dnssecResultSecure,
dnssecResultBogus,
dnssecResultIndeterminate,
dnssecResultNta,
policyResultNoaction,
policyResultDrop,
policyResultNxdomain,
policyResultNodata,
policyResultTruncate,
policyResultCustom,
queryPipeFullDrops,
truncatedDrops,
emptyQueries,
dnssecAuthenticDataQueries,
dnssecCheckDisabledQueries,
variableResponses,
trapReason
}
STATUS current
DESCRIPTION "Objects conformance group for PowerDNS Recursor"
::= { recConformance 2 }
recTrapsGroup NOTIFICATION-GROUP
NOTIFICATIONS {
customTrap
}
STATUS current
DESCRIPTION "Traps conformance group for PowerDNS Recursor"
::= { recConformance 3 }
END
Starting with version 4.1.4 of the recursor, it is possible to define a maintenance() callback function that will be called periodically. This function expects no argument and doesn’t return any value
function maintenance()
-- This would be called every second
-- Perform here your maintenance
end
The interval can be configured through the lua-maintenance-interval setting.