Experimente mit “dnsdist”

Ich betreibe ja “aus Spaß” einen authoritativen Bind9 Nameserver. (Fragt nicht.) Jetzt kam der Gedanke auf, dass man den doch “besser absichern” könnte, sowas wie sshguard oder fail2ban für Bind9.

Eine kurze Recherche später war “dnsdist” gefunden, es war als Paket meiner Distribution verfügbar und los geht der Spaß. Viele Fehlversuche später (Das Config-File ist nicht eben “menschenfreundlich”.) hab ich das Teil deinstalliert und fahre wieder den nackten Bind9. Nicht dass dnsdist schlecht wäre, nie nicht, aber es ist wie in einer Beziehung: Man passt zueinander oder eben nicht.

Nevertheless, falls es vllt. mal irgendjemandem hilft, hier ist eine funktionierende Config mit Log nach /var/log/dnsdist.log und einem Bind9 Backend, das auf localhost Port 5353 lauscht. Wie immer alles ohne Garantie und Gewähr, das war einfach ein kurzes Spaßprojekt. Schaut auf Owner, Group und Rechte des Configfiles, macht Gebrauch von “dnsdist –check-config -C /path/to/dnsdist.conf”. Das Übliche halt. Und BITTE checkt, ob ihr damit nicht versehentlich einen Open-Resolver baut, das ist wichtig.

-- Log queries (5 parameters)
-- Parameters: filename, binary, append, buffered, verboseOnly
addAction(AllRule(), LogAction("/var/log/dnsdist.log", false, true, false, false))

-- Log responses (5 parameters)
-- Parameters: filename, binary, append, buffered, verboseOnly
addResponseAction(AllRule(), LogResponseAction("/var/log/dnsdist.log", false, true, false, false))

-- Log cache hits (5 parameters)
-- Parameters: filename, binary, append, buffered, verboseOnly
addCacheHitResponseAction(AllRule(), LogResponseAction("/var/log/dnsdist.log", false, true, false, false))

-- Log self-answered repsonse (5 parameters)
-- Parameters: filename, binary, append, buffered, verboseOnly
addSelfAnsweredResponseAction(AllRule(), LogResponseAction("/var/log/dnsdist.log", false, true, false, false))

-- 1. Listener & Backend
addLocal('0.0.0.0:53', { reusePort=true, tcpFastOpenQueueSize=100, interface="eth0" })
newServer({address="127.0.0.1:5353", name="bind-main", healthCheckMode='lazy'})
setACL({'0.0.0.0/0'}) -- Opens the door; security is handled below

-- 2. Initialize Dynamic Blocking & Whitelist
local dbr = dynBlockRulesGroup()
dbr:excludeRange({"127.0.0.1/8"}) -- WHITELIST

-- 3. Static Security Rules (Applied to EVERY query immediately)
addAction(QTypeRule(DNSQType.ANY), TCAction()) -- Force ANY to TCP

local cnDomains = newSuffixMatchNode()
cnDomains:add("cn")
addAction(SuffixMatchNodeRule(cnDomains), DropAction())

-- 4. Dynamic Rules (Fail2ban style)
dbr:setQueryRate(20, 10, "Exceeded query rate", 60)
dbr:setRCodeRate(DNSRCode.NXDOMAIN, 5, 10, "Exceeded NXDOMAIN rate", 60)
dbr:setRCodeRate(DNSRCode.SERVFAIL, 2, 10, "Exceeded SERVFAIL rate", 60)
dbr:setRCodeRate(DNSRCode.REFUSED, 1, 30, "Exceeded REFUSED rate", 60)

-- 5. Maintenance Loop
function maintenance()
dbr:apply()
end