ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

DNS Sinkhole是如何工作的?esp32-c3-adblock去广告协议原理一文讲透

DNS Sinkhole是如何工作的?esp32-c3-adblock去广告协议原理一文讲透 DNS Sinkhole是如何工作的esp32-c3-adblock去广告协议原理一文讲透【免费下载链接】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?featureshare项目地址: https://gitcode.com/GitHub_Trending/es/esp32-c3-adblock这篇文章带你一文讲透DNS SinkholeDNS 黑洞的协议原理主角是开源项目esp32-c3-adblock一块售价约 2 美元、不带 PSRAM的 ESP32-C3 开发板就能跑起 Pi-hole 风格的全屋 DNS 去广告。它的杀手锏是把537,000 个广告域名压缩成 40-bit FNV-1a 哈希存进 flash用二分查找定位单次拦截查询约10 毫秒响应全程只占约50 KB RAM。下面从协议层到工程实现逐层拆解。一、3 分钟看懂 DNS Sinkhole 工作原理浏览器访问doubleclick.net之前需要先向 DNS 服务器问一句它的 IP 是多少——这就像查电话簿。DNS Sinkhole 的核心套路在路由器旁边放一台山寨 DNS 服务器客户端的查询先到它这里域名在广告黑名单里 → 不查真实 IP直接回一个黑洞地址0.0.0.0广告请求发到一个不存在的 IP直接失败域名不在名单里 → 原样转发给上游 DNS默认 Quad99.9.9.9拿到答案后再原路交回客户端。项目 README 里用一张极简流程图概括了整条链路查询进来 ──▶ 提取域名 ──▶ FNV-1a 哈希 各级父域名 ──▶ 二分查找 flash 哈希表 ├─ 命中 ──▶ 回复 0.0.0.0被黑洞拦截 └─ 未中 ──▶ 转发上游解析器中继应答DNS 本身是无状态的 UDP 协议所以中间人式的改写成本极低——这正是 ESP32 这种小芯片也能胜任的原因。DNS 报文解析与应答构造的实现可以对照 src/main.cpp 阅读。二、痛点为什么大多数 ESP32 去广告方案要 PSRAM主流做法是把域名字符串整表搬进 RAM 做比对。一个域名平均十几到二十几个字节14 万个域名就要吃掉约 2.5 MB RAM——远超 ESP32-C3 自带的 400 KB 内存只好外挂 PSRAM硬件成本翻到 $8 左右。esp32-c3-adblock 的思路完全不同域名字符串不进 RAM固定 5 字节40 bit的哈希进 flash对比项字符串进 RAM 方案本项目哈希进 flash硬件ESP32 PSRAM约 $8ESP32-C3无 PSRAM约 $214.1 万域名占用约 2.5 MB RAM0.67 MB flash运行内存大部分 RAM约 50 KB单次查找字符串比对约 18 次 flash 读取含 WiFi 往返约 10 ms哈希冲突不存在14.1 万域名下为053.7 万个时约 1 个三、核心技巧哈希进 flash 二分查找3.1 为什么是 40-bit FNV-1a每个域名用 FNV-1a 算法算出 64 位哈希再**截断成 40 位5 字节**存入 flash。为什么偏偏是 40 位这是生日悖论算出来的甜点40 bit14.1 万域名冲突约 0 个53.7 万个也仅约 1 个极个别域名被误伤32 bit省 20% flash但 25 万域名时冲突涨到约 7 个误伤明显变多64 bit每个域名多花 3 字节解决的却是一个本不存在的问题。哈希函数的实现只有几行见 src/main.cpp#L79-L83。3.2 二级索引 二分查找把 flash 读取压到最少flash 里的哈希表是排序好的天然适合二分查找。但 flash 随机读很慢项目又加了一层优化一级索引开机时从 flash 表中等距抽取 4096 个采样哈希载入 RAM仅 20 KB先定位目标大概落在哪个区间区间内线性比对每个区间最多 256 个哈希一次读出整块 buffer 再在 RAM 里比256 槽直接映射缓存热点域名第二次查询直接命中不再读 flash。三级合起来一次查询约18 次 flash 读取核心逻辑在 src/main.cpp#L103-L138。3.3 一个域名连子域名一起拦只匹配精确域名是不够的ads.example.com、trk.ads.example.com全得拦。于是isBlocked会对域名逐级父级依次取哈希比对a.b.c.d→b.c.d→c.d实现父域名命中即全子树拉黑见 src/main.cpp#L161-L170。这也是黑名单工具能省掉海量通配符规则的原因。四、一次查询的完整旅程约 10 毫秒把前面各环节串起来一条 UDP DNS 查询在设备内的旅程是解析parseQuery从报文剥出域名顺手去掉www.前缀省掉一半冗余哈希判定父域名逐级哈希 → 缓存 / flash 二分查找命中buildBlocked原地改写报头0x8180表示这是应答追加一条指向0.0.0.0的 A 记录回包构造细节见 src/main.cpp#L236-L241。这里藏着一个新手必踩的坑DNS 客户端普遍带EDNS OPT 记录被拦截的应答必须只保留 question 一条 answerNSCOUNTARCOUNT0否则报文畸形直接丢弃未命中forwardUpstream换上一个新的随机事务 ID 转发给 Quad9且只接受事务 ID、问题区、来源地址三者的应答先排空残留报文再发送——这是为了根治慢回复串包导致每个答案错位一位的经典 bugsrc/main.cpp#L247-L271。整个过程不阻塞主循环设备在空闲时还会主动让出 CPU既快又凉快。五、不只是去广告Web 控制台 全 OTA这个 $2 小盒子还自带一个完整的运维面Web 仪表盘c3adblock.local每台设备的拦截/放行计数、一键封禁某台设备、自定义添加黑名单域名WiFi 零配置没连上网时自动变身开放热点C3-AdBlock-XXXX 强制门户手机选个 WiFi、输密码即完成配置无需重新刷机固件与黑名单双 OTA浏览器上传新固件 / 新黑名单或填一个 URL 定时自动拉取更新刷完一次 USB 之后彻底解放。4 MB flash 有个有趣的取舍见 partitions.csv双固件槽支持 OTA留给黑名单约 1.3 MB ≈25 万域名单槽布局则能塞下53.7 万域名的极限版但牺牲固件 OTA。懒得装 PlatformIO项目内置了浏览器一键刷机页docs/index.htmlChrome/Edge 插上板子点一下约 30 秒完成固件 黑名单写入零工具链。六、快速上手4 步变成全屋去广告网关硬件任意 ESP32-C3 板作者实测 C3 SuperMini约 $24 MB flash无需 PSRAM手机充电头或路由器的 USB 口供电即可想更精致仓库附了可打印外壳 hardware/esp32-c3-supermini-enclosure.stl注意别把天线端埋进实心塑料刷机按 platformio.ini 配置依次执行——复制 src/secrets.example.h 为secrets.h并设置控制台/OTA 密码必填否则局域网任何人都能重写固件→ 运行 tools/build_blocklist.py 生成哈希表 →pio run -t uploadpio run -t uploadfs一次性写入固件和 LittleFS 文件系统配网上电后连上热点C3-AdBlock-XXXX选择家里 WiFi 并输入密码设备自动重连生效与验证把设备 IP 设为路由器或单台设备的 DNS然后测试dig c3-ip doubleclick.net # - 0.0.0.0 (被拦截) dig c3-ip github.com # - 真实 IP (正常转发)自定义黑名单同样灵活build_blocklist.py支持 hosts 文件、纯域名列表、AdGuard/AdBlock 基础规则三种格式混用还支持白名单规则把某个域名从黑名单里豁免出来。七、常见问题 FAQQ1为什么回复 0.0.0.0而不是 NXDOMAIN域名不存在因为 0.0.0.0 对几乎所有 HTTP 客户端意味着连接立即失败行为最确定且 A 记录应答0.0.0.0能同时兼容 IPv4 解析报文结构也更简单。Q2会不会误伤正常网站40-bit 哈希在 14.1 万域名下冲突数为 053.7 万域名的极限版也仅约 1 个生日悖论式冲突——概率上约等于某个倒霉域名被多拦日常使用的平衡名单基本无感。Q324 小时挂着功耗和发热如何静态功耗仅几瓦以内芯片温度约 45–55 °C用外壳时保留散热孔、别遮挡天线即可。空闲时固件会自动休眠有负载才满速运行。Q4它还能进化成什么作者在 Roadmap 里留了两个方向分桶前缀索引把单次查找从约 18 次 flash 读取压到 1–2 次吞吐翻倍的关键以及直接充当 DHCP 服务器把自己发给每台设备实现真正的插电即用。八、项目文件地图按需深入文件说明README.md完整文档原理、构建、OTA、安全模型、踩坑记录src/main.cpp全部核心逻辑DNS Sinkhole、哈希二分查找、Web 仪表盘、OTAtools/build_blocklist.py黑名单预处理域名 → 排序的 40-bit 哈希 blobpartitions.csv4 MB flash 分区布局OTA 槽 vs 大容量黑名单的取舍platformio.iniPlatformIO 构建配置C3 / 经典 ESP32 双环境docs/index.html浏览器一键刷机页含 docs/manifest.json 刷机清单hardware/esp32-c3-supermini-enclosure.stl3D 打印外壳模型小结DNS Sinkhole 本质是在 DNS 电话簿里把广告页撕掉而 esp32-c3-adblock 的精彩之处在于证明了一件事——不需要 PSRAM、不需要大树莓派2 美元的芯片 排序哈希表 二分查找就能以 10 毫秒的延迟撑起全屋级别的去广告网关。这套哈希进 flash的技巧对任何大存储预算、小内存预算的嵌入式场景都通用值得一读。【免费下载链接】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?featureshare项目地址: https://gitcode.com/GitHub_Trending/es/esp32-c3-adblock创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表