# dnsdist DNS proxy [dnsdist](https://dnsdist.org/) is a highly configurable DNS-, DoS- and abuse-aware loadbalancer. Here's an example configuration file: ``` -- File: /etc/dnsdist/dnsdist.conf -- listen for console connection with the given secret key controlSocket("0.0.0.0:53530") setKey("supersecretAPIkey") setConsoleACL({"172.16.16.0/24","192.168.168.0/24","10.10.20.0/24"}) -- start and configure the web server webserver("0.0.0.0:8053") setWebserverConfig({password="supersecretpassword", apiKey="supersecretAPIkey"}, acl="172.16.16.0/24,192.168.168.0/24,10.10.20.0/24") -- accept DNS queries on UDP/53 and TCP/53 addLocal("0.0.0.0:53") -- accept DNS queries on UDP/5200 and TCP/5200 -- addLocal("0.0.0.0:5200") -- fix up possibly badly truncated answers from pdns 2.9.22 truncateTC(true) -- Log message warnlog(string.format("Script starting %s", "up!")) -- define the server pools -- public-google newServer({address="8.8.8.8", pool="public-google", checkInterval=300}) newServer({address="8.8.4.4", pool="public-google", checkInterval=300}) -- public-cloudflare newServer({address="1.1.1.1", pool="public-cloudflare", checkInterval=300}) -- public-quad9 newServer({address="9.9.9.9", pool="public-quad9", checkInterval=300}) newServer({address="149.112.112.112", pool="public-quad9", checkInterval=300}) -- internal pools newServer({address="192.168.1.53", pool="company1-auth", checkInterval=300}) newServer({address="192.168.2.53", pool="company2-auth", checkInterval=300}) newServer({address="192.168.3.53", pool="company3-auth", checkInterval=300}) -- local router newServer({address="172.16.16.254", pool="router", checkInterval=300}) newServer({address="127.0.0.1:53531", pool="nodeapp1", checkInterval=300}) -- switch the server balancing policy to round robin, -- the default being least outstanding queries setServerPolicy(roundrobin) addAction({"camera.project1.loc.", "device.project1.loc."}, PoolAction("nodeapp1")) addAction({"company1.loc"}, PoolAction("company1-auth")) addAction({"company2.loc"}, PoolAction("company2-auth")) addAction({"company3.loc"}, PoolAction("company3-auth")) addAction(AllRule(), PoolAction("public-google")) -- addAction(AllRule(), PoolAction("public-cloudflare")) -- addAction(AllRule(), PoolAction("public-quad9")) -- addAction(AllRule(), PoolAction("router")) -- refuse all queries not having exactly one question -- addAction(NotRule(RecordsCountRule(DNSSection.Question, 1, 1)), RCodeAction(DNSRCode.REFUSED)) -- return 'refused' for domains matching the regex evil[0-9]{4,}.powerdns.com$ -- addAction(RegexRule("evil[0-9]{4,}\\.powerdns\\.com$"), RCodeAction(DNSRCode.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 addAction("luaspoof1.powerdns.com.", LuaAction(spoof1rule)) addAction("luaspoof2.powerdns.com.", LuaAction(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)) --]] ``` -end