I recently set up a redundant pi-hole in Docker on my home server to alleviate the single point of failure from my original pi-hole which runs on bare metal on a Raspberry Pi 4B. I’ve been using a single pi-hole for about six years to block advertisements, tracking links, and time-wasting websites across my home network. During that time my pi-hole has gone down 3 or 4 times. A couple were due to corrupted microSD cards (all that logging is pretty rough), and most recently the major version update to pi-hole v6 bricked my install beyond repair, requiring a fresh reimage.
My router doesn’t support scripting, so if the pi-hole dies the home network loses all connectivity until I can get into the router and manually switch back to public DNS. Not a great event if my wife is working from home and I’m away. Hence the redundant pi-hole, and with the router configured to use both as DNS servers, I should have plenty of notice to repair one if it goes down while the network continues humming along on the surviving pi-hole.
I monitor both pi-holes from my Homepage dashboard, and since setting up Pi-Hole2 I’ve noticed an abnormally large number of queries (per 24 hours) that never settled out after several days:

Both pi-hole dashboards show an outsized number of pointer (PTR) requests, which are used for reverse DNS lookups:

A quick check of my top permitted domains shows some very blatant suspects:

Over 400,000 requests per day on each pi-hole to lb._dns-sd._udp.0.1.168.192.in-addr.arpa, db._dns-sd._udp.0.1.168.192.in-addr.arpa, and b._dns-sd._udp.0.1.168.192.in-addr.arpa.
A quick internet search reveals these to be Multicast DNS (mDNS) requests for DNS Service Discovery (DNS-SD), frequently associated with Apple’s Bonjour protocol, which allows Apple devices to automatically find and advertise services on a local network independent of a central DNS server. Bad Apple! If I want to connect two devices on my network, I’ll assign them static configurations and do it myself.
Further investigation of my pi-hole logs revealed these PTR requests to be coming in batches of 1000, which conveniently enough is the default rate limit that pi-hole applies to devices making more than a threshold amount of queries per minute. Without that rate limit, Apple Bonjour would have likely brought my home network to its knees.
Developers on the official pi-hole forums proposed a number of solutions, none of which were satisfactory to me:
- Set the router’s WAN DNS to a public DNS resolver. I can’t do this as my router doesn’t allow separate LAN and WAN DNS resolvers; even if I could I truly don’t think this would solve the issue as mDNS is a local network protocol and is not forwarded to the internet. Plus this would just lead to DNS leakage defeating the purpose of pi-hole.
- Use pi-hole as the DHCP server. I’m already doing this, it works fine to make Apple Bonjour behave but only if the user has one pi-hole on their network. I have two pi-holes, and I split my subnet so they can both act as DHCP servers on non-overlapping ranges for maximum redundancy.
- Disable conditional forwarding. I don’t want to do this if I don’t have to. I like the client/device names showing in the pi-hole logs, and without conditional forwarding pihole2 has no knowledge of DHCP leases from pihole1, so the logs just fill with IP addresses. The only workaround would be to statically configure every client in my network and share that across both pi-holes, but I’d rather not.
Why pi-hole explodes with Apple Bonjour when conditional forwarding is enabled
As far as I understand it, here’s the network flow:
- An Apple device sends a multicast DNS packet to all devices on the local network. This is structured as a reverse query (in this case, 0.1.168.192, a rarp for my private IP subnet 192.168.1.0/24) to the whole subnet. mDNS operates on the local network using multicast out of UDP port 5353, which pi-hole is blind to as it’s listening for unicast DNS on port 53.
- All devices on the network listening on port 5353 receive the mDNS broadcast packets, learning things from the sender like hostname, type, and A/AAAA records to map hostnames to IPs. Any device supporting Service Discovery responds in kind with its own info. Again, we can’t see any of this in pi-hole.
- There’s another protocol of Apple Bonjour running on UDP port 53. This is unicast traffic for DNS Service Discovery, and it’s Bonjour trying to query if any DNS server handles service discovery for the network. But it’s using the same naming conventions mDNS uses. This request being unicast goes out on port 53 to pi-hole, our DNS server, and it’s the queries I see taking over my pi-hole logs.
- Pi-hole should reply “no such domain”, indicating no special DNS-SD records are published, and the Apple Bonjour client should then fall back to the answers it collected from the port 5353 multicast. Pi-hole does not do this which is where the trouble starts when the user has conditional forwarding enabled.
- Pi-hole has no capability to resolve the unicast DNS-SD request; with conditional forwarding enabled pi-hole1 then forwards all the
lb._dns-sd._udp.,db._dns-sd._udp., andb._dns-sd._udp.queries to pi-hole2. Pi-hole2 cannot resolve the request and sends it back to pi-hole1. Repeat back and forth on port 53 until the rate limit is hit. Over and over, 1000 requests every time an Apple device tries to discover if there’s an authoritative DNS-SD server on the network.
What didn’t work
I tried modifying misc.dnsmasq_lines to inject a custom configuration into dnsmasq on the pi-holes. First I tried pointing these addresses to 0.0.0.0 and then restarting the DNS resolver service:
address=/lb._dns-sd._udp.0.1.168.192.in-addr.arpa/0.0.0.0
address=/db._dns-sd._udp.0.1.168.192.in-addr.arpa/0.0.0.0
address=/b._dns-sd._udp.0.1.168.192.in-addr.arpa/0.0.0.0
When that didn’t work, I tried pointing them to NXDOMAIN:
address=/lb._dns-sd._udp.0.1.168.192.in-addr.arpa/#
address=/db._dns-sd._udp.0.1.168.192.in-addr.arpa/#
address=/b._dns-sd._udp.0.1.168.192.in-addr.arpa/#
Interestingly neither of those seemed to have the intended effect (or really, do anything at all).
Ending the Apple Bonjour DNS-SD loop
What did work was making a simple regex blacklist in pi-hole to nicely wrap up all these domains in one entry and blacklist them. I came up with the following regex deny filter to blacklist all three flavors of offending PTR requests on both pi-holes:
^[a-z]?b\._dns-sd\._udp\.
Verifying it works next time we see Apple Bonjour trying to look for a DNS-SD server:

Nice. One blacklisted query and it’s done, I don’t get 1000 echoed queries back and forth between the two pi-holes as I did five minutes previously.
Ending the Apple Bonjour local loop
I also discovered a bunch of requests to “local” stuck in a DNS loop until hitting the rate limit, though a small fraction compared to the above offenders. I go back in my logs to check the origin of the request and big surprise, it’s an Apple device again!

These .local queries are also a part of the multicast DNS network discovery process of Apple Bonjour. Easily eliminated in pi-hole by going to Settings –> DNS and checking the box to “Never forward non-FQDN A and AAAA queries”. From the description of the toggle we learn that this setting “Tells Pi-hole to never forward A or AAAA queries for plain names, without dots or domain parts, to upstream nameservers. If the name is not known from /etc/hosts or DHCP then a ‘not found’ answer is returned.” Sure enough this setting works as advertised and the local queries are whittled down to a handful per hour after a restart of pi-hole’s DNS resolver.
Why the regex deny is the most proper bandaid fix, and doesn’t even break Apple Bonjour’s local network discovery!
As I explained earlier, these DNS Service Discovery requests on port 53 aren’t providing any essential information to Apple Bonjour. All they’re looking for is an authoritative server on the network that is already handling service discovery. We don’t have one of those (at least I don’t at home), and since pi-hole lacks the ability to properly resolve these DNS-SD requests, sinkholing them is the closest we can get to responding “no such domain”. And we get to keep conditional forwarding enabled!
Apple Bonjour already got all of the information it needs to discover other devices from the multicast DNS it also sent out on port 5353 that pi-hole can’t see. We can easily verify that with an app like Discovery – DNS-SD Browser by Lily Ballard on the App Store.
Here’s all the local devices Apple Bonjour discovered over Wi-Fi on my iPhone, including my Vizio TV:

And from my Mac Mini over ethernet I can run in the terminal dns-sd -B _services._dns-sd._udp. to see the same information, verifying I can see the same devices, though a couple are duplicated in the terminal output compared to the app.
Before and after, my pi-hole dashboard is useful again
Silencing the DNS loops caused by Apple Bonjour and pi-hole’s conditional forwarding yielded some immediate and obvious results on my primary pi-hole:

On the secondary pi-hole, an even more drastic reduction:

Pi-hole2 is used far less frequently, I assume because most devices on my network had existing DHCP leases on pi-hole1 and prefer to use the first listed DNS in my router.
The red on both pi-holes are queries from its partner pi-hole. Hundreds of thousands of looped queries per day. Tomorrow when this data falls off and the scales readjust, I’ll actually be able to use these charts to once again get a visual representation of how chatty different devices are.
I’m happy to have resolved this and now I can leave my redundant pi-hole setup alone to hum along smoothly without DOSing my own network or polluting the logs with thousands of repeated queries.
I’m not sure if there can be a proper fix for this Apple Bonjour interaction from the pi-hole team, given that it’s relatively niche to run multiple pi-holes, and the custom dnsmasq configurations I tried didn’t seem to do anything. Maybe they could implement a toggle setting to “silence Apple Bonjour conditional forwarding loops” that implements the regex deny on the backend?