☰
ESP32-C3开发板制作局域网DNS广告拦截器,低成本净化家庭网络
2026/10/9 1:50:42 网站建设 项目流程

手里这块 ESP32-C3 开发板,原本是拿来练 RISC-V 指令集用的。结果某天晚上被电视盒子每隔十分钟弹一次的推广卡片烦到崩溃,突然灵光一闪:这板子带 WiFi,又有 4MB Flash,跑一个小型的 DNS 服务器绰绰有余,那不如把它改造成家庭局域网里的广告拦截器。这个想法落地之后,家里的电视盒子、手机、电脑看视频和刷网页时清净了不少,而且整件事的成本不到二十块钱,不需要动路由器固件,也不影响家人正常上网。

下面就把我踩过的坑和整个改造过程完整写出来。适合手里正好有一块 ESP32-C3 开发板、但还没想好能做什么的人,也适合被智能电视广告烦到想自己动手解决的人。你不需要精通通信协议,只要会看串口日志、会登录路由器后台,就能照着重现。

1. 为什么选中 ESP32-C3 开发板来挡广告

1.1 先看看传统拦截方案有哪些坑

浏览器插件确实能拦掉网页广告,但它只能在浏览器里起作用。到了电视盒子、智能冰箱、扫地机器人这些设备上,插件完全没有用武之地。改 hosts 文件也能挡广告,但每一条记录都要手工维护,域名列表一多就容易错,而且手机上的 App 不一定走 hosts 逻辑,很多还会无视本地解析直接连后台地址。给主路由器刷第三方固件是最彻底的思路,可风险也最大,刷错一次全家断网,家里人还容易把账算到你头上。

ESP32-C3 开发板做独立广告过滤器,解决的正是这个痛点。它不需要改变主路由器的固件,也不需要在每台设备上安装软件,只要让局域网设备把 DNS 指到这块板子,拦截动作就在网络底层完成。一套设备,覆盖全家设备,这是浏览器插件和本机 hosts 都做不到的。

1.2 ESP32-C3 的硬件底子凭什么能胜任

ESP32-C3 是一颗 160MHz 单核 RISC-V 芯片,集成 2.4GHz WiFi 和蓝牙 5.0,常见开发板板载 4MB Flash。放在十年前,这种配置只能算单片机;但用来处理家庭局域网的 DNS 查询,绰绰有余。家庭环境通常只有几十台设备,每秒 DNS 请求量也不会超过几十条,ESP32-C3 处理这些小数据包根本不费力,实测 CPU 占用常年很低。

更关键的是功耗。整板在 WiFi 常开状态下大概 0.3 瓦,用手机充电头就能长期供电,连续运行一个月也没有过热问题。板子上的 USB 口还能同时做串口调试,规则写错了、域名被误杀,都能在日志里及时发现。对我来说,它比树莓派便宜,比 Arduino Uno 多了一个关键的网络能力,天生就是干这活的料。

1.3 ESP32-C3 广告过滤器的适用场景

这个方案最适合三件事:一是净化智能电视,把内置视频 App 的推广卡片从源头掐掉;二是清理手机游戏和资讯类 App 里的追踪域名;三是给只有 2.4GHz WiFi 的老设备做统一过滤。如果你家里有 NAS 或者树莓派常开,也可以不买 ESP32-C3,直接在那些设备上跑同类型服务;但如果你希望用一个低功耗、独立、不干扰现有服务的小盒子,ESP32-C3 的性价比就非常突出。

需要说明的是,广告拦截不是玄学。像电视开机广告如果是网络动态下发广告图,DNS 过滤可以有效;如果广告资源已经预先打包在系统固件里,完全离线播放,那 DNS 过滤拦不了。后面我会讲到如何把这种预期管理做到位,别到时候以为是自己没配置好。

2. 广告拦截方案对比:为什么 DNS 过滤最省心

2.1 主流拦截手段的性能对比

我把自己试过的几种思路放在一张表里,方便你快速判断:

方案覆盖范围维护成本主要风险
浏览器插件仅浏览器低对 App 无效
本地 hosts单台设备高移动 App 不理会
路由器第三方固件全家高刷机风险大
ESP32 DNS 过滤全家中规则误杀

浏览器插件适合办公电脑,hosts 适合喜欢折腾服务器的朋友,路由器第三方固件适合已经具备救砖能力的老手。而 ESP32-C3 方案夹在中间,它给普通家庭用户提供了一条不用改变现有网络结构、又能覆盖全部设备的中间路线。我当时选它没有太多犹豫,因为不想把每天都要用的家庭网络搞成实验现场。

2.2 DNS 过滤的原理:从域名到 IP 的“查号台”

设备访问任何一个网站或广告服务器之前,必须先把域名翻译成 IP 地址,这个过程就叫 DNS 解析。你可以把 DNS 服务器想象成电话查号台:你想联系“某广告商”,先拨查号台问号码,查号台给你一个错误号码,你就永远联系不上它。

ESP32-C3 扮演的正是这个“查号台”。当电视盒子询问ad.xxx.com的 IP 时,ESP32-C3 发现这个域名在拦截列表里,就返回一个不可达地址,比如0.0.0.0,设备连接失败,广告自然加载不出来。当设备询问正常域名时,它照常向上游公共 DNS 查询,拿到真实 IP 后返回给设备。整个过程就是一次 UDP 53 端口的问答,处理逻辑非常直接。

2.3 需要准备的材料清单

实际材料比想象中少,我列一下:

  • ESP32-C3 开发板一块,任意品牌都可以,只要是 ESP32-C3 芯片
  • USB Type-C 数据线一根,如果是老款 micro USB 板子就准备对应线
  • 5V/1A 充电头或电脑 USB 口,用来给板子供电
  • 一台电脑,用于烧录程序和查看日志
  • 路由器管理后台的登录账号,用来改 DHCP 下发的 DNS

这里提醒一句,数据线尽量选质量好的。市面上很多 USB 线只能充电,不能传输数据,烧录时会导致设备无法识别。我一开始翻出一根拖线板的线,插上后电脑完全没反应,后来换了键盘的原装线才正常,这个问题很隐蔽。

3. 烧录与接线:给开发板灌入“拦截大脑”

3.1 安装 Arduino 环境并添加 ESP32 开发板管理器

整个固件开发我用的是 Arduino IDE,原因是生态成熟、示例多,不用从底层寄存器开始写。先打开 Arduino IDE 的“首选项”,在“附加开发板管理器地址”里填入:

https://dl.espressif.com/dl/package_esp32_index.json

然后打开“工具 -> 开发板 -> 开发板管理器”,搜索esp32,选择 Espressif 官方包安装。安装完成后,在“开发板”下拉菜单里选择ESP32C3 Dev Module,串口选择识别到的那一个。插上开发板后,Windows 一般会自动装好 USB 串口驱动;如果没识别到,可以去芯片厂商页面下对应的驱动,常见的是 CP2102 或 CH340。

3.2 选现成固件还是自己写:我建议分情况

如果你只想快速用起来,可以先在开发者社区找现成的 ESP32 广告过滤固件,下载编译好的 bin 文件,用 esptool 工具或者在线烧录工具写进板子。这种方式最快,十几分钟就能跑起来,缺点是规则列表改起来不直观,遇到问题黑盒一样,不一定符合所有人的习惯。

我个人更推荐自己写一遍,因为核心代码真的不多。创建任务就是让 ESP32-C3 监听 UDP 53 端口,收到查询后解析请求里的域名,查拦截表,命中就返回不可达 IP,未命中就转发给上游公共 DNS。下面这个骨架展示了整体逻辑:

#include <WiFi.h> #include <WiFiUDP.h> #define DNS_PORT 53 const char* ssid = "你的WiFi名"; const char* password = "你的WiFi密码"; WiFiUDP udp; const char* blocklist[] = { "doubleclick.net", "googleadservices.com", "ads.example.net" }; void setup() { Serial.begin(115200); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(300); Serial.print("."); } Serial.print("\n本机IP: "); Serial.println(WiFi.localIP()); udp.begin(DNS_PORT); } void loop() { int packetSize = udp.parsePacket(); if (packetSize) { // 1. 从 packetBuffer 中解析出被查询的域名 QNAME // 2. 与 blocklist 做后缀匹配 // 3. 命中则构造 DNS 响应,返回 0.0.0.0 // 4. 未命中则把原始请求转发到上游公共 DNS,如 223.5.5.5 } }

这里最关键的一点是“后缀匹配”而不是“完整匹配”。广告服务商为了让反拦截机制失效,经常给域名换随机子域名,比如a1.ads.example.net、a2.ads.example.net,如果只匹配固定字符串,马上就会漏。我实际验证过,用后缀匹配以后,在规则总数相同的情况下拦截率能提升不少。

3.3 第一次上电前的检查清单

烧录之前,先把下面几项检查一遍,能省掉很多不必要的折腾:

  • 开发板和电脑之间用能够传输数据的数据线连接,不是那种只能充电的线
  • Arduino IDE 右下角显示的端口确实对应 ESP32-C3,不要选错成其他串口设备
  • 波特率设置为 115200,方便看启动日志
  • 代码里的 WiFi 名称和密码填得没有空格、没有大小写错误
  • 如果板子和路由器的距离太远,先拿到路由器旁边调试,避免信号弱导致反复重连

第一次上电时,建议打开串口监视器观察日志。正常情况会看到板子先打印一串点,然后出现本机IP: 192.168.x.x。看到这个 IP,说明板子已经成功加入局域网,接下来就是让其他设备“听”它的指令了。

4. 把 DNS 指过来:三种接入方式实操

4.1 方式一:在路由器 DHCP 里改 DNS

这是覆盖全家设备的最推荐做法。登录路由器管理后台,找到“DHCP 服务器”设置页,把首选 DNS 改成 ESP32-C3 的 IP,比如192.168.1.88。备用 DNS 建议填一个公共 DNS,比如223.5.5.5,这样即使 ESP32-C3 临时挂掉,设备还能正常上网,不会出现全家断网的尴尬。

需要注意的是,改的是内网 DHCP 下发给设备的 DNS,不是路由器 WAN 口的 DNS。很多朋友第一次操作容易搞混,把路由器自身联网用的 DNS 也改掉了,导致路由器自己解析异常。你就记住一条:DHCP 页面里的 DNS 是写给手机电脑看的,WAN 口配置里的 DNS 是路由器自己用的,别动后者。

4.2 方式二:在单台设备上改 DNS

如果不想影响全家,只打算让电视盒子或某一台电脑走过滤,可以直接在这台设备上手动设置 DNS。Windows 在“网络适配器 -> 属性 -> 使用下面的 DNS 服务器地址”里填 ESP32-C3 的 IP;安卓在 WiFi 长按选择“修改网络”后,把 IP 设置改成静态,DNS 1 填 ESP32-C3;iPhone 在“配置 DNS -> 手动”里添加;电视盒子通常在“网络设置”的高级选项里有 DNS 填写栏。

这台设备的系统会优先使用手填 DNS 地址,因此不会去请求路由器下发的默认 DNS。如果以后想让设备恢复原样,把 DNS 改成自动获取即可。这种做法的好处是随时可以回退,适合先做小范围测试,确认你的电视盒子真的能被挡住广告之后,再决定要不要在路由器层面开启全家过滤。

4.3 方式三:做成一个常亮的“DNS 盒子”

ESP32-C3 没有以太网口,只有 WiFi,所以它没法像硬路由那样做物理串联,它本质上是局域网里的一个“独立 DNS 服务器节点”。比较稳定的做法是,在路由器后台给 ESP32-C3 绑定静态 IP,然后其他设备通过 DHCP 自动把 DNS 指到它,这就是前面两个方式组合后的长期运行状态。

我自己家里就用这个方式:ESP32-C3 放在客厅角落,用充电头供电,路由器 DHCP 把首选 DNS 指向它的静态 IP。平时完全没有存在感,只有打开日志想找广告域名的时候才意识到它一直在干活。这种“盒子”形态比插在电脑上更靠谱,因为电脑关机、休眠都不影响它工作。

5. 实测:用真实流量看拦截效果

5.1 拦截前后对比

配置完成后,我在电脑上用 ping 命令测试广告域名。拦截前能 ping 到真实 IP,延迟 20 多毫秒;把系统 DNS 改成 ESP32-C3 后,再 ping 同一个域名,返回的是0.0.0.0或者直接超时,说明请求已经被丢进黑洞。

实际体验中最明显的是电视盒子里的视频 App。改动之前打开首页,推荐信息流里夹杂着各种推广卡片,还在右上角时不时弹出红包动画;改动之后,这些位置变成空白或者显示加载失败占位图,视频正片加载完全不受影响。手机上的资讯 App 同样清净了很多,以前每刷两屏就有一个原生广告,现在基本被干掉了,滚动速度也快了不少。

5.2 延迟与功耗实测

用网络抓包工具连续观察一段时间后,我发现命中的广告域名直接由 ESP32-C3 返回,延迟不到 1 毫秒;未命中的正常域名需要转发到上游公共 DNS,整体解析耗时大约增加 2 到 4 毫秒。这个体量人眼完全感知不到,看视频、开网页都毫无影响。

