Skip to content
Denis MACHARD edited this page Aug 17, 2023 · 8 revisions

wiki page with dnsdist examples

Configuration examples for DNSdist PowerDNS

This repository contains several configurations examples with focus on

  • DNS security
  • Traffic logging
  • Traffic routing rules

Filter DNS queries based on DoH endpoint

In the below example, we support two DoH local Endpoints and we want to send their traffic to two different PowerDNS instances. Using HTTPPathRegexRule we can match them we a specific pool.

New in version 1.4.0

-- DNS over HTTPS
addDOHLocal("127.0.0.1:8053", nil, nil, "/dns-query", { reusePort=true })
addDOHLocal("127.0.0.1:8054", nil, nil, "/ads", { reusePort=true })

-- Filter DNS queries to backend DNS based on endpoint
newServer({address="127.0.0.1:5454", pool="ads"})
addAction(HTTPPathRegexRule("ads"), PoolAction("ads"))

-- fwd queries to:
newServer({address="127.0.0.1:5353"})

Create a dynamic wildcard DNS

a full working example is here.

This lua code will resolve any domain name with an IP in its hostname to its IP. If no IP matches, then dnsdist will response with client's IP address (whatismyip).

-- Import  LuaJIT - FFI Library
local ffi = require("ffi")

-- Declare inet_pton
ffi.cdef[[
  int inet_pton(int af, const char *src, void *dst);
]]

-- Family IPv4
local AF_INET = 2
local inet = ffi.new("unsigned int [1]")

function luarule(dq)

  -- replace dash with dot
  ip = string.gsub(dq.qname:toString(), "-", ".")
  -- get only digits
  ip = string.match(ip, "%d+%.%d+%.%d+%.%d+")

  -- if not matched, print whatismyip
  if ip == nil then
    return DNSAction.Spoof, dq.remoteaddr:tostring()
  end

  -- Validate IPv4
  if ffi.C.inet_pton(AF_INET, ip , inet) == 1 then
    return DNSAction.Spoof, ip
  else
    return DNSAction.Spoof, dq.remoteaddr:tostring()
  end

end

addAction(AllRule(), LuaAction(luarule))

Flush dnsdist cache for domain when a NOTIFY arrives

Flush all records for a specific zone from dnsdist cache when a NOTIFY packet arrives, also log. Useful if dnsdist used in front of an authoritative server.

-- flush cache for domain, then continue processing
local function onNotifyFlush(dq)
        pdnslog("NOTIFY received, flushing cache for "..dq.qname:toString())
        getPool("my_pool"):getCache():expungeByName(dq.qname, DNSQType.ANY, true)
        return DNSAction.None
end

Send Notify packets to function

-- Flush local cache for zones, then continue processing
addAction(OpcodeRule(DNSOpcode.Notify), LuaAction(onNotifyFlush))