This guide covers configuration of dnsdist using both Lua (traditional) and YAML (v2.0+) formats.
⚠️ Version Note:
- Version 2.0.x supports both Lua and YAML configuration (YAML requires Rust)
- Version 2.1.0-alpha1 uses YAML as default configuration format
- Configuration files:
/etc/dnsdist/dnsdist.conf(Lua),/etc/dnsdist/dnsdist.yml(YAML)
Location: /etc/dnsdist/dnsdist.conf
Structure:
-- Listen addresses
addLocal("0.0.0.0:53")
-- Backend servers
newServer{address="192.168.1.10:53"}
-- Load balancing policy
setServerPolicy(roundrobin)
-- Web interface
webserver("127.0.0.1:8083", "password")
Location: /etc/dnsdist/dnsdist.yml
Structure:
servers:
- address: "192.168.1.10:53"
listen:
- "0.0.0.0:53"
load_balancing:
policy: roundrobin
webserver:
address: "127.0.0.1:8083"
password: "password"
# Check configuration syntax
dnsdist --check-config
# Test with specific file
dnsdist --config=/etc/dnsdist/dnsdist.conf --check
dnsdist --config=/etc/dnsdist/dnsdist.yml --check
-- Listen on all interfaces
addLocal("0.0.0.0:53")
addLocal(":::53")
-- Backend servers
newServer{address="192.168.1.10:53"}
newServer{address="192.168.1.11:53"}
-- Load balancing policy
setServerPolicy(roundrobin)
-- Web interface (localhost only)
webserver("127.0.0.1:8083", "secure_password")
listen:
- "0.0.0.0:53"
- ":::53"
servers:
- address: "192.168.1.10:53"
- address: "192.168.1.11:53"
load_balancing:
policy: roundrobin
webserver:
address: "127.0.0.1:8083"
password: "secure_password"
Lua:
-- Basic backend
newServer{address="192.168.1.10:53"}
-- With weight
newServer{address="192.168.1.10:53", weight=10}
-- With pool
newServer{address="192.168.1.10:53", pool="primary"}
-- With health checks
newServer{
address="192.168.1.10:53",
checkInterval=10,
checkTimeout=2
}
YAML:
servers:
- address: "192.168.1.10:53"
weight: 10
- address: "192.168.1.11:53"
pool: "primary"
- address: "192.168.1.12:53"
health_check:
interval: 10
timeout: 2
Available Policies:
| Policy | Description | Use Case |
|---|---|---|
roundrobin |
Distribute evenly | General purpose |
firstAvailable |
Use first available | Primary/backup |
leastOutstanding |
Least busy server | Variable load |
hashed |
Hash-based distribution | Session affinity |
latencyOrder |
Lowest latency first | Geographic distribution |
wrandom |
Weighted random | Weighted distribution |
Lua:
-- Round robin (default)
setServerPolicy(roundrobin)
-- First available (primary/backup)
setServerPolicy(firstAvailable)
-- Least outstanding queries
setServerPolicy(leastOutstanding)
-- Hashed by query name
setServerPolicy(hashed)
YAML:
load_balancing:
policy: roundrobin # firstAvailable, leastOutstanding, hashed, latencyOrder, wrandom
Lua:
-- Define pools
newServer{address="192.168.1.10:53", pool="primary"}
newServer{address="192.168.1.11:53", pool="primary"}
newServer{address="192.168.1.20:53", pool="backup"}
-- Route to pools
addAction(
SuffixRule("internal.example.com"),
PoolAction("primary")
)
-- Default pool
setPoolServerPolicy("primary", roundrobin)
YAML:
servers:
- address: "192.168.1.10:53"
pool: "primary"
- address: "192.168.1.20:53"
pool: "backup"
pools:
primary:
policy: roundrobin
backup:
policy: firstAvailable
Lua:
-- DoT listener
addTLSLocal("0.0.0.0:853",
"/etc/dnsdist/dnsdist.crt",
"/etc/dnsdist/dnsdist.key")
-- TLS configuration
setTLSConfig({
ciphers = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384",
ciphers13 = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256",
minTLSVersion = "TLSv1.2"
})
YAML:
tls:
listen:
- address: "0.0.0.0:853"
cert: "/etc/dnsdist/dnsdist.crt"
key: "/etc/dnsdist/dnsdist.key"
config:
ciphers: "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384"
ciphers13: "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256"
min_tls_version: "TLSv1.2"
Lua:
-- Forward to upstream over TLS
newServer{
address="1.0.0.1:853",
tls="cloudflare-dns.com"
}
YAML:
servers:
- address: "1.0.0.1:853"
tls:
hostname: "cloudflare-dns.com"
Lua:
-- DoH listener (nghttp2 backend)
addDOHLocal("0.0.0.0:443",
"/etc/dnsdist/dnsdist.crt",
"/etc/dnsdist/dnsdist.key",
"/dns-query")
-- DoH configuration
setDOHConfig({
path = "/dns-query",
trusted_proxies = {"10.0.0.0/8", "192.168.0.0/16"}
})
YAML:
doh:
listen:
- address: "0.0.0.0:443"
cert: "/etc/dnsdist/dnsdist.crt"
key: "/etc/dnsdist/dnsdist.key"
path: "/dns-query"
trusted_proxies:
- "10.0.0.0/8"
- "192.168.0.0/16"
Lua:
-- API key authentication
addDOHLocal("0.0.0.0:443",
"/etc/dnsdist/dnsdist.crt",
"/etc/dnsdist/dnsdist.key",
"/dns-query",
{
apiKeys = {"secret-key-1", "secret-key-2"}
})
Lua:
-- Global rate limit
addAction(AllRule(), MaxQPSRule(10000))
-- Per-IP rate limit
addAction(AllRule(), MaxQPSIPRule(50, 100)) -- 50 sustained, 100 burst
YAML:
rate_limiting:
- rule: "all"
qps: 10000
action: "drop"
- rule: "per_ip"
qps: 50
burst: 100
action: "drop"
Lua:
-- Limit ANY queries (amplification attack)
addAction(
AndRule({QTypeRule("ANY")}),
DropAction()
)
-- Limit TXT queries
addAction(
AndRule({QTypeRule("TXT"), MaxQPSRule(100)}),
DropAction()
)
YAML:
rate_limiting:
- query_type: "ANY"
action: "drop"
- query_type: "TXT"
qps: 100
action: "drop"
Lua:
-- Enable cache
setPacketCacheSize(100000)
-- Cache TTL settings
setECSServFailTTL(60)
setServFailTTL(60)
setTempFailureTTL(60)
setCacheCleaningDelay(3600)
YAML:
cache:
packet_cache:
size: 100000
servfail_ttl: 60
temp_failure_ttl: 60
cleaning_delay: 3600
Lua:
-- Bypass cache for specific domains
addAction(
SuffixRule("nocache.example.com"),
NoCacheAction()
)
Lua:
-- Set ACL
setACL({"10.0.0.0/8", "192.168.0.0/16", "172.16.0.0/12"})
-- Block specific networks
addAction(
NetGroupRule({"198.51.100.0/24"}),
DropAction()
)
YAML:
acl:
allow:
- "10.0.0.0/8"
- "192.168.0.0/16"
- "172.16.0.0/12"
deny:
- "198.51.100.0/24"
Lua:
-- Block specific domains
addAction(
SuffixRule("malware-domain.com"),
DropAction()
)
-- Block specific query types
addAction(
QTypeRule("ANY"),
DropAction()
)
YAML:
filters:
- type: "suffix"
pattern: "malware-domain.com"
action: "drop"
- type: "query_type"
qtype: "ANY"
action: "drop"
Lua:
-- Enable web interface
webserver("127.0.0.1:8083", "secure_password")
-- With ACL
setACL({"127.0.0.0/8", "::1/128"})
YAML:
webserver:
address: "127.0.0.1:8083"
password: "secure_password"
acl:
- "127.0.0.0/8"
- "::1/128"
# Access API
curl -u dnsdist:secure_password http://localhost:8083/api/v1/servers/localhost
# Get statistics
curl -u dnsdist:secure_password http://localhost:8083/api/v1/servers/localhost/statistics
-- Complex rule with multiple conditions
addAction(
AndRule({
QTypeRule("A"),
SuffixRule("example.com"),
NetGroupRule({"10.0.0.0/8"})
}),
PoolAction("internal")
)
-- Custom action with Lua function
addAction(
SuffixRule("rewrite.example.com"),
LuaAction(function(dq)
dq:setQuestionName(newDN("target.example.com"))
return DNSAction.None
end)
)
-- Modify responses
addResponseAction(
SuffixRule("example.com"),
LuaResponseAction(function(dr)
-- Modify response
return DNSResponseAction.None
end)
)
-- Log specific queries
addAction(
SuffixRule("log.example.com"),
LogAction("/var/log/dnsdist/specific.log", true, true, true)
)
Squeezing every bit of performance from your dnsdist installation? Our experts help with:
Optimize your setup: office@linux-server-admin.com | Contact Us