The DNSQuestion (dq) object

A DNSQuestion or dq object is available in several hooks and Lua actions. This object contains details about the current state of the question. This state can be modified from the various hooks.

class DNSQuestion

The DNSQuestion object has several attributes, many of them read-only:

dh

The DNSHeader (dh) object of this query.

ecsOverride

Whether an existing ECS value should be overridden, settable.

ecsPrefixLength

The ECS prefix length to use, settable.

len

The length of the data starting at DNSQuestion.dh, including any trailing bytes following the DNS message.

localaddr

ComboAddress of the local bind this question was received on.

opcode

Integer describing the OPCODE of the packet. Can be matched against OPCode.

pool

New in version 1.8.0.

The pool of servers to which this query will be routed.

qclass

QClass (as an unsigned integer) of this question. Can be compared against DNSClass.

qname

DNSName of this question.

qtype

QType (as an unsigned integer) of this question. Can be compared against the pre-defined constants like DNSQType.A, DNSQType.AAAA.

remoteaddr

ComboAddress of the remote client.

rcode

RCode (as an unsigned integer) of this question. Can be compared against RCode

size

The total size of the buffer starting at DNSQuestion.dh.

skipCache

Whether to skip cache lookup / storing the answer for this question, settable.

tempFailureTTL

On a SERVFAIL or REFUSED from the backend, cache for this amount of seconds, settable.

tcp

Whether the query was received over TCP.

useECS

Whether to send ECS to the backend, settable.

It also supports the following methods:

:addProxyProtocolValue(type, value)

New in version 1.6.0.

Add a proxy protocol TLV entry of type type and value to the current query.

Parameters:
  • type (int) – The type of the new value, ranging from 0 to 255 (both included)
  • value (str) – The binary-safe value
:getContent() → str

New in version 1.8.0.

Get the content of the DNS packet as a string

:getDO() → bool

Get the value of the DNSSEC OK bit.

Returns:true if the DO bit was set, false otherwise
:getEDNSOptions() → table

Return the list of EDNS Options, if any.

Returns:A table of EDNSOptionView objects, indexed on the ECS Option code
:getHTTPHeaders() → table

New in version 1.4.0.

Changed in version 1.8.0: see keepIncomingHeaders on addDOHLocal()

Return the HTTP headers for a DoH query, as a table whose keys are the header names and values the header values. Since 1.8.0 it is necessary to set the keepIncomingHeaders option to true on addDOHLocal() to be able to use this method.

Returns:A table of HTTP headers
:getHTTPHost() → string

New in version 1.4.0.

Return the HTTP Host for a DoH query, which may or may not contain the port.

Returns:The host of the DoH query
:getHTTPPath() → string

New in version 1.4.0.

Return the HTTP path for a DoH query.

Returns:The path part of the DoH query URI
:getHTTPQueryString() → string

New in version 1.4.0.

Return the HTTP query string for a DoH query.

Returns:The query string part of the DoH query URI
:getHTTPScheme() → string

New in version 1.4.0.

Return the HTTP scheme for a DoH query.

Returns:The scheme of the DoH query, for example http or https
:getProtocol() → string

New in version 1.7.0.

Return the transport protocol this query was received over, as a string. The possible values are:

  • “Do53 UDP”
  • “Do53 TCP”
  • “DNSCrypt UDP”
  • “DNSCrypt TCP”
  • “DNS over TLS”
  • “DNS over HTTPS”
Returns:A string
:getProxyProtocolValues() → table

New in version 1.6.0.

Return a table of the Proxy Protocol values currently set for this query.

Returns:A table whose keys are types and values are binary-safe strings
DNSQuestion:getQueryTime -> timespec

New in version 1.8.0.

Return the time at which the current query has been received, in whole seconds and nanoseconds since epoch, as a timespec object.

Returns:A timespec object
:getServerNameIndication() → string

New in version 1.4.0.

Return the TLS Server Name Indication (SNI) value sent by the client over DoT or DoH, if any. See SNIRule() for more information, especially about the availability of SNI over DoH.

Returns:A string containing the TLS SNI value, if any
:getTag(key) → string

Get the value of a tag stored into the DNSQuestion object.

Parameters:key (string) – The tag’s key
Returns:The tag’s value if it was set, an empty string otherwise
:getTagArray() → table

Get all the tags stored into the DNSQuestion object.

Returns:A table of tags, using strings as keys and values
:getTrailingData() → string

New in version 1.4.0.

Get all data following the DNS message.

Returns:The trailing data as a null-safe string
:sendTrap(reason)

Send an SNMP trap.

Parameters:reason (string) – An optional string describing the reason why this trap was sent
:setContent(data)

New in version 1.8.0.

Replace the whole DNS payload of the query with the supplied data. The new DNS payload must include the DNS header, whose ID will be adjusted to match the one of the existing query. For example, this replaces the whole DNS payload of queries for custom.async.tests.powerdns.com and type A, turning it them into FORMERR responses, including EDNS with the DNSSECOK bit set and a UDP payload size of 1232:

function replaceQueryPayload(dq)
  local raw = '\000\000\128\129\000\001\000\000\000\000\000\001\006custom\005async\005tests\008powerdns\003com\000\000\001\000\001\000\000\041\002\000\000\000\128\000\000\\000'
  dq:setContent(raw)
  return DNSAction.Allow
end
addAction(AndRule({QTypeRule(DNSQType.A), makeRule('custom.async.tests.powerdns.com')}), LuaAction(replaceQueryPayload))
Parameters:data (string) – The raw DNS payload
:setEDNSOption(code, data)

New in version 1.8.0.

Add arbitrary EDNS option and data to the query. Any existing EDNS content with the same option code will be overwritten.

Parameters:
  • code (int) – The EDNS option code
  • data (string) – The EDNS option raw data
:setHTTPResponse(status, body, contentType="")

New in version 1.4.0.

Set the HTTP status code and content to immediately send back to the client. For HTTP redirects (3xx), the string supplied in body should be the URL to redirect to. For 200 responses, the value of the content type header can be specified via the contentType parameter. In order for the response to be sent, the QR bit should be set before returning and the function should return Action.HeaderModify.

Parameters:
  • status (int) – The HTTP status code to return
  • body (string) – The body of the HTTP response, or a URL if the status code is a redirect (3xx)
  • contentType (string) – The HTTP Content-Type header to return for a 200 response, ignored otherwise. Default is application/dns-message.
:setNegativeAndAdditionalSOA(nxd, zone, ttl, mname, rname, serial, refresh, retry, expire, minimum)

New in version 1.5.0.

Turn a question into a response, either a NXDOMAIN or a NODATA one based on nxd, setting the QR bit to 1 and adding a SOA record in the additional section.

Parameters:
  • nxd (bool) – Whether the answer is a NXDOMAIN (true) or a NODATA (false)
  • zone (string) – The owner name for the SOA record
  • ttl (int) – The TTL of the SOA record
  • mname (string) – The mname of the SOA record
  • rname (string) – The rname of the SOA record
  • serial (int) – The value of the serial field in the SOA record
  • refresh (int) – The value of the refresh field in the SOA record
  • retry (int) – The value of the retry field in the SOA record
  • expire (int) – The value of the expire field in the SOA record
  • minimum (int) – The value of the minimum field in the SOA record
:setProxyProtocolValues(values)

New in version 1.5.0.

Set the Proxy-Protocol Type-Length values to send to the backend along with this query.

Parameters:values (table) – A table of types and values to send, for example: { [0x00] = "foo", [0x42] = "bar" }. Note that the type must be an integer. Try to avoid these values: 0x01 - 0x05, 0x20 - 0x25, 0x30 as those are predefined in https://www.haproxy.org/download/2.3/doc/proxy-protocol.txt (search for PP2_TYPE_ALPN)
:setRestartable()

New in version 1.8.0.

