ESP32_AdBlocker_Reborn
ESP32_AdBlocker_Reborn
ESP32_AdBlocker_Reborn: Rebuilding a DNS Ad Blocker with ESP32 + W5500
The Original: Pi-hole, a Raspberry Pi–Based Network Ad Blocker
When it comes to network-wide ad and tracker blocking, the first name that comes to mind is Pi-hole. Instead of installing browser extensions on every device, you set up a single Raspberry Pi as your network's DNS server, and it blocks ad and tracker domains at the source — for every device on the network, from smartphones to smart TVs to IoT gadgets.
The mechanism is simple. When a device queries an ad server's domain, Pi-hole returns a non-routable address such as 0.0.0.0 instead of the real IP. Since the request never actually reaches the ad server, Pi-hole filters out even in-app ads and smart TV ads — things a browser-based ad blocker can't touch.
The Commercial Product It Was Meant to Replace: AdTrap
What's interesting is Pi-hole's origin story. Developer Jacob Salmela originally built Pi-hole as an open-source alternative to AdTrap, a commercial ad-blocking hardware appliance.
AdTrap launched via Kickstarter in 2013, raising over $200,000 for a router-shaped box (model AT1000, priced at $139) that filtered ads from websites, video, music streams, and mobile apps at the network level — no configuration required, just plug it in between your modem and router. The device was manufactured by BluePoint Security, a mobile antivirus software company, and it even routed a phone's cellular traffic through the in-home AdTrap unit to extend ad blocking beyond Wi-Fi. In short, AdTrap was the commercial hardware product that first proved out the concept of "network-level ad blocking," and Pi-hole reproduced that idea as open-source software running on an inexpensive Raspberry Pi. The founding idea was to replace a commercial appliance with a cheap embedded board.
Pi-hole's Own Productized Spin-offs
Pi-hole later came full circle, getting turned back into commercial products in its own right:
- Pi Supply's Official Pi-hole Kit: Released through an official partnership between Pi Supply and the Pi-hole team, this is a fully assembled kit with hardware and software already set up, sold for around £80.
- The Pi Hut's Official Pi-hole Raspberry Pi 4 Kit: A boxed package built around a Raspberry Pi 4 (2GB), including an SD card pre-loaded with a Pi-hole OS image — ready to go after running a single install script.
In short, Pi-hole is a case of "commercial hardware (AdTrap) → open-source software (Pi-hole) → commercial kits again" — a full loop that shows the "Linux-based SBC + DNS sinkhole software" combination is a proven enough concept to sustain an actual product market.
Can the Same Thing Be Done Without an SBC — Using Just an MCU?
Pi-hole depends on an SBC (Raspberry Pi) that needs to boot Linux. ESP32_AdBlocker_Reborn, a recently released project, implements the same DNS sinkhole concept using nothing but an ESP32-S3 + W5500 Ethernet chip, running as pure ESP-IDF firmware with no Linux involved.
Built around the LilyGO T-ETH-Elite board (ESP32-S3-WROOM-1 + W5500), it loads the entire OISD blocklist (roughly 330,000 wildcard domains) into PSRAM, where it's queried instantly via a hash table and binary search. The sorted table is cached on a microSD card, so it restores in about one second on reboot — no OS boot process, the service starts the moment power comes on.
The Original Project Was Already Featured on WIZnet UCC
This isn't actually the first ESP32 + W5500 DNS ad blocker. WIZnet UCC has already covered s60sc's ESP32_AdBlocker (Arduino-based), and the ESP32_AdBlocker_Reborn README explicitly credits that project as its inspiration. In other words, this isn't an entirely new attempt — it's a from-scratch ESP-IDF rewrite of a project UCC has already introduced.
The original ESP32_AdBlocker runs on the Arduino framework and lets you switch between Wi-Fi, Ethernet (W5500), and Eth+AP at runtime via a single netMode variable. When blocking, its DNS server logic fills in 0.0.0.0 as the response. It shares the same basic idea as this remake — loading the blocklist into PSRAM for sub-100µs lookups per entry — but it differs in that responses are generated at the socket/Arduino DNS server layer, and it doesn't publish quantitative performance figures (latency, QPS), unlike ESP32_AdBlocker_Reborn.
Key Implementation Details
- PSRAM-resident blocklist: 330,000 domains hashed with 32-bit MurmurHash3, stored in two PSRAM buffers using a radix-sort + binary search structure, with support for subdomain wildcard matching.
- L2 fast path: Blocked queries and cache hits bypass the lwIP/socket layer entirely — responses are built and sent directly at the W5500 Ethernet RX hook. It sidesteps the socket stack altogether.
- Forward cache: Allowed responses are cached in PSRAM (1,024 slots, split between A and AAAA records), reused according to their TTL.
- Pi-hole-level management features: mDNS, multiple blocklist sources, whitelisting/custom rules, DNS rewrites, client ACLs, query logs, NTP, and DNS-over-TLS upstream — all exposed through a web UI.
Measured Performance
| Path | p50 Latency (c=1) | Max Throughput |
|---|---|---|
| Blocked query (L2 fast path) | 1.8 ms | ~2,200 QPS |
| Cache hit (L2 fast path) | 1.8 ms | ~2,100 QPS |
| New query (upstream forwarding) | ~40 ms (gateway RTT) | — |
The bottleneck isn't the CPU — it's the W5500's SPI bus (fixed at 40MHz, with no speedup even at 60MHz). Compared to dnsmasq's roughly 0.7ms, this is about 2.5x slower, but that's due to the per-frame overhead inherent to SPI Ethernet hardware (~405µs), not a limitation of the software design.
Pi-hole vs. ESP32_AdBlocker_Reborn
| Aspect | Pi-hole (Raspberry Pi) | ESP32_AdBlocker_Reborn (ESP32-S3 + W5500) |
|---|---|---|
| Runtime environment | Requires Linux OS boot | No OS — pure ESP-IDF firmware |
| Boot time | Tens of seconds (OS boot) | ~1 second (SD cache load) |
| Power consumption | Relatively high (SBC) | Very low (MCU) |
| DHCP server | Supported | Not supported |
| Throughput | Tens of thousands of QPS or more (Linux socket stack) | ~2,200 QPS (W5500 SPI-bound) |
| Cache / whitelist / ACL / DoT | Supported | Supported |
| Productization | Started as an AdTrap replacement; multiple preset kits and display-equipped kits on the market | Personal project, currently limited to a specific LilyGO board (a Wi-Fi-only general-purpose ESP32-S3 version is on the roadmap) |
Just as Pi-hole replaced a commercial appliance with "an SBC + Linux," ESP32_AdBlocker_Reborn demonstrates that the same role can be reproduced with just "an MCU + W5500" — at lower power and lower cost.
ESP32_AdBlocker (Original) vs. ESP32_AdBlocker_Reborn
Even within the same ESP32 + W5500 combination, the original and the remake diverge significantly in implementation.
| Aspect | ESP32_AdBlocker (original, s60sc) | ESP32_AdBlocker_Reborn |
|---|---|---|
| Framework | Arduino | Pure ESP-IDF 6.0.1 (native) |
| Network mode | Wi-Fi / Ethernet (W5500) / Eth+AP, switchable at runtime | LilyGO T-ETH-Elite only, W5500 fixed (Wi-Fi version on roadmap) |
| Block-response layer | Arduino DNS server (socket level) returns 0.0.0.0 | L2 fast path at the Ethernet RX hook (bypasses lwIP/sockets) |
| Blocklist lookup speed | PSRAM-based, sub-100µs per entry (documented) | MurmurHash3 hashing + radix-sort + binary search, ~64µs |
| Quantitative performance data | None (qualitative description only) | Full benchmarks: p50 1.8ms, max ~2,200 QPS |
| Cache / DoT / ACL / rewrite | None | Forward cache, DNS-over-TLS, client ACL, DNS rewrite all supported |
| Featured on WIZnet UCC | Already featured | Newly introduced in this article |
Where the original emphasized "a general-purpose structure supporting both Wi-Fi and W5500," Reborn takes the opposite approach — "focusing on W5500 alone and optimizing all the way down to the Ethernet frame level." The L2 fast path design, which responds directly at the Ethernet RX hook, is a practical optimization technique for minimizing socket-stack overhead in SPI Ethernet environments — well worth a look for developers working with the W5500.
