esp32-c3-adblock 如何切换上游 DNS:一行构建参数换到 1.1.1.1,10 分钟生效

发布时间:2026/11/2 18:37:34
esp32-c3-adblock 如何切换上游 DNS:一行构建参数换到 1.1.1.1,10 分钟生效

esp32-c3-adblock 如何切换上游 DNS:一行构建参数换到 1.1.1.1,10 分钟生效

【免费下载链接】esp32-c3-adblockPi-hole-class DNS ad-blocker on a $2 ESP32-C3 (no PSRAM): 537k domains as 40-bit FNV-1a hashes in flash, binary-searched. UDP DNS sinkhole + web dashboard. https://youtube.com/shorts/RaxszOUMi8E?feature=share项目地址: https://gitcode.com/GitHub_Trending/es/esp32-c3-adblock

esp32-c3-adblock 是一个 Pi-hole 式的 DNS 广告拦截器:一块约 2 美元的 ESP32-C3 小模块,把 53.7 万个广告域名以 40 位 FNV-1a 哈希存进 flash,查询命中就直接回0.0.0.0掐死。本文只解决一件事——把设备的默认上游解析器(Quad99.9.9.9)换成 Cloudflare1.1.1.1或其他公共 DNS,全程不碰源码。工作量:加一行构建参数、烧录一次、两条命令验证,大约 10 分钟。

在build_flags加一行-DUPSTREAM_IP:官方预留的覆盖入口

先看默认值写在哪。src/main.cpp 第 24~29 行:

#ifndef UPSTREAM_IP #define UPSTREAM_IP 9, 9, 9, 9 // Quad9 #endif #ifndef UPSTREAM_PORT #define UPSTREAM_PORT 53 #endif

#ifndef的意思是"编译时如果已有定义,就用你给的值"。这就是官方预留的自定义入口:只要构建时传了自己的UPSTREAM_IP,源码里的 Quad9 自动被跳过,一行代码都不用改。

打开 platformio.ini,在[env:c3]段的build_flags末尾追加一行(如果你用的是经典 ESP32 开发板,改的是[env:esp32dev]段):

[env:c3] board = esp32-c3-devkitm-1 build_flags = -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DUPSTREAM_IP=1, 1, 1, 1 ; ← 新增:上游改为 Cloudflare 1.1.1.1 ; -DUPSTREAM_PORT=5353 ; 仅当上游跑在非标准 53 端口时才放开