Make it possible to restart that query after receiving the response, for example to try a different pool of servers after receiving a SERVFAIL or a REFUSED response. Under the hood, this tells dnsdist to keep a copy of the initial query around so that we can send it a second time if needed. Copying the initial DNS payload has a small memory and CPU cost and thus is not done by default. See also DNSResponse:restart().

:setTag(key, value)

Changed in version 1.7.0: Prior to 1.7.0 calling DNSQuestion:setTag() would not overwrite an existing tag value if already set.

Set a tag into the DNSQuestion object. Overwrites the value if any already exists.

Parameters:
  • key (string) – The tag’s key
  • value (string) – The tag’s value
:setTagArray(tags)

Changed in version 1.7.0: Prior to 1.7.0 calling DNSQuestion:setTagArray() would not overwrite existing tag values if already set.

Set an array of tags into the DNSQuestion object. Overwrites the values if any already exist.

Parameters:tags (table) – A table of tags, using strings as keys and values
:setTrailingData(tail) → bool

New in version 1.4.0.

Set the data following the DNS message, overwriting anything already present.

Parameters:tail (string) – The new data
Returns:true if the operation succeeded, false otherwise
:spoof(ip|ips|raw|raws)

New in version 1.6.0.

Forge a response with the specified record data as raw bytes. If you specify list of raws (it is assumed they match the query type), all will get spoofed in.

Parameters:
  • ip (ComboAddress) – The ComboAddress to be spoofed, e.g. newCA(“192.0.2.1”).
  • ComboAddresses ips (table) – The ComboAddress`es to be spoofed, e.g. `{ newCA(“192.0.2.1”), newCA(“192.0.2.2”) }.
  • raw (string) – The raw string to be spoofed, e.g. “\192\000\002\001”.
  • raws (table) – The raw strings to be spoofed, e.g. { “\192\000\002\001”, “\192\000\002\002” }.
:suspend(asyncID, queryID, timeoutMS) → bool

New in version 1.8.0.

Suspend the processing for the current query, making it asynchronous. The query is then placed into memory, in a map called the Asynchronous Holder, until it is either resumed or the supplied timeout kicks in. The object is stored under a key composed of the tuple (asyncID, queryID) which is needed to retrieve it later, which can be done via getAsynchronousObject(). Note that the DNSQuestion object should NOT be accessed after successfully calling this method. Returns true on success and false on failure, indicating that the query has not been suspended and the normal processing will continue.

Parameters:
  • asyncID (int) – A numeric identifier used to identify the suspended query for later retrieval. Valid values range from 0 to 65535, both included.
  • queryID (int) – A numeric identifier used to identify the suspended query for later retrieval. This ID does not have to match the query ID present in the initial DNS header. A given (asyncID, queryID) tuple should be unique at a given time. Valid values range from 0 to 65535, both included.
  • timeoutMS (int) – The maximum duration this query will be kept in the asynchronous holder before being automatically resumed, in milliseconds.

DNSResponse object

class DNSResponse

This object has almost all the functions and members of a DNSQuestion, except for the following ones which are not available on a response:

  • addProxyProtocolValue
  • ecsOverride
  • ecsPrefixLength
  • getProxyProtocolValues
  • getHTTPHeaders
  • getHTTPHost
  • getHTTPPath
  • getHTTPQueryString
  • setHTTPResponse
  • getHTTPScheme
  • getServerNameIndication
  • setNegativeAndAdditionalSOA
  • setProxyProtocolValues
  • spoof
  • tempFailureTTL
  • useECS

If the value is really needed while the response is being processed, it is possible to set a tag while the query is processed, as tags will be passed to the response object. It also has one additional method:

:editTTLs(func)

The function func is invoked for every entry in the answer, authority and additional section.

func points to a function with the following prototype: myFunc(section, qclass, qtype, ttl)

All parameters to func are integers:

  • section is the section in the packet and can be compared to DNS Packet Sections
  • qclass is the QClass of the record. Can be compared to DNSClass
  • qtype is the QType of the record. Can be e.g. compared to DNSQType.A, DNSQType.AAAA constants and the like.
  • ttl is the current TTL

