
(Part 3 - Load Balancing With DNSdist)
Created: 2021-04-21 Wed 16:25


Welcome to part three of our BIND 9 webinar series
























leastOutstanding: use the server with the least outstanding
queries (possibly least load)chashed: distribute based on hashes of the query name (sticky
queries)whashed: distribute based on hashes of the query name (sticky
queries), but apply the configured weight for the back-end serverwrandom: distribute random, but with a weight applied. Back-end
server receive the share of queries based on their configured
weightroundrobin: distribute queries to all back-end server based on an
round-robin algorithm (send each query to the next server)

counter=0
function luaroundrobin(servers, dq)
counter=counter+1
return servers[1+(counter % #servers)]
end
setServerPolicyLua("luaroundrobin", luaroundrobin)












> getPool(""):getCache():printStats()
Entries: 122/10000
Hits: 9147
Misses: 10147
Deferred inserts: 1
Deferred lookups: 0
Lookup Collisions: 0
Insert Collisions: 0
TTL Too Shorts: 0














dnsdist.conf
(usually in /etc/dnsdist)


dnsdist.conf
---- Listen addresses
addLocal('192.0.2.1:53', { reusePort=true })
addLocal('127.0.0.1:53', { reusePort=true })
addLocal('[::1]:53', { reusePort=true })
addLocal('[2001:db8::1]:53', { reusePort=true })
---- Back-end server
newServer({address="192.0.2.100", qps=10000, order=1})
newServer({address="2001:db8:100::5353", qps=100, order=3})
newServer({address="2001:db8:200::6312", qps=100, order=2})
---- Policy
setServerPolicy(whashed)
setACL({'192.0.2.0/24', '2001:db8::/64'})
---- Cache
pc = newPacketCache(10000, {maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false})
getPool(""):setCache(pc)
---- Web-server
webserver("192.0.2.1:8083")
setWebserverConfig({acl="192.0.2.10/32",password="dnsdist-is-great"})
--- Console
controlSocket('127.0.0.1:5199')
setKey("2ux3QDmpdDAzYjspexaspAdqnXF8jXFU5qhd/BqXV8ag=")
---- Filter Rules
addAction(RegexRule(".*\\.facebook\\..*$"), RCodeAction(DNSRCode.REFUSED))
addAction(RegexRule(".*\\.doubleclick\\..*$"), RCodeAction(DNSRCode.REFUSED))


$ /bin/dnsdist -c
> showServers()
198.51.100.12# Name Address State Qps Qlim Ord Wt Queries Drops Drate Lat Outstanding Pools
0 192.0.2.53:53 192.0.2.53:53 up 1.0 10000 1 1 10088 132 0.0 9.2 0
1 198.51.100.12:53 198.51.100.12:53 up 0.0 100 2 1 1391 2 0.0 44.5 0
2 203.0.113.11:53 203.0.113.11:53 up 0.0 100 3 1 318 0 0.0 65.3 0
All 0.0 11797 134
> newServer({address="1.1.1.1", qps=10000, order=1})
1.1.1.1:53
> showServers()
# Name Address State Qps Qlim Ord Wt Queries Drops Drate Lat Outstanding Pools
0 192.0.2.53:53 192.0.2.53:53 up 0.0 10000 1 1 10103 132 0.0 8.9 0
1 1.1.1.1:53 1.1.1.1:53 up 0.0 10000 1 1 3 0 0.0 0.3 0
2 198.51.100.12:53 198.51.100.12:53 up 0.0 100 2 1 1392 2 0.0 44.4 0
3 203.0.113.11:53 203.0.113.11:53 up 0.0 100 3 1 319 0 0.0 65.2 0
All 0.0 11817 134
>


---- Webserver
webserver("192.0.2.1:8083")
setWebserverConfig({acl="192.0.2.10/32",password="dnsdist-is-great"})








Example dnsdist configuration:
carbonServer('192.0.2.210', 'dnsdist.isp.example', 30, 'dnsdist', 'main')


/metrics URL
endpoint of the Web-API

pc = newPacketCache(10000, --- create a new pool cache "pc" with 10.000 entries
{
maxTTL=86400, --- maximum TTL cache time
minTTL=0, --- minimum TTL cache time
temporaryFailureTTL=60, --- TTL used for server failures or "refused"
staleTTL=60, --- TTL for stale cache entries
dontAge=false --- cache entries "age", their TTL is decremented in cache
})
getPool(""):setCache(pc) --- assign the cache to the default pool




a.root-servers.net
A-Record towards the downstream server
isc.org:
newServer({address="51.75.79.143", checkType="SOA", checkType=DNSClass.IN, checkName="isc.org"})
newServer({address="199.6.1.52", checkType="SOA", checkType=DNSClass.IN, checkName="isc.org"})
newServer({address="199.254.63.254", checkType="SOA", checkType=DNSClass.IN, checkName="isc.org"})
newServer({address="149.20.1.73", checkType="SOA", checkType=DNSClass.IN, checkName="isc.org"})
setServerPolicy(leastOutstanding)
setLocal("192.0.2.123:53")
[...]


primary, which only contains one
primary authoritative server
newServer({
address="192.0.2.123",
name="primary",
pool={"primary", "otherpool"}
})
addAction(
OrRule({
QTypeRule(DNSQType.SOA),
QTypeRule(DNSQType.AXFR),
QTypeRule(DNSQType.IXFR)}),
PoolAction("primary")
)


source parameter tells dnsdist which IP-address or
interface to use for outgoing queries:
newServer({address="192.0.2.1", source="192.0.2.127"})
newServer({address="192.0.2.1", source="eth1"})
newServer({address="192.0.2.1", source="192.0.2.127@eth1"})


mname fieldnsupdate) to use a dedicated IP address:nsupdate > ttl 3600 > server 192.0.2.221 > add www.example.com. IN A 192.0.2.212 > send


notify messages to
all secondaries configured in the NS records
notify from trusted source addressesnotify can be configured explicitly on the
authoritative servers. Example for BIND 9:
zone "example.com" {
type primary;
file "example.com";
notify explicit;
also-notify { 192.0.2.53; 198.51.100.12; };
};




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) function maintenance() dbr:apply() end






firstAvailable will
create a simple fail-over configuration
---- Back-end server
newServer({address="192.0.2.100", qps=1000, order=1})
newServer({address="2001:db8:100::5353", qps=500, order=2})
newServer({address="2001:db8:200::6312", qps=500, order=3})
---- Policy
setServerPolicy(firstAvailable)
setACL({'192.0.2.0/24', '2001:db8::/64'})
---- Cache
pc = newPacketCache(10000, {maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false})
getPool(""):setCache(pc)
[...]


---- Back-end server
newServer({address="192.0.2.100", order=1})
newServer({address="2001:db8:100::5353", order=3})
newServer({address="2001:db8:200::6312", order=2})
---- Policy
setServerPolicy(leastOutstanding)
setACL({'192.0.2.0/24', '2001:db8::/64'})
---- Cache
pc = newPacketCache(10000, {maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false})
getPool(""):setCache(pc)
[...]


-- Add a backend server with address 192.0.2.3 and assign it to the "abuse" pool
newServer({address="192.0.2.3", pool="abuse"})
-- Send all queries for "bad-domain1.example." and "bad-domain2.example" to the "abuse" pool
addAction({'bad-domain1.example', 'bad-domain2.example.'}, PoolAction("abuse"))












