Skip to content

Instantly share code, notes, and snippets.

@zoonderkins
Created April 14, 2019 09:07
Show Gist options
  • Save zoonderkins/adb438727aeaacfb7b9ea4b574255de6 to your computer and use it in GitHub Desktop.
Save zoonderkins/adb438727aeaacfb7b9ea4b574255de6 to your computer and use it in GitHub Desktop.
dnsdist config
-- listen for console connection with the given secret key
-- controlSocket("0.0.0.0")
-- setKey(please generate a fresh private key with makeKey())

-- start the web server on port 8083, using password 'set a random password here'
-- webserver("0.0.0.0:8083", "set a random password here")

-- accept DNS queries on UDP/5200 and TCP/5200
addLocal("0.0.0.0:5200")

-- send statistics to PowerDNS metronome server
-- carbonServer("2001:888:2000:1d::2")

-- fix up possibly badly truncated answers from pdns 2.9.22
truncateTC(true)

warnlog(string.format("Script starting %s", "up!"))

-- define the good servers
newServer("8.8.8.8", 2)  -- 2 qps
newServer("8.8.4.4", 2)
newServer("208.67.222.222", 1)
newServer("208.67.220.220", 1)
newServer("2001:4860:4860::8888", 1)
newServer("2001:4860:4860::8844",1)
newServer("2620:0:ccc::2", 10)
newServer("2620:0:ccd::2", 10)
newServer({address="192.168.1.2", qps=1000, order=2})
newServer({address="192.168.1.79:5300", order=2})
newServer({address="127.0.0.1:5300", order=3})
newServer({address="192.168.1.30:5300", pool="abuse"})

-- switch the server balancing policy to round robin,
-- the default being least outstanding queries
-- setServerPolicy(roundrobin)

-- send the queries for selected domain suffixes to the server
-- in the 'abuse' pool
addAction({"ezdns.it.", "xxx."}, PoolAction("abuse"))

-- send the queries from a selected subnet to the
-- abuse pool
addAction("192.168.1.0/24", PoolAction("abuse"))

-- send the queries for the "com" suffix to the "abuse"
-- pool, but only up to 100 qps
addAction("com.", QPSPoolAction(100, "abuse"))

-- declare a Lua action function, routing NAPTR queries
-- to the abuse pool
function luarule(dq)
	if(dq.qtype==dnsdist.NAPTR)
	then
		return DNSAction.Pool, "abuse" -- send to abuse pool
	else
		return DNSAction.None, ""      -- no action
	end
end
-- send only queries from the selected subnet to
-- the luarule function
addLuaAction("192.168.1.0/24", luarule)

-- drop queries exceeding 5 qps, grouped by /24 for IPv4
-- and /64 for IPv6
addAction(MaxQPSIPRule(5, 24, 64), DropAction())

-- move the last rule to the first position
topRule()

-- drop queries for the following suffixes:
addAction("powerdns.org.", DropAction())
addAction("spectre.", DropAction())

-- called before we distribute a question
block=newDNSName("powerdns.org.")
truncateNMG = newNMG()
truncateNMG:addMask("213.244.0.0/16")
truncateNMG:addMask("2001:503:ba3e::2:30")
truncateNMG:addMask("fe80::/16")

print(string.format("Have %d entries in truncate NMG", truncateNMG:size()))

