I Built a Private DNS Sinkhole.
Then My BT Router Said No.

I set out to block a few adverts. I ended up running Pi-hole and Unbound in Docker, resolving DNS for myself, and discovering exactly how little control a BT Smart Hub gives you.

~ 8 min read

Home LabDNSPrivacyDockerNetworking

Every device in the house has the same nervous habit. Before it loads a website, opens an app or checks for an update, it asks where that service actually lives. That question goes through DNS, the address book that turns a name such as example.com into an address a computer can contact. On a normal home connection, the answer usually comes from a resolver chosen by the internet provider. The resolver is simply the service that goes away and finds that address.

I wanted that part of the network under my control. The plan was Pi-hole: a small DNS server that answers normal requests and quietly gives blocked adverts, trackers and known malicious domains nowhere to go. That last trick is the "sinkhole" in DNS sinkhole. Instead of returning the real destination, Pi-hole returns a dead end.

The plan worked. Then I tried to give it to the rest of the house.

01Home deviceAsks where a domain lives
02Pi-holeBlocks or forwards the request
03UnboundResolves and validates the answer
04Authoritative DNSReturns the source answer

First, put a bouncer in a box

The home lab already runs its services in Docker, so Pi-hole went in as another container instead of being installed directly onto the machine. A container keeps the application and its dependencies in a separate package, which makes it easier to remove, replace or restore. Two usual sources of trouble, another service already using DNS's network doorway and the machine's own resolver getting in the way, turned out not to be trouble at all. The container came up healthy on the first attempt.

The default list gave it roughly 96,000 domains to block. That was enough to prove the path worked. A request arrived, Pi-hole checked it, and the dashboard recorded the result. The skeleton was alive.

Pi-hole dashboard showing 2,732 DNS queries, 1,711 blocked queries, a 62.6 percent block rate and 2,388,869 domains on its lists
Pi-hole after the first test run: 2,732 DNS requests, 1,711 blocked, and just under 2.4 million domains loaded.

Give it a blocklist that looks after itself

The base list was only the start. I added two maintained sources: one broad list for adverts and trackers, and a threat feed covering malware, phishing and scam domains. Once duplicates were removed, Pi-hole was holding roughly 2.4 million blocked domains.

That number is a snapshot, not a target to chase. A giant list that breaks ordinary websites is worse than a smaller one that behaves. The useful part is that these lists have stayed quiet during testing, and a safety allowlist of about 190 commonly caught domains is already in place before the wider rollout.

Pi-hole combines its subscribed lists into one local index called the Gravity database. That is the list it can check quickly whenever a device asks for a domain. Mine refreshes every Sunday morning. The lab also exports its configuration once a week and keeps several previous copies, so rebuilding the container should be a restore job rather than an exercise in memory.

What surprised me: 2.4 million entries sounds heavy. On this box, the running container sits in the low tens of megabytes of memory and barely troubles the CPU.

Brick up the browser's side door

There was one more route around the filter. Modern browsers can use DNS over HTTPS, usually shortened to DoH. It encrypts DNS lookups, which is useful on an untrusted network, but a browser configured to use an outside DoH provider can send those lookups around the local Pi-hole. Chrome calls the feature Secure DNS, while Firefox offers several DoH protection levels. Their exact behaviour depends on the browser and its settings, so this is not an automatic bypass on every machine.

I added one more maintained list containing a few thousand known encrypted-DNS endpoints. When a browser in its normal fallback mode tries one of those providers, Pi-hole gives it a dead end and the browser falls back to the DNS supplied by the operating system. On this network, that brings the request back through Pi-hole. It cannot cover every private or newly created resolver, or software that already knows a resolver's address, but it closes the common quiet route around the blocklists.

I tested the common encrypted endpoints offered through Firefox and Chrome, including Google, Cloudflare, Quad9 and OpenDNS. Every endpoint in that test came back as a dead end.

I deliberately stopped short of blocking full VPNs. A VPN can carry its own DNS and bypass this setup too, but I need mine working so I can reach the lab from outside. I bricked up the browser loophole, not the deliberate tunnel I set up myself. Right tool, right job.

Cut out the public resolver

Pi-hole can block a domain, but it still needs an answer for everything else. By default that answer comes from an upstream resolver. Moving every device behind Pi-hole would hide individual clients from that provider, but the provider could still receive the household's combined lookup history.

Unbound changes the route. It is a recursive resolver, running as a second container, which does the searching itself instead of asking one big provider for the finished answer. It starts with the internet's root directory, follows the signpost for the ending such as .com or .uk, then reaches the authoritative server. That final server holds the official DNS answer for the domain. Pi-hole's official Unbound guide describes the same chain and its privacy trade-offs.

This does not make web traffic invisible. Authoritative DNS servers still answer the relevant parts of a lookup, the internet provider still carries the connection, and the services I visit still see traffic. What it removes is one public DNS provider receiving the complete stream of requests.

I tested DNSSEC validation on purpose. DNSSEC adds a digital signature that lets a resolver check whether an answer is genuine and arrived unchanged. A domain with a deliberately broken signature came back as a failure. A valid signed domain resolved normally with authenticated data. That is the useful difference here: Unbound did not merely return an answer. It checked whether the signed answer could be trusted.

The small things that make it livable

A working resolver is useful. A resolver I can understand and recover is much better.

01

Names instead of numbers

Conditional forwarding lets Pi-hole ask the router which local device belongs to an address. That turns a log full of numbers into recognisable device names, so I can tell which gadget is getting chatty without doing a second lookup.

02

A proper dashboard

Pi-hole now feeds the monitoring stack. Queries, block rate and the noisiest clients sit beside the rest of the lab instead of being trapped in another admin page.

03

Backups before bravery

The full configuration is exported every week. Lists, settings and local rules can come back with the container if I break something while experimenting.

Then I found the wall

The final step should have been one router setting: hand out Pi-hole as the DNS server through DHCP, reconnect the devices, done. DHCP is the router service that automatically gives each device its network settings. That includes which DNS server it should use.

My router is a BT Smart Hub. The consumer Smart Hub firmware does not provide a setting for changing the DNS servers it hands to clients. There was no advanced page I had overlooked. BT community support answers point users back to changing DNS on each device, which is technically a workaround and completely misses the point of network-wide DNS.

BT Smart Hub warning: if the guide you are following says "just change DNS on the router", check whether your router actually exposes that setting before you build the rest. Mine does not.

I lost a solid hour looking for a box that was never there.

The workaround, then the real fix

For now, my main PC points to Pi-hole directly. It took about a minute to change, and it gave me the proof I needed. A lookup for a known advertising domain came back as a dead end. The dashboard immediately showed the PC's requests, including an application repeatedly trying to contact a telemetry endpoint. Pi-hole dropped every attempt.

That was deeply satisfying. It was also only one device.

The next build is pfSense, router and firewall software that gives me the controls missing from the BT hub. A machine running it can sit behind the hub and become the part of the network that hands out addresses and DNS settings. Once pfSense points every client at Pi-hole, the whole house gets the same policy without configuring devices one by one.

The software was the easy part. Docker behaved. Pi-hole blocked what it should. Unbound resolved and validated its own answers. The thing that stopped the rollout was a missing field in a consumer router.

That is a fairly good reason to have a home lab. If a box on my network makes a decision I cannot change, I can build a route around it.

More soon, when pfSense enters the chat.

Zombie