Un desarrollador que firma como Zed (M-Abozaid) ha publicado esp32-c3-adblock. Es un bloqueador de anuncios y rastreadores a nivel de DNS, al estilo de Pi-hole. Funciona en un microcontrolador ESP32-C3 que cuesta unos 2 dólares. No necesita PSRAM. El truco está en cómo guarda la lista negra. En lugar de conservar los nombres de dominio como texto en la memoria RAM, almacena una huella de cada uno en la memoria flash. Con ese método caben más de 140.000 dominios en unos 0,7 MB. Incluso se puede llegar a más de 537.000 si se renuncia a las actualizaciones del firmware por aire. El proyecto es de código abierto. Incluye un panel web, configuración inicial mediante portal cautivo y una caja imprimible en 3D. Veamos cómo funciona y qué límites tiene.
Un Pi-hole reducido a lo esencial
La idea de un bloqueador DNS no es nueva. Todos los dispositivos de la red preguntan al servidor DNS por la dirección de cada dominio al que quieren conectarse. Si el dominio pertenece a una lista de publicidad o rastreo, el bloqueador responde con una dirección nula. El dispositivo no llega a conectarse y el anuncio no se descarga.
Hasta ahora, este tipo de filtro solía montarse en una Raspberry Pi o en un servidor doméstico. Aquí el trabajo recae en un ESP32-C3. Es un chip de Espressif con un núcleo RISC-V de 32 bits a 160 MHz, 400 KB de SRAM, 4 MB de flash y Wi-Fi 4 de 2,4 GHz. Son cifras modestas. Por eso el diseño de la lista es la parte más interesante del proyecto.
El autor reconoce la inspiración de ESP32_AdBlocker, un proyecto previo de s60sc. Pero esp32-c3-adblock es una implementación independiente. Aquel enfoque dependía de PSRAM para almacenar listas grandes. Este lo evita por completo.
Hashes en flash en vez de cadenas en RAM
Guardar medio millón de nombres de dominio como texto exigiría varios megabytes de memoria. Un ESP32-C3 básico no los tiene. La solución consiste en convertir cada dominio en un número de 40 bits mediante FNV-1a, una función de hash sencilla y rápida. Cada entrada ocupa 5 bytes. Los números se ordenan y se escriben en la flash.
Con ese formato, 140.000 dominios ocupan unos 0,7 MB. La RAM utilizada se queda en torno a 50 KB. Es una fracción pequeña de los 400 KB disponibles, y deja margen para la pila Wi-Fi y el servidor web.
La consulta funciona así. Llega un paquete DNS por UDP y el firmware, escrito en C++, extrae el nombre del dominio. Calcula su hash y también el de sus sufijos superiores. Después busca cada valor en la tabla mediante búsqueda binaria. Si hay coincidencia, devuelve 0.0.0.0. Si no la hay, reenvía la pregunta a un servidor DNS externo y devuelve la respuesta al cliente.
La búsqueda binaria encaja bien con este diseño. Sobre unos 141.000 elementos hacen falta unas 18 lecturas de flash, porque el logaritmo en base 2 de esa cifra ronda 17. Según los datos publicados, cada consulta tarda unos 10 ms. Esa cifra incluye el viaje de ida y vuelta por Wi-Fi. Es un retardo que un usuario no percibe al navegar.
Hay un detalle de ingeniería que merece atención. El motivo de elegir 40 bits es el equilibrio entre espacio y errores. Con 32 bits se ahorraría flash, pero aparecerían unas siete colisiones con 250.000 dominios. Una colisión significa que un dominio legítimo comparte hash con uno bloqueado. Se bloquearía por error. Con 40 bits, el desarrollador indica que con 141.000 dominios las colisiones son casi nulas. Con 537.000 dominios aparece aproximadamente una.
Capacidad real según la partición de flash
La capacidad depende de cómo se reparta la flash de 4 MB. El proyecto ofrece tres configuraciones. La primera aloja unos 141.000 dominios con colisiones prácticamente inexistentes. La segunda mantiene dos particiones de aplicación para poder actualizar el firmware por aire. Esa opción deja alrededor de 1,3 MB para la lista, lo que equivale a unos 250.000 dominios. La tercera usa una sola partición de aplicación. Así se alcanzan unos 537.000 dominios, pero se pierde la actualización OTA del firmware.
Hay que elegir con cabeza. Para la mayoría de los usuarios, 250.000 dominios con actualización remota es un compromiso razonable. Las listas públicas más habituales suelen quedarse por debajo de esa cifra. Quien quiera una lista agresiva puede sacrificar la comodidad de las actualizaciones.
El método escala hacia arriba. El autor señala que el mismo enfoque aplicado a un ESP32-S3 de 16 MB permitiría guardar unos 2,7 millones de dominios con hashes de 40 bits. En cambio, almacenar cadenas en 8 MB de PSRAM dejaría el techo en torno a 466.000 dominios. La diferencia es notable, y demuestra que el ahorro viene del formato de datos y no tanto del chip.
El producto en detalle: esp32-c3-adblock
Pasemos al proyecto en sí. El código fuente en C++, las instrucciones de compilación con PlatformIO y el archivo STL de la caja están en este Github. La placa de referencia es la ESP32-C3 SuperMini, de 16 pines y con puerto USB-C. También se ha probado en placas ESP32 clásicas, como las DevKit o las basadas en WROOM.
La puesta en marcha es sencilla. Al arrancar por primera vez, el dispositivo abre un portal cautivo. Allí se introducen las credenciales de la red Wi-Fi, así que no hace falta escribirlas en el código. Después se accede al panel en http://c3adblock.local. Desde él se ve qué peticiones se han bloqueado o permitido por cada cliente. También se puede bloquear un dispositivo concreto o añadir dominios propios a la lista.
Las actualizaciones por aire cubren tanto el firmware como la lista de bloqueo. Además, el sistema puede programar descargas automáticas de listas ya compiladas desde una dirección que el usuario indique. Así se evita volver a conectar la placa por cable.
En seguridad, el autor ha tomado medidas básicas pero acertadas. Los puntos de acceso que cambian el estado del sistema exigen autenticación HTTP Basic. Los dominios personalizados se escapan en HTML para prevenir ataques XSS. Y se ha reforzado el panel frente a CSRF. Es un detalle que se agradece en un dispositivo que quedará encendido de forma permanente en la red doméstica.
La alimentación pide cuidado. El proyecto indica que la placa necesita 5 V por USB desde una fuente estable. Una tensión inestable puede provocar caídas de tensión en la radio, con reinicios y respuestas perdidas. Una de las imágenes del artículo muestra la placa conectada directamente al puerto USB del router, con un adaptador de USB-C a USB-A. Es una solución cómoda, siempre que ese puerto entregue suficiente corriente.
Reflexiones adicionales
Lo más valioso de esp32-c3-adblock no es el ahorro económico. Es el ejemplo de optimización. Cambiar cadenas de texto por hashes ordenados, y mover los datos de la RAM a la flash, convierte un chip limitado en una herramienta útil. Es la clase de decisión que conviene recordar en cualquier proyecto con recursos escasos.
Conviene también ser realistas. Un bloqueador DNS no elimina todos los anuncios. No puede filtrar publicidad servida desde el mismo dominio que el contenido. Tampoco controla las aplicaciones que usan DNS cifrado sobre HTTPS y se saltan el servidor de la red. Y un único microcontrolador no tiene redundancia. Si falla, la red depende de que los clientes recurran a otro servidor DNS.
Aun así, para una red doméstica pequeña es una opción interesante. Es barata, consume poco y se puede entender de principio a fin. Para quien disfrute con la electrónica, además, es un buen proyecto de fin de semana.
6