-- called to pick a downstream server, ignores 'up' status
counter=0
function luaroundrobin(servers, dq)
	 counter=counter+1;
	 return servers[1+(counter % #servers)]
end
-- setServerPolicyLua("luaroundrobin", luaroundrobin)

newServer({address="2001:888:2000:1d::2", pool={"auth", "dnssec"}})
newServer({address="2a01:4f8:110:4389::2", pool={"auth", "dnssec"}})
--addAction(DNSSECRule(), PoolAction("dnssec"))
--topRule()

-- split queries between the 'auth' pool and the regular one,
-- based on the RD flag
function splitSetup(servers, dq)
	 if(dq.dh:getRD() == false)
	 then
		return firstAvailable.policy(getPoolServers("auth"), dq)
	 else
		return firstAvailable.policy(servers, dq)
	 end
end
-- setServerPolicyLua("splitSetup", splitSetup)

-- the 'maintenance' function is called every second
function maintenance()
	 -- block all hosts that exceeded 20 qps over the past 10s,
	 -- for 60s
	 addDynBlocks(exceedQRate(20, 10), "Exceeded query rate", 60)
end

-- allow queries for the domain powerdns.com., drop everything else
-- addAction(makeRule("powerdns.com."), AllowAction())
-- addAction(AllRule(), DropAction())

-- clear the RD flag in queries for powerdns.com.
-- addAction("powerdns.com.", NoRecurseAction())

-- set the CD flag in queries for powerdns.com.
-- addAction("powerdns.com.", DisableValidationAction())

-- delay all responses for 1000ms
-- addAction(AllRule(), DelayAction(1000))

-- truncate ANY queries over UDP only
-- addAction(AndRule{QTypeRule(dnsdist.ANY), TCPRule(false)}, TCAction())

-- truncate ANY queries over TCP only
-- addAction(AndRule({QTypeRule(dnsdist.ANY), TCPRule(true)}), TCAction())
-- can also be written as:
-- addAction(AndRule({QTypeRule("ANY"), TCPRule(true)}), TCAction())

-- return 'not implemented' for qtype != A over UDP
-- addAction(AndRule({NotRule(QTypeRule("A")), TCPRule(false)}), RCodeAction(dnsdist.NOTIMP))

-- return 'not implemented' for qtype == A OR received over UDP
-- addAction(OrRule({QTypeRule("A"), TCPRule(false)}), RCodeAction(dnsdist.NOTIMP))

-- log all queries to a 'dndist.log' file, in text-mode (not binary) appending and unbuffered
-- addAction(AllRule(), LogAction("dnsdist.log", false, true, false))

-- drop all queries with the DO flag set
-- addAction(DNSSECRule(), DropAction())

-- drop all queries for the CHAOS class
-- addAction(QClassRule(3), DropAction())
-- addAction(QClassRule(DNSClass.CHAOS), DropAction())

-- drop all queries with the UPDATE opcode
-- addAction(OpcodeRule(DNSOpcode.Update), DropAction())

-- refuse all queries not having exactly one question
-- addAction(NotRule(RecordsCountRule(DNSSection.Question, 1, 1)), RCodeAction(dnsdist.REFUSED))

-- return 'refused' for domains matching the regex evil[0-9]{4,}.powerdns.com$
-- addAction(RegexRule("evil[0-9]{4,}\\.powerdns\\.com$"), RCodeAction(dnsdist.REFUSED))

-- spoof responses for A, AAAA and ANY for spoof.powerdns.com.
-- A queries will get 192.0.2.1, AAAA 2001:DB8::1 and ANY both
-- addAction("spoof.powerdns.com.", SpoofAction({"192.0.2.1", "2001:DB8::1"}))

-- spoof responses will multiple records
-- A will get 192.0.2.1 and 192.0.2.2, AAAA 20B8::1 and 2001:DB8::2
-- ANY all of that
-- addAction("spoof.powerdns.com", SpoofAction({"192.0.2.1", "192.0.2.2", "20B8::1", "2001:DB8::2"}))

-- spoof responses with a CNAME
-- addAction("cnamespoof.powerdns.com.", SpoofCNAMEAction("cname.powerdns.com."))

-- spoof responses in Lua
--[[
    function spoof1rule(dq)
        if(dq.qtype==1) -- A
        then
                return DNSAction.Spoof, "192.0.2.1"
        elseif(dq.qtype == 28) -- AAAA
        then
                return DNSAction.Spoof, "2001:DB8::1"
        else
                return DNSAction.None, ""
        end
    end
    function spoof2rule(dq)
        return DNSAction.Spoof, "spoofed.powerdns.com."
    end
    addLuaAction("luaspoof1.powerdns.com.", spoof1rule)
    addLuaAction("luaspoof2.powerdns.com.", spoof2rule)

--]]

-- alter a protobuf response for anonymization purposes
--[[
function alterProtobuf(dq, protobuf)
    requestor = newCA(dq.remoteaddr:toString())
    if requestor:isIPv4() then
        requestor:truncate(24)
    else
        requestor:truncate(56)
    end
    protobuf:setRequestor(requestor)
end

rl = newRemoteLogger("127.0.0.1:4242")
addAction(AllRule(), RemoteLogAction(rl, alterProtobuf))
--]]


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment