This setting is recommended if you use more than one DNS forwarder for resilience. This setup uses dnsdist as an intelligent DNS proxy in front of your normal forwarders, with Samba DCs configured to forward external DNS queries through `dnsdist`.
While `dnsdist` provides fast and intelligent failover between DNS forwarders (e.g., Pi-hole instances), Samba's internal DNS server introduces a noticeable delay before switching to an alternate forwarder when the primary becomes unavailable.
This happens because Samba tries to contact the first configured forwarder and waits for the request to timeout, which can take several seconds per query. Only then does it attempt the next one. This sequential behavior causes temporary failures or latency spikes when a forwarder goes down.
To mitigate this, `dnsdist` is placed in front of the forwarders and Samba forwards all external queries to `dnsdist` alone, allowing fast switching and load balancing to be handled outside of Samba.
apt update
apt install dnsdist
This installs `dnsdist`, its dependencies, and sets up the systemd service.
nano /etc/dnsdist/dnsdist.conf
-- Listen only on localhost, port 5353 setLocal('127.0.0.1:5353') addLocal('[::1]:5353') -- Accept queries only from localhost setACL({'127.0.0.1/32', '::1/128'}) -- Load balancing policy: least outstanding queries setServerPolicy(leastOutstanding) -- Upstream server 1 newServer({ address = "192.168.0.25:53", retries = 1, -- Allow one retry for transient issues timeout = 0.5, -- 500ms timeout checkInterval = 10, -- Check every 10s for faster failure / availability detection checkType = "A", checkName = "debian.org" }) -- Upstream server 2 newServer({ address = "192.168.0.26:53", retries = 1, -- Allow one retry timeout = 0.5, -- 500ms timeout checkInterval = 10, -- Check every 10s checkType = "A", checkName = "debian.org" }) -- Last resort (gateway) newServer({ address = "192.168.0.253:53", backup = true, retries = 0, -- No retries for fast failure timeout = 0.5, -- 500ms timeout checkInterval = 15, -- Check every 15s checkType = "A", checkName = "debian.org" })
systemctl enable dnsdist
systemctl start dnsdist
Check that it is running:
systemctl status dnsdist
To verify that `dnsdist` is listening correctly on port 5353 and responding as expected, a manual query was executed using `dig`:
dig @127.0.0.1 -p 5353 example.com ;; ->>HEADER<<- opcode: QUERY, status: NOERROR ;; flags: qr rd ra ;; QUESTION SECTION: ;example.com. IN A ;; ANSWER SECTION: example.com. 299 IN A 23.192.228.84 example.com. 299 IN A 23.215.0.136 example.com. 299 IN A 23.215.0.138 example.com. 299 IN A 96.7.128.175 example.com. 299 IN A 96.7.128.198 example.com. 299 IN A 23.192.228.80 ;; Query time: 8 msec ;; SERVER: 127.0.0.1#5353(127.0.0.1) ;; WHEN: Sat May 17 21:14:07 UTC 2025
This confirms that:
[global] dns forwarder = 127.0.0.1:5353
systemctl restart samba-ad-dc
Check that now Samba is resolving properly - note now we use port 53 instead of 5353 to make sure we query samba:
dig @127.0.0.1 -p 53 example.com ; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> @127.0.0.1 -p 53 example.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37277 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ; EDE: 3 (Stale Answer) ;; QUESTION SECTION: ;example.com. IN A ;; ANSWER SECTION: example.com. 0 IN A 96.7.128.175 example.com. 0 IN A 23.215.0.138 example.com. 0 IN A 23.215.0.136 example.com. 0 IN A 23.192.228.84 example.com. 0 IN A 23.192.228.80 example.com. 0 IN A 96.7.128.198 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP) ;; WHEN: Sat May 17 21:30:39 UTC 2025 ;; MSG SIZE rcvd: 142
-- Only listen on localhost, port 5353 setLocal('127.0.0.1:5353') addLocal('[::1]:5353')
Configures `dnsdist` to listen only on `127.0.0.1` (loopback), port 5353. This prevents exposure to the network and avoids conflict with Samba DNS on port 53.
-- Allow only queries from localhost setACL({'127.0.0.1/32', '::1/128'})
Restricts access to `dnsdist` so that only processes on the local machine (like Samba) can query it.
-- Use leastOutstanding for smart load balancing setServerPolicy(leastOutstanding)
The `leastOutstanding` policy in `dnsdist` is a dynamic and intelligent load-balancing strategy. It selects the upstream server (forwarder) that currently has the fewest active, unanswered queries.
This approach distributes load more evenly under pressure by avoiding overloaded servers and preferring those that are currently faster or less busy.
In this setup, where Samba forwards DNS queries to `dnsdist`, and `dnsdist` balances between two Pi-hole servers, `leastOutstanding` ensures that queries are directed to the least busy Pi-hole, improving performance and failover behavior. One last resort server (router) to be used if both upstreams are U/S
-- Upstream server 1 newServer({ address = "192.168.0.25:53", retries = 1, -- Allow one retry for transient issues timeout = 0.5, -- 500ms timeout checkInterval = 10, -- Check every 10s for faster failure / availability detection checkType = "A", checkName = "debian.org" })
Upstream DNS server.
-- Last resort newServer({ address = "192.168.3.253:53", backup = true, retries = 0, -- No retries for fast failure timeout = 0.5, -- 500ms timeout checkInterval = 15, -- Check every 15s checkType = "A", checkName = "debian.org" })
Last resort Upstream DNS server.
To verify the resilience and failover handling of `dnsdist`, a 30-second DNS stress test was performed using `dnsperf`. The forwarders configured in `dnsdist` were two Pi-hole servers. During the test, one of the Pi-hole forwarders was deliberately shut down after 10 seconds to simulate a failure.
dnsperf -s localhost -d queries.txt -l 30
Queries sent: 105909 Queries completed: 105859 (99.95%) Queries lost: 50 (0.05%) Response codes: NOERROR 105859 (100.00%) Average packet size: request 36, response 77 Run time (s): 30.43 Queries per second: 3478.13 Average Latency (s): 0.026 Latency StdDev (s): 0.0526
Despite shutting down one Pi-hole during the test:
`dnsdist`, configured with `leastOutstanding` policy and `retries=1`, provides a robust DNS load balancing and failover mechanism suitable for critical infrastructure such as Samba AD environments.