分享到微信

当前解读页的微信分享二维码

用微信扫一扫打开,点击右上角「···」分享给朋友或朋友圈。

手机上可截屏后,在微信扫一扫中从相册识别二维码。

M-Abozaid/esp32-c3-adblock

运维与部署

在一块约 2 美元的 ESP32-C3 上实现 DNS 广告拦截:把域名哈希存进 flash 并二分查找,适合想用极低成本做家庭网络过滤的人。

3,474
387
C++
MIT
创建于 4 个月前

用 2 美元开发板做 DNS 广告拦截

项目在无需 PSRAM 的 ESP32-C3 上运行一套类似 Pi-hole 的 DNS sinkhole。它不把拦截域名的字符串放进 RAM,而是把每个域名存成排好序的 40 位 FNV-1a 哈希放入 flash,查询时对这张表做二分查找:命中就返回 0.0.0.0,未命中就转发给上游解析器并回传结果。按 README 的说法,约 14 万个域名占用约 0.7 MB flash,匹配耗时约 10 ms,内存占用约 50 KB;537k 域名的大列表也能放下,但预计会有约 1 次哈希碰撞。

它面向希望在家庭网络里做 DNS 过滤、又不想投入太多硬件的人,例如把 C3 SuperMini 插进路由器的空闲 USB 口。其他功能包括带每个客户端统计的 Web 面板、封禁客户端、自定义拦截域名、通过 c3adblock.local 做 mDNS 发现、固件与拦截列表的 OTA 更新,以及配网门户。

快速使用

准备一块 4 MB flash 的 ESP32-C3 板(不需要 PSRAM)、稳定的 USB 供电,以及较新的 PlatformIO。发行版/apt 里的 platformio 版本过旧会报错,请使用当前 VS Code 扩展自带的核心,或在虚拟环境里执行 pip install -U platformio。

  1. 复制密钥模板并编辑:cp src/secrets.example.h src/secrets.h。WEB_USER、WEB_PASS 和 OTA_PASS 必须设置,它们保护面板上会改变状态的接口和网络 OTA;WIFI_SSID 和 WIFI_PASS 可选,保留占位符即可改用设备上的配网门户。
  2. 生成拦截列表哈希表:python3 tools/build_blocklist.py data/blocklist.bin。默认来源是 StevenBlack 基础列表加 Hagezi Light,约 10 万条。也可以额外传入 URL 和本地文件,支持 hosts 文件、纯域名列表和基础 AdGuard/Adblock 规则。
  3. 烧录固件和文件系统:先 pio run -t upload,再 pio run -t uploadfs。这是唯一一次 USB 烧录。
  4. 用 pio device monitor 查看启动日志、记下 IP,然后访问 http://c3adblock.local 打开面板。

如果没填 WiFi 或连接失败,设备会开启名为 C3-AdBlock-XXXX 的开放热点和配网页面。用手机连上,选择网络并输入密码即可。之后想换网络,可以在面板点 Forget WiFi,或按住 BOOT 键上电让配网页面重新出现。

使用时,把某个设备的 DNS 指向 C3 的 IP,或把它作为主 DNS 之后的辅助解析器。验证方式:

dig @<c3-ip> doubleclick.net   # -> 0.0.0.0  (被拦截)
dig @<c3-ip> github.com        # -> 真实 IP  (被转发)

更新方式

首次烧录之后,拦截列表和固件都可以通过 WiFi 从面板更新。可以上传新生成的 blocklist.bin,也可以设置一个远程 URL 让设备按计划拉取预构建列表,或上传 .pio/build/c3/firmware.bin 做 OTA。GitHub Actions 每周一重建默认列表并发布到固定的 release 地址。命令行 OTA 可用 pio run -t upload --upload-port c3adblock.local --upload-protocol espota,需要 OTA_PASS。

使用约束

  • Flash 预算: 固件 OTA 需要两个 app 分区,只剩约 1.3 MB 给拦截列表,最多约 25 万域名。537k 的“终极”列表只能配合单 app 分区表使用,此时无法做固件 OTA。分区方案在 partitions.csv 中调整。
  • 板卡支持: C3 SuperMini 是测试过的目标。经典 ESP32 DevKit/WROOM 可用 pio run -e esp32dev -t upload 构建,但属于社区贡献、只做过编译测试。
  • 安全边界: 面板是 80 端口的明文 HTTP,Basic Auth 凭据只是 base64 编码而非加密。会改变状态的接口还要求携带 X-Requested-With: c3-adblock 请求头,以阻止跨站表单/图片请求。如果 secrets.h 仍使用公开的占位密码,设备会打印警告并在面板显示横幅,但仍然会启动,因此在不可完全信任的网络上使用前务必改成真实密码。配网热点在设置期间按设计是开放且不加密的。
  • 列表表达能力: 正则、通配符、$ 修饰符和 cosmetic ## 规则会被跳过并计数。@@ 允许规则只能移除某一条精确条目,无法从被拦截的父域名下单独放行子域名。
  • Linux 串口: Fedora/Ubuntu 上的 ModemManager 可能占用 /dev/ttyACM0 并复位 C3。停用 ModemManager 并为厂商 ID 303a 添加 udev 规则即可解决。
  • 天线与供电: README 提醒廉价的 USB-C 转 A 转接头可能导致射频发射时掉电,打印外壳时也应让天线一端保持空旷。

HotRepo 点评

在 2026-11-01 的 C++ 月榜记录中,项目当月新增 2,789 Star,最好名次为第 15。更早的 2026-10-06 日榜记录显示 1,614 Star、当日新增 196。它还在 2026-10-07 引出一个 195 分、82 条评论的 Hacker News 讨论。讨论中最实质的技术质疑集中在哈希碰撞:评论者认为 README 把碰撞描述成“两个被拦截域名同哈希”,但真正的风险是误报,即一个正常域名与被拦截域名哈希相同(muti、zamadatix)。这一点值得留意,因为设备处在所有 DNS 查询的路径上,一次不巧的碰撞就可能误伤正常网站,直到通过面板或接口手动放行。其余讨论多集中在硬件选择上,例如部分 C3 板载天线较弱,这更多影响设备摆位而非核心设计。

本文由 AI 根据项目 README 生成,更新于 ,以项目官方文档为准。

Hacker News 讨论

ESP32-C3 Adblock
▲ 195 · 82 条评论 · 2026年10月7日