功耗方面,我实际用 USB 电流表测过,板子 WiFi 常开、待机等查询时电流在 70mA 左右,按 5V 供电算,整板功耗大约 0.35W。一个月电费不到两毛钱,全年跟一块钱差不多。这也是我敢让它 7x24 小时常开的原因,长期下来几乎没有电费负担。

5.3 规则库怎么更新和维护

规则列表是这个项目里唯一需要持续维护的东西。广告域名的变化速度很快,新广告系统上线、旧广告域名下线,如果没有规则更新,拦截效果会逐渐变弱。我的维护方式比较简单:通过串口输入命令添加或删除规则,同时在程序里把规则列表存在 SPIFFS 文件系统里,这样断电重启后规则不会丢。

如果你想精细维护,可以让板子定时从公开的广告域名列表抓取更新,只要这个列表来自可信渠道、更新频率合理就行。我个人的建议是,不要盲目引入几十万条的大名单,规则越多误杀概率越大,日常使用的核心规则控制在几千条以内,既稳定又容易排查。

6. 常见问题与排查技巧实录

6.1 问题速查表

我在使用过程中归纳了几个高频问题,直接做成速查表方便你对比:

现象可能原因解决办法
手机连上 WiFi 但打不开网页设备的 DNS 没拿到或指向错误检查 DHCP 设置,确认首选 DNS 是 ESP32-C3 静态 IP
部分正常网站打不开域名被规则误杀在串口日志里找到被拦截的域名,加入白名单
重启后之前加的规则全没了规则只存在内存里把规则写入 SPIFFS 或 NVS,启动时读取
电视盒子广告还在广告资源离线打包在系统固件里这种广告只能靠厂商修改,DNS 过滤拦不了
板子偶尔掉线路由器下面设备太多或信号弱给板子指定信道,或放在路由器更近的位置
串口日志乱码波特率或接线问题把串口波特率固定为 115200,换根数据线

这些里面,最容易被低估的是“白名单”功能。我第一次上线就发现某个新闻 App 的正文图片全部加载不出来,查了日志才发现它用的图片 CDN 域名里带一个ad子串,被我无差别匹配给拦了。把该域名加进白名单后一切正常,从那以后我检查每条新规则都会想想会不会误伤。

6.2 从日志入手定位 DNS 异常

串口日志是整个系统最好的诊断入口。我在代码里会打印每个查询的域名和动作,比如[BLOCKED] ads.example.net或[FORWARD] www.example.com,通过观察这个输出,几分钟就能定位是规则问题、网络问题还是 DNS 转发问题。

如果你看到[BLOCKED]很多,但广告依旧出现,说明设备没有把 DNS 指向 ESP32-C3,多半是 DHCP 配置没生效。如果你看到[FORWARD]之后很久才返回,说明上游 DNS 延迟高,可以考虑换一个更近的公共 DNS。日志不是只在出问题时看,我每周都会扫一眼,顺便能找到不少新增广告域名。

6.3 稳定运行两个月的小技巧

让 ESP32-C3 稳定运行,除了供电要稳,我给板子加了一个很小的铝散热片粘在芯片背面,触摸板体时温度从六十多度降到五十度上下。另外,在 Arduino 代码里加了 WiFi 掉线重连逻辑,每隔 30 秒检查一次连接状态,如果掉线就主动重连,避免长时间运行后卡在断网状态。

还有一个容易被忽略的点:给 ESP32-C3 设置静态 IP 时,最好避开路由器 DHCP 地址池的常用范围,比如家用路由器地址池从192.168.1.100开始,那我给它固定成192.168.1.88,降低被分配出去的碰撞概率。方法是在 Arduino 代码里用WiFi.config()设置固定 IP、网关和子网掩码,或者在路由器后台做静态地址绑定,两种方式任选其一。

最后说一个我反复用到的经验:规则列表别贪多。网上有一些几十万条的 hosts 大名单,看着拦截率高,实际误杀也高,很可能把某个正常更新服务给挡了。我从两万条精简到五千条核心规则之后,干扰明显下降,拦截效果反而更稳定。清理广告这件事,讲的是精准,不是数量。这块 ESP32-C3 开发板现在就在书房的插线板上安静地亮着,每隔一段时间我会翻一下日志,顺手把失效的规则删掉,把新出现的广告域名加进去。整个过程已经变成一种很自然的使用习惯,而家里人也早已忘记它是一块单片机。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询