想切回 Quad9 就把值改回9, 9, 9, 9。保存后选一条烧录路径:

  1. USB 本地烧录:执行pio run -t upload,PlatformIO 会重新编译并把新固件经 USB 写入设备;
  2. 在线 OTA(设备已在网内):打开 Web 控制台(http://c3adblock.local),把编译产物.pio/build/c3/firmware.bin传到Firmware → OTA update,设备校验通过后自动重启进新镜像;也可以在命令行直接推:pio run -t upload --upload-port c3adblock.local --upload-protocol espota。

小结:改动只有一行参数,USB 或 OTA 任一方式烧录完成即生效,源码原样未动;烧完别急着收工,下一步用两条命令确认流量真的换了门。

两条dig命令验收:一条被拦,一条放行

dig是命令行 DNS 查询工具,@<host>表示把这条查询指给指定地址;下文<c3-ip>指 C3 设备在局域网内被路由器分配的 IP(可在 Web 控制台或路由器面板看到,其 mDNS 域名是c3adblock.local)。重新上电后,从任意一台能访问 C3 的电脑执行:

dig @<c3-ip> doubleclick.net # 广告域名,应仍返回 0.0.0.0 dig @<c3-ip> github.com # 正常域名,应返回新上游解析出的真实 IP

两条命令各验一支:

  • 第一条预期0.0.0.0:证明拦截链路不受上游切换影响——广告域名到 C3 就被 sinkhole 掉,根本轮不到上游;
  • 第二条预期真实 IP:证明正常查询确实经由新上游(1.1.1.1)解析并回传了。

辅助信号:控制台首页的 "Total allowed" 计数(src/page.h 渲染的统计)随每条成功转发增长,直观说明转发在干活。顺带一提,这两条命令在切换之前跑一遍就是定位工具:第一条通、第二条超时无应答,说明问题出在上游那一支,而不是拦截逻辑。

小结:一拦一放两条命令都符合预期,切换就算真正完成;至于"为什么改上游动不了拦截逻辑",回看下面这张数据走向图就明白了。

回看数据走向:哈希表命中后的两个分支

整台 C3 在网里扮演的角色类似"守门员":每个进来的查询先在门口盘一遍,广告域名当场拦下;盘不出问题的,再交给它请的"外援"——上游解析器——去跑腿查真实 IP。一条查询的完整路径:

客户端 DNS 查询 (UDP 53) │ ▼ 提取域名 → 做 FNV-1a 40 位哈希 │ ▼ 在 flash 哈希表中二分查找 │ ├─ 命中 ──▶ 直接回 0.0.0.0(sinkhole,与上游无关) │ └─ 未命中 ▶ 转发上游解析器(默认 9.9.9.9:53) │ ▼ 把答复原样回传客户端,"Total allowed" +1

关键就在"命中/未命中"这个分叉:拦截发生在转发之前,命中哈希的查询永远到不了上游;上游解析器只服务"未命中"那一支,所以换它的地址,天然碰不到拦截逻辑。这也是为什么本次改动可以只加一行参数。

小结:上游只负责"没被拦"的查询,是替换安全度最高的一环;那这一环到底该填谁的地址?

上游选谁:Quad9、Google、Cloudflare 一张表对比

解析器地址官方定位
Quad9(本项目默认)9.9.9.9安全导向,自带已知恶意域名/DGA 拦截
Google8.8.8.8全球节点覆盖广,延迟普遍较低
Cloudflare1.1.1.1主打速度与隐私
Cloudflare for Families1.1.1.2在 1.1.1.1 基础上额外过滤成人内容

三条选择建议:

  1. 先测延迟:在自家网络里对各地址各跑一次dig,挑实测快且稳定的,理论排名不如实测数;
  2. 看日志政策:对照各家的隐私声明,确认你能接受查询记录被保留多久、以什么形式保留;
  3. 看附加能力:要不要免费搭上的恶意域名拦截(Quad9)或成人内容过滤(1.1.1.2),按需取舍。

普通家宽到这几家公共解析器都能直连,不需要任何端口映射;想保留默认 Quad9,什么都不用改。

小结:按三点挑定目标地址后,回第一节改那一行参数即可;动手前再把下面三个容易混淆的边界划清楚,省得改完去排查不相干的故障。

三个易混淆的边界:拦截列表、配网与应答匹配 📌

上游 ≠ 拦截列表。换上游不会让拦截列表变新。列表更新是另一条独立链路:用 tools/build_blocklist.py 把域名源构建成blocklist.bin,再经控制台Blocklist → Upload上传,或在Remote auto-update里填一个 URL 让设备按设定间隔自动拉取——两条路都和本次改动互不干扰。

设备连不上网 ≠ 上游的锅。如果切换后设备直接离线,那是配网问题,不是 DNS 问题:走控制台Forget WiFi,或按住 BOOT 键上电重新进入配网引导页(详见 README.md 的 WiFi setup 一节)。

转发有防串包机制。转发函数每次先丢弃积压的过期应答,再用全新的随机事务 ID(txid)发查询,且只接收 txid、问题段、源地址/端口三者都对得上的应答——多客户端并发时不会把 A 的答复错发给 B。这套机制与上游是谁无关,换了照样生效。

小结:列表更新、WiFi 配网、应答匹配三件事各走各的链路,排查故障时先分清属于哪一支,就能少跑不少弯路。

行动清单:按上表选定上游地址 → 在platformio.ini的[env:c3]加一行-DUPSTREAM_IP→pio run -t upload(或控制台 OTA 上传固件)→ 两条dig确认"广告域名仍被拦、正常域名走新上游"。

资源索引:

  • src/main.cpp:主程序入口,UPSTREAM_IP/UPSTREAM_PORT默认值(第 24~29 行)与上游转发逻辑都在这里;
  • platformio.ini:PlatformIO 构建配置,本文唯一的改动位置;
  • src/page.h:Web 控制台页面源码,固件 OTA 与拦截列表上传的入口;
  • tools/build_blocklist.py:拦截列表构建脚本,把域名源编译成blocklist.bin哈希表;
  • partitions.csv:分区表,决定固件双 OTA 槽位与拦截列表容量的取舍;
  • README.md:完整文档,含配网引导、OTA 细节与已知坑位。

一句话收尾:改一行参数、烧一次录、两条dig验证——上游从此由你自己说了算。

【免费下载链接】esp32-c3-adblockPi-hole-class DNS ad-blocker on a $2 ESP32-C3 (no PSRAM): 537k domains as 40-bit FNV-1a hashes in flash, binary-searched. UDP DNS sinkhole + web dashboard. https://youtube.com/shorts/RaxszOUMi8E?feature=share项目地址: https://gitcode.com/GitHub_Trending/es/esp32-c3-adblock

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考