This function must return an integer with the new TTL. Setting this TTL to 0 to leaves it unchanged

Parameters:func (string) – The function to call to edit TTLs.
:restart()

New in version 1.8.0.

Discard the received response and restart the processing of the query. For this function to be usable, the query should have been made restartable first, via DNSQuestion:setRestartable(). For example, to restart the processing after selecting a different pool of servers:

function makeQueryRestartable(dq)
  -- make it possible to restart that query later
  -- by keeping a copy of the initial DNS payload around
  dq:setRestartable()
  return DNSAction.None
end
function restartOnServFail(dr)
  if dr.rcode == DNSRCode.SERVFAIL then
    -- assign this query to a new pool
    dr.pool = 'restarted'
    -- discard the received response and
    -- restart the processing of the query
    dr:restart()
  end
  return DNSResponseAction.None
end
addAction(AllRule(), LuaAction(makeQueryRestartable))
addResponseAction(AllRule(), LuaResponseAction(restartOnServFail))

DNSHeader (dh) object

class DNSHeader

This object holds a representation of a DNS packet’s header.

:getAA() → bool

Get authoritative answer flag.

:getAD() → bool

Get authentic data flag.

:getCD() → bool

Get checking disabled flag.

:getID() → int

New in version 1.8.0.

Get the ID.

:getRA() → bool

Get recursion available flag.

:getRD() → bool

Get recursion desired flag.

:setAA(aa)

Set authoritative answer flag.

Parameters:aa (bool) – State of the AA flag
:setAD(ad)

Set authentic data flag.

Parameters:ad (bool) – State of the AD flag
:setCD(cd)

Set checking disabled flag.

Parameters:cd (bool) – State of the CD flag
:setQR(qr)

Set Query/Response flag. Setting QR to true means “This is an answer packet”.

Parameters:qr (bool) – State of the QR flag
:setRA(ra)

Set recursion available flag.

Parameters:ra (bool) – State of the RA flag
:setRD(rd)

Set recursion desired flag.

Parameters:rd (bool) – State of the RD flag
:setTC(tc)

Set truncation flag (TC).

Parameters:tc (bool) – State of the TC flag

EDNSOptionView object

class EDNSOptionView

An object that represents the values of a single EDNS option received in a query.

:count()

The number of values for this EDNS option.

:getValues()

Return a table of NULL-safe strings values for this EDNS option.

AsynchronousObject object

class AsynchronousObject

New in version 1.8.0.

This object holds a representation of a DNS query or response that has been suspended.

:drop() → bool

Drop that object immediately, without resuming it. Returns true on success, false on failure.

:getDQ() → DNSQuestion

Return a DNSQuestion object for the suspended object.

:getDR() → DNSResponse

Return a DNSResponse object for the suspended object.

:resume() → bool

Resume the processing of the suspended object. For a question, it means first checking whether it was turned into a response, and sending the response out it it was. Otherwise do a cache-lookup: on a cache-hit, the response will be sent immediately. On a cache-miss, it means dnsdist will select a backend and send the query to the backend. For a response, it means inserting into the cache if needed and sending the response to the backend. Note that the AsynchronousObject object should NOT be accessed after successfully calling this method. Returns true on success, false on failure.

:setRCode(rcode, clearRecords) → bool

Set the response code in the DNS header of the current object to the supplied value, optionally removing all records from the existing payload, if any. Returns true on success, false on failure.

Parameters:
  • code (int) – The response code to set
  • clearRecords (bool) – Whether to clear all records from the existing payload, if any
getAsynchronousObject(asyncID, queryID) → AsynchronousObject

New in version 1.8.0.

Retrieves an asynchronous object stored into the Asynchronous holder.

param int asyncID:
 A numeric identifier used to identify the query when it was suspended
param int queryID:
 A numeric identifier used to identify the query when it was suspended