Разработчик под ником Zed (M-Abozaid) выложил в открытый доступ проект esp32-c3-adblock — DNS-блокировщик рекламы в духе Pi-hole, который работает на микроконтроллерной плате ESP32-C3 стоимостью около 2 долларов и не требует PSRAM. Устройство фильтрует DNS-запросы и тем самым отсекает рекламные и трекинговые домены сразу для всех устройств в домашней или небольшой офисной сети.
Главная идея проекта — не хранить строки доменов в оперативной памяти. Вместо этого блоклист записывается во flash-память в виде отсортированных 40-битных хешей FNV-1a, а проверка запроса сводится к двоичному поиску по этой таблице. Благодаря такому подходу примерно в 0,7 МБ flash помещается более 140 000 доменов, а оперативной памяти прошивке требуется всего около 50 КБ.
Блокировщик рекламы на ESP32-C3 SuperMini в напечатанном на 3D-принтере корпусе с переходником USB-C — USB-A для прямого подключения к роутеру
Как устроена проверка DNS-запросов
Когда на устройство приходит UDP-запрос DNS, прошивка на C++ извлекает из него доменное имя и вычисляет хеш — в том числе для родительских суффиксов домена. Затем она двоичным поиском ищет полученное значение в таблице хешей во flash-памяти. Если домен числится в блоклисте, ESP32-C3 отвечает адресом 0.0.0.0, и запрос оказывается заблокирован. В противном случае он пересылается на вышестоящий DNS-сервер, а полученный ответ возвращается клиенту.
Проверка занимает около 10 мс с учётом времени прохождения сигнала по Wi-Fi и требует примерно 18 обращений к flash-памяти. Именно двоичный поиск позволяет обойтись небольшим числом чтений вместо перебора всей таблицы целиком.
Требования и характеристики
Основные требования и особенности esp32-c3-adblock:
Блокировщик рекламы на ESP32-C3 SuperMini, подключённый напрямую к USB-порту роутера (изображение улучшено с помощью ИИ)
- Беспроводной модуль — 16-контактный ESP32-C3 Super Mini
- SoC — Espressif Systems ESP32-C3FH4
- Процессор — одноядерный 32-битный микроконтроллер RISC-V с частотой до 160 МГц
- ОЗУ — 400 КБ SRAM
- Накопитель — 4 МБ flash
- Беспроводная связь — Wi-Fi 4 на частоте 2,4 ГГц
- USB — порт USB Type-C для прошивки
- Керамическая антенна
- Сообщество проверило работу и на классических платах ESP32 (DevKit / WROOM)
- SoC — Espressif Systems ESP32-C3FH4
- Хранилище — минимум 4 МБ flash
- около 0,7 МБ flash занимают более 140 000 доменов
- домены хранятся прямо во flash в виде отсортированных 40-битных хешей FNV-1a (по 5 байт каждый), а не строками в ОЗУ
- Производительность DNS-блокировки:
- время проверки — около 10 мс (включая ~18 чтений flash и задержку Wi-Fi)
- варианты ёмкости — ~141 тыс. доменов (практически без коллизий), ~250 тыс. доменов (с двумя разделами приложения для OTA-обновления прошивки) или до ~537 тыс. доменов (один раздел приложения, ~1 коллизия)
- Безопасность
- HTTP Basic Auth для эндпоинтов, изменяющих состояние
- экранирование HTML в пользовательских доменах для защиты от XSS
- защита от CSRF-атак
- Питание — 5 В по USB (нужен стабильный источник питания, чтобы избежать просадок, из-за которых сбоит радиомодуль)
- Корпус — файл STL для печати на 3D-принтере под форм-фактор ESP32-C3 SuperMini
Веб-панель, настройка Wi-Fi и обновления
У проекта есть веб-панель, доступная по адресу http://c3adblock.local: в ней можно смотреть заблокированные и разрешённые DNS-запросы по каждому клиенту, блокировать отдельные устройства и добавлять собственные домены в блоклист. Первоначальная настройка Wi-Fi выполняется через captive portal, поэтому данные сети не нужно зашивать в код.
Веб-панель со статистикой блоклиста, списком клиентов, уровнем Wi-Fi-сигнала, использованием памяти и пользовательскими заблокированными доменами (изображение улучшено с помощью ИИ)
Поддерживается обновление «по воздуху» (OTA) как прошивки, так и блоклистов, а также автоматические обновления по расписанию: готовые файлы блоклиста скачиваются по указанному адресу.
На плате ESP32-C3 с 4 МБ flash для OTA-обновления прошивки нужны два слота приложения, и под блоклист остаётся около 1,3 МБ — этого хватает на 250 000 доменов. Чтобы воспользоваться большим списком на 537 000 доменов, придётся перейти на раздел с одним слотом приложения, но тогда OTA-обновление прошивки станет недоступно.
Почему выбран 40-битный хеш
Необычно выглядит сама ширина хеша — 40 бит. По словам разработчика, для такого бюджета flash-памяти это оптимальный размер. При 141 тыс. доменов коллизий почти нет, а при агрессивном расширении списка до 537 тыс. доменов получается примерно одна коллизия, то есть один ошибочно заблокированный домен. Переход на стандартный 32-битный хеш сэкономил бы место, но дал бы около семи коллизий уже на 250 тыс. доменов.
Проект вдохновлён разработкой ESP32_AdBlocker от s60sc, однако это независимая реализация: для больших блоклистов она использует flash-память вместо PSRAM. Тот же подход применим и на более мощных чипах: например, ESP32-S3 с 16 МБ flash при 40-битных хешах вместит около 2,7 млн доменов — против примерно 466 тысяч доменов, которые удаётся хранить строками в 8 МБ PSRAM.
Исходный код на C++, инструкции по сборке через PlatformIO и модель корпуса для 3D-печати доступны в репозитории проекта на GitHub.














