feat: Route traffic to other resolvers to reduce load on HSD
All checks were successful
Build Docker / Build_Docker (push) Successful in 2m49s

This commit is contained in:
2025-08-15 14:27:04 +10:00
parent 6885ac2783
commit dadb53ba5e
4 changed files with 1541 additions and 19 deletions

View File

@@ -1,38 +1,102 @@
-- --- Dynamic block rules
local dbr = dynBlockRulesGroup()
dbr:setQueryRate(30, 10, "Exceeded query rate", 60)
dbr:setRCodeRate(DNSRCode.NXDOMAIN, 20, 10, "Exceeded NXD rate", 60)
dbr:setRCodeRate(DNSRCode.SERVFAIL, 20, 10, "Exceeded ServFail rate", 60)
dbr:setQTypeRate(DNSQType.ANY, 5, 10, "Exceeded ANY rate", 60)
dbr:setResponseByteRate(10000, 10, "Exceeded resp BW rate", 60)
dbr:setQueryRate(20, 10, "Exceeded query rate", 60)
dbr:setRCodeRate(DNSRCode.NXDOMAIN, 15, 10, "Exceeded NXD rate", 60)
dbr:setRCodeRate(DNSRCode.SERVFAIL, 15, 10, "Exceeded ServFail rate", 60)
dbr:setQTypeRate(DNSQType.ANY, 3, 10, "Exceeded ANY rate", 60)
dbr:setResponseByteRate(8000, 10, "Exceeded resp BW rate", 60)
function maintenance()
dbr:apply()
end
dbr:apply()
addAction(AndRule{MaxQPSIPRule(5), TCPRule(false)}, TCAction())
-- --- Protect against large UDP amplification
-- dnsdist 2.0.0 does not support setMaxUDPSize() or TruncateAction()
-- Use ednsUDPSize in setLocal() to advertise max UDP size
-- Clients requesting larger responses will be truncated automatically
-- drop queries to .lan
-- --- Basic query mitigations
addAction(QTypeRule(DNSQType.ANY), DropAction()) -- Drop ANY queries
addAction(AndRule{QClassRule(3), QNameRule("version.bind")}, DropAction()) -- Block version.bind
-- Drop queries to local TLDs
local sldsToDrop = newSuffixMatchNode()
sldsToDrop:add("lan.")
addAction(SuffixMatchNodeRule(sldsToDrop), DropAction())
addAction(QTypeRule(DNSQType.ANY), DropAction())
newServer({address="127.0.0.1:5353", name="HSD"})
-- Create a node for all IANA TLDs
local tldNode = newSuffixMatchNode()
local tldsFile = io.open("/etc/dnsdist/tlds-alpha-by-domain.txt", "r")
if tldsFile then
for line in tldsFile:lines() do
if not line:match("^#") and line ~= "" then
-- SuffixMatchNode expects lower-case domain with trailing dot
tldNode:add(line:lower() .. ".")
end
end
tldsFile:close()
end
addLocal('0.0.0.0:53', {reusePort=true})
addLocal('[::]:53', {reusePort=true})
addDOHLocal("127.0.0.1:8053", nil, nil, {"/", "/dns-query"}, { reusePort=true, customResponseHeaders={["Access-Control-Allow-Origin"]="*"} })
addTLSLocal('0.0.0.0', '/etc/letsencrypt/live/hnsdoh.com/fullchain.pem', '/etc/letsencrypt/live/hnsdoh.com/privkey.pem', { reusePort=true })
addTLSLocal('[::]', '/etc/letsencrypt/live/hnsdoh.com/fullchain.pem', '/etc/letsencrypt/live/hnsdoh.com/privkey.pem', { reusePort=true })
-- Max QPS per client
addAction(MaxQPSIPRule(15, 24), DropAction())
addAction(MaxQPSIPRule(15, 64), DropAction())
addAction(AndRule{MaxQPSIPRule(5), TCPRule(false)}, TCAction())
-- --- Upstream servers
-- Public resolvers for official TLDs
local cloudflare = newServer({address="1.1.1.1", name="Cloudflare", pool="tldPool"})
local cloudflarealt = newServer({address="1.0.0.1", name="CloudflareALT", pool="tldPool"})
local google = newServer({address="8.8.8.8", name="Google", pool="tldPool"})
local googlealt = newServer({address="8.8.4.4", name="GoogleALT", pool="tldPool"})
cloudflare:setUp()
cloudflarealt:setUp()
google:setUp()
googlealt:setUp()
-- Your local upstream
local localUpstream = newServer({address="127.0.0.1:5353", name="HSD"})
localUpstream:setUp()
-- If domain matches official TLDs -> use tldPool
addAction(SuffixMatchNodeRule(tldNode), PoolAction("tldPool"))
-- Everything else -> use local upstream
-- addAction(PassAction()) -- Queries fall through to defaultPool
-- setServerPolicy("defaultPool")
-- --- Local listeners
addLocal('0.0.0.0:53', { reusePort = true, ednsUDPSize = 1232 }) -- limit UDP response size
addTLSLocal('0.0.0.0', '/etc/letsencrypt/live/hnsdoh.com/fullchain.pem',
'/etc/letsencrypt/live/hnsdoh.com/privkey.pem', { reusePort = true })
-- HTTPS certificates added with Caddy
addDOHLocal("127.0.0.1:8053", nil, nil,
{"/", "/dns-query"}, { reusePort = true, customResponseHeaders = {["Access-Control-Allow-Origin"]="*"} })
-- Uncomment for IPv6 support
-- addLocal('[::]:53', { reusePort = true, ednsUDPSize = 1232 })
-- addTLSLocal('[::]', '/etc/letsencrypt/live/hnsdoh.com/fullchain.pem',
-- '/etc/letsencrypt/live/hnsdoh.com/privkey.pem', { reusePort = true })
-- addACL('[::]/0')
-- Allow public access
addACL('0.0.0.0/0')
addACL('[::]/0')
map = { newDOHResponseMapEntry("^/$", 307, "https://welcome.hnsdoh.com") }
-- --- DOH front-end redirect
dohFE = getDOHFrontend(0)
dohFE:setResponsesMap(map)
if dohFE then
map = { newDOHResponseMapEntry("^/$", 307, "https://welcome.hnsdoh.com") }
dohFE:setResponsesMap(map)
end
-- --- Control socket & key
setKey("csl2icaGACsP3+M9tx55c8+dBxVCnlnqAHEC92P55eo=")
controlSocket('127.0.0.1:5199')