ESP32-C3 ตัวเล็กที่ไม่มี PSRAM จะเก็บ Blocklist หลักแสนโดเมนได้อย่างไร? โปรเจกต์ esp32-c3-adblock แก้โจทย์ด้วยการไม่เก็บชื่อ Domain เป็น String ใน RAM แต่แปลงเป็น 40-bit FNV-1a Hash ขนาด 5 Bytes แล้วเก็บเรียงไว้ใน Flash ผลคือ ESP32-C3 SuperMini ที่มี Flash 4 MB สามารถทำหน้าที่เป็น DNS Sinkhole พร้อม Web Dashboard, OTA และ Blocklist ขนาดใหญ่ได้ โดย Configuration สูงสุด รองรับประมาณ 537,000 Domains แต่ต้องแลกกับการปิด Firmware OTA

ESP32-C3 ทำ DNS Ad Blocker บล็อกกว่า 500,000 โดเมนโดยไม่ใช้ PSRAM

ESP32-C3 ตัวเล็ก ๆ ที่มี Flash เพียง 4 MB จะเอา Blocklist หลักแสนโดเมนไปเก็บไว้ตรงไหน โดยเฉพาะเมื่อไม่มี PSRAM ให้ยัดชื่อเว็บไซต์ทั้งหมดลงไป?

โปรเจกต์ open-source esp32-c3-adblock ของ M-Abozaid เลือกแก้โจทย์ด้วยวิธีที่น่าสนใจกว่าเพิ่ม RAM: ไม่เก็บ Domain เป็น String ในหน่วยความจำ แต่แปลงแต่ละชื่อให้เหลือ 40-bit FNV-1a Hash ขนาดเพียง 5 Bytes แล้วเก็บ Hash ที่เรียงลำดับไว้ใน Flash

ผลคือ ESP32-C3 SuperMini สามารถทำหน้าที่เป็น Pi-hole-style DNS Sinkhole พร้อม Web Dashboard, Blocklist Update และ OTA ได้ โดย Configuration ที่เน้นความจุสามารถขยายไปถึงประมาณ 537,000 Domains ตามข้อมูลของผู้พัฒนา

แต่คำว่า “รองรับกว่า 500,000 Domains” มี Trade-off ที่ต้องรู้ก่อน: Maximum-capacity Configuration นี้ต้องใช้ Single-app Partition และแลกกับการปิด Firmware OTA

ESP32-C3 SuperMini DNS Ad Blocker ในเคสพิมพ์ 3D พร้อม USB-A Adapter
ESP32-C3 SuperMini DNS Ad Blocker ในเคสพิมพ์ 3D พร้อม USB-C to USB-A Adapter สำหรับเสียบกับแหล่งจ่ายไฟหรือ USB ของ Router
Key Takeaways
  • โปรเจกต์ใช้ ESP32-C3 ที่มี Flash 4 MB และไม่ต้องมี PSRAM
  • Domain ถูกเก็บเป็น 40-bit FNV-1a Hash ขนาด 5 Bytes แทน String
  • 140,000+ Domains ใช้ Flash ประมาณ 0.67–0.7 MB ตามข้อมูลของผู้พัฒนา
  • ผู้พัฒนารายงาน RAM Usage ประมาณ 50 KB
  • ผู้พัฒนารายงาน Lookup ประมาณ 10 ms ในบริบทที่รวม Wi-Fi Round-trip Time
  • Dual-app Partition รองรับ Blocklist ประมาณ 250k พร้อม Firmware OTA
  • Single-app Partition ขยายไปประมาณ 537k แต่ Firmware OTA ใช้ไม่ได้
  • มี Web Dashboard, Captive Portal, Remote Blocklist Update และ OTA
  • มี STL เคสสำหรับ ESP32-C3 SuperMini ใน Official Repository

ESP32-C3 AdBlock คืออะไร?

esp32-c3-adblock เป็น Open-source DNS Ad Blocker ที่พัฒนาให้ทำงานบน ESP32-C3 โดยไม่ต้องพึ่ง PSRAM

แนวคิดใกล้เคียงกับ DNS Sinkhole: Client ใน Network ส่ง DNS Query มายัง ESP32-C3 แล้วอุปกรณ์จะตรวจว่า Domain นั้นอยู่ใน Blocklist หรือไม่

ถ้าอยู่ใน Blocklist Firmware จะตอบกลับด้วย 0.0.0.0 เพื่อทำให้ Request นั้นไปต่อไม่ได้ตามแนวทางของโปรเจกต์

ถ้า Domain ไม่อยู่ใน Blocklist Query จะถูก Forward ไปยัง Upstream DNS Resolver แล้วส่งคำตอบกลับมายัง Client

สิ่งที่ทำให้โปรเจกต์นี้น่าสนใจ: ปัญหาหลักไม่ใช่ว่า ESP32-C3 ทำ DNS ได้หรือไม่ แต่คือจะเก็บ Blocklist ขนาดใหญ่มากใน Hardware ที่ไม่มี PSRAM อย่างไร

DNS Sinkhole ต่างจาก Browser Ad Blocker อย่างไร?

โปรเจกต์นี้ทำงานในระดับ DNS ไม่ใช่ Extension ที่ติดตั้งอยู่ใน Browser

Device ที่ต้องการใช้ระบบนี้ ต้องส่ง DNS Request มายัง ESP32-C3 หรือวาง ESP32-C3 เป็น Resolver ตาม Network Configuration ที่ผู้ใช้กำหนด

README ระบุว่าสามารถชี้ DNS ของอุปกรณ์ไปยัง IP ของ C3 หรือใช้เป็น Secondary Resolver อยู่ด้านหลัง Main DNS ได้

เมื่อ Domain ตรงกับ Blocklist ระบบจึงตัดสินใจตั้งแต่ขั้นตอน DNS Resolution ก่อนที่จะเชื่อมต่อไปยังปลายทาง

อย่าตีความว่า Block โฆษณาได้ 100%: Source ไม่ได้ให้ตัวเลขเปอร์เซ็นต์ Ad-blocking Success Rate และไม่ได้รับรองว่าจะจัดการโฆษณาทุกประเภทได้ บทความนี้จึงไม่อ้างประสิทธิภาพเกินขอบเขตของ Source

ไม่มี PSRAM แต่เก็บ Blocklist ใหญ่ได้ เพราะไม่เก็บชื่อ Domain แบบเดิม

ถ้าเก็บ Domain เป็น String ชื่อ Domain แต่ละรายการจะมีความยาวไม่เท่ากัน และการเก็บรายการหลักแสนรายการใน RAM สามารถกิน Memory ได้มาก

Project นี้เลือกอีกวิธี: นำ Domain ไปคำนวณ FNV-1a Hash แล้วตัดให้เหลือ 40 Bits

40 Bits เท่ากับ 5 Bytes ต่อรายการ ทำให้ขนาดข้อมูลของแต่ละ Entry คงที่ และสามารถเรียง Hash ทั้งหมดไว้ใน Flash เพื่อค้นหาภายหลังได้

แนวทาง ข้อมูลจากผู้พัฒนา
เก็บ Domain String ใน RAM ผู้พัฒนายกตัวอย่างว่า 141k Domains อาจใช้ RAM ราว 2.5 MB ใน String-based Approach
40-bit Hash ใน Flash 141k Domains ใช้ Flash ประมาณ 0.67–0.7 MB และ RAM โดยรวมประมาณ 50 KB ตามรายงานของผู้พัฒนา
Hash Size 5 Bytes ต่อ Domain Hash

จุดสำคัญคือ Blocklist ไม่จำเป็นต้องถูกโหลดเป็น Domain String ทั้งก้อนเข้ามาอยู่ใน RAM จึงลดข้อจำกัดเรื่องหน่วยความจำลงอย่างมาก

ทำไมต้อง 40-bit? ทำไมไม่ใช้ 32-bit หรือ 64-bit ไปเลย?

Official README อธิบายว่าผู้พัฒนาเลือก 40 Bits เพราะมองว่าเป็นจุดสมดุลระหว่าง Flash Usage และโอกาสเกิด Hash Collision

Hash Width ข้อแลกเปลี่ยนตาม Developer
32-bit ใช้ Flash น้อยลง แต่ผู้พัฒนาประเมินว่าที่ประมาณ 250k Domains อาจเกิดราว 7 Collisions
40-bit 5 Bytes ต่อ Entry ถูกเลือกเป็น Sweet Spot สำหรับ Flash Budget ของโปรเจกต์
64-bit ใช้ 8 Bytes ต่อ Entry ซึ่งเพิ่มอีก 3 Bytes ต่อ Domain เพื่อแก้ปัญหา Collision ที่ผู้พัฒนาเห็นว่าไม่จำเป็นใน Scale นี้

ผู้พัฒนาประเมินว่า Blocklist ราว 141k Domains มี Collision ใกล้ศูนย์ ขณะที่รายการประมาณ 537k Domains อาจมีประมาณหนึ่ง Collision

Collision ไม่ได้แปลว่า Firmware พัง: ในบริบทของ Hash-based Blocklist Collision อาจทำให้ Domain ที่ไม่ได้ตั้งใจ Block ถูกมองว่า Match กับ Hash ที่อยู่ในรายการ ผู้พัฒนาเรียกผลลัพธ์นี้ในเชิง Over-blocking และตัวเลข Collision ข้างต้นเป็นการประเมินจากผู้พัฒนา ไม่ใช่ Accuracy Benchmark ของ GlobalByte

เมื่อ DNS Query เข้ามา ESP32-C3 ทำอะไรบ้าง?

DNS Query
↓ Extract Domain
↓ FNV-1a 40-bit Hash + Parent Suffix
↓ Search Blocklist ใน Flash
↓ Match → ตอบ 0.0.0.0
ไม่ Match → Forward ไป Upstream DNS

Firmware ไม่ตรวจเฉพาะ Domain เต็มเพียงรายการเดียว แต่ยังคำนวณ Parent Suffix ตาม Logic ที่ Source Code ระบุ

นั่นหมายความว่า Block Rule ระดับ Parent Domain สามารถมีผลกับ Subdomain ตามวิธีการ Matching ของโปรเจกต์

Official README รายงาน Lookup ประมาณ 10 ms ในบริบทที่รวม Wi-Fi Round-trip Time และอธิบายแนวทางเดิมว่าใช้ประมาณ 18 Flash Reads สำหรับการค้นหา

ตัวเลข Performance ต้องอ่านคู่กับ Version: Current Source Code มี First-level Flash Index, Cache และ Range Buffer เพิ่มเข้ามาแล้ว ดังนั้นบทความนี้จะไม่สรุปว่า ทุก Query ใน Current Version ต้องอ่าน Flash 18 ครั้งเสมอ เพราะ Source ไม่มี Benchmark ใหม่ที่ยืนยันตัวเลขนั้นสำหรับทุกกรณี

141k, 250k และ 537k Domains ต่างกันอย่างไร?

ตัวเลขทั้งสามชุดไม่ได้หมายถึง Configuration เดียวกัน และนี่เป็นจุดที่สำคัญที่สุดก่อนเอาคำว่า “รองรับกว่า 500,000 Domains” ไปใช้งาน

ระดับ Blocklist จุดเด่น Trade-off
ประมาณ 141k ใช้พื้นที่ราว 0.67–0.7 MB และ Developer ประเมิน Collision ใกล้ศูนย์ เป็นตัวอย่างหลักสำหรับอธิบาย Memory Efficiency
ประมาณ 250k ใช้กับ Dual-app Partition บน Flash 4 MB ยังเก็บ Firmware สอง App Slots เพื่อรองรับ Firmware OTA
ประมาณ 537k ใช้พื้นที่กับ Blocklist ได้มากที่สุดใน Configuration ที่กล่าวถึง ต้องใช้ Single-app Partition และไม่มี Firmware OTA
สรุปสั้น ๆ: ถ้าอยากได้ Firmware OTA ให้มอง Configuration แถวประมาณ 250k Domains แต่ถ้าจะดัน Blocklist ไปถึงราว 537k ต้องแลกพื้นที่ App Slot ที่ใช้สำหรับ OTA

Current Source Code ไม่ได้ค้นหา Flash แบบตรง ๆ อย่างเดียว

เมื่อเปิด Source Code ปัจจุบัน จะเห็นว่าผู้พัฒนาเพิ่มโครงสร้างช่วยลดงานค้นหา มากกว่าคำอธิบาย Binary Search แบบพื้นฐานในบทความ

ใน `main.cpp` มีองค์ประกอบ เช่น:

  • First-level Flash Index
  • Direct-mapped Cache
  • Range Buffer
  • Custom Domain List แยกจาก Flash Blocklist

แนวคิดคือใช้ Index ช่วยจำกัดช่วงของ Hash ก่อนอ่านข้อมูลช่วงที่เกี่ยวข้องจาก Flash และ Cache ผลบางส่วนเพื่อลดการค้นซ้ำ

แต่เนื่องจาก Source ไม่ได้ให้ Benchmark ใหม่ ที่ระบุ Lookup Time ของ Optimization ปัจจุบัน บทความนี้จึงไม่สร้างตัวเลข Performance เพิ่มเอง

Hardware ที่ใช้

Target หลักของโปรเจกต์คือ ESP32-C3 และ Board ที่ผู้พัฒนาระบุว่าทดสอบคือ ESP32-C3 SuperMini

รายการ ข้อมูลจาก Source
MCU / Board Target ESP32-C3, ทดสอบกับ ESP32-C3 SuperMini
CPU Single-core 32-bit RISC-V สูงสุด 160 MHz
SRAM 400 KB
Flash ขั้นต่ำ 4 MB สำหรับ Configuration ของโปรเจกต์นี้
PSRAM ไม่จำเป็น
Wi-Fi 2.4 GHz Wi-Fi
Power 5V ผ่าน USB ตามข้อมูลของโปรเจกต์

README ยังระบุว่า Classic ESP32 DevKit / WROOM มี Build Target ที่ Community ช่วยเพิ่มเข้ามา และผ่านระดับ Compile Test แต่ C3 ยังคงเป็น Target หลักที่ผู้พัฒนาทดสอบ

Power Source สำคัญ: ผู้พัฒนาแนะนำให้ใช้ USB Power ที่เสถียร เพราะ Adapter หรือ Connection ที่หลวม สามารถทำให้ Radio Brownout ระหว่าง Wi-Fi Transmit ได้

เสียบกับ Router แล้วกลายเป็น DNS Sinkhole ได้อย่างไร?

ESP32-C3 SuperMini DNS Ad Blocker เสียบกับพอร์ต USB ของ Router
ตัวอย่าง ESP32-C3 SuperMini เสียบกับ USB ของ Router ผ่าน Adapter โดย CNX Software ระบุว่าภาพต้นฉบับนี้ได้รับการปรับแต่งด้วย AI

USB ของ Router ในภาพทำหน้าที่เป็นแหล่งจ่ายไฟ ไม่ได้หมายความว่า Router ทุกยี่ห้อจะตั้ง DNS ให้ ESP32-C3 ให้อัตโนมัติเพียงเพราะเสียบ USB

ตาม README ผู้ใช้ต้องชี้ DNS ของ Client มายัง IP Address ของ C3 หรือจัด Network Configuration ให้ C3 อยู่ในเส้นทางการ Resolve DNS ตามที่ต้องการ

คำว่า Plug-and-play ยังมีข้อจำกัด: Repository ปัจจุบันยังมี Roadmap เรื่องให้ C3 ทำหน้าที่ DHCP Server และประกาศตัวเองเป็น DNS สำหรับ Plug-and-play แบบเต็มตัว แปลว่า Feature นี้ยังไม่ใช่สถานะปัจจุบันตาม Source

ตั้ง Wi-Fi ผ่าน Captive Portal ได้ ไม่ต้อง Hardcode Credential เสมอไป

ถ้า C3 เชื่อม Wi-Fi ไม่ได้ หรือผู้ใช้ไม่ได้ใส่ Credential ไว้ใน Firmware ระบบจะเปิด Access Point สำหรับ Setup

SSID มีรูปแบบ: C3-AdBlock-XXXX

ผู้ใช้สามารถเชื่อมจากโทรศัพท์ เลือก Wi-Fi Network แล้วใส่ Password ผ่าน Captive Portal

เมื่อต้องการย้ายไป Network ใหม่ README ระบุว่าสามารถใช้ปุ่ม Forget WiFi ใน Dashboard หรือกด BOOT ขณะเปิดเครื่อง เพื่อเรียก Setup Portal กลับมา

Security Note: Setup Access Point เป็น Open AP ตามการออกแบบ เพื่อให้ผู้ใช้ Join ได้โดยยังไม่รู้ Password ดังนั้นควรทำ Setup ในสภาพแวดล้อมที่ควบคุมได้

Web Dashboard ที่ c3adblock.local ดูอะไรได้บ้าง?

Web Dashboard ของ ESP32-C3 AdBlock แสดง Blocklist และสถิติ Client
Web Dashboard แสดงข้อมูล Blocklist, Client, Wi-Fi และ Custom Domains โดย CNX Software ระบุว่าภาพต้นฉบับนี้ได้รับการปรับแต่งด้วย AI

Dashboard เข้าผ่าน: http://c3adblock.local

Feature ที่ Source ระบุ ได้แก่:

  • ดูจำนวน DNS Request ที่ Block / Allow
  • ดูสถิติแยกตาม Client
  • Ban Client
  • Add Custom Blocked Domain
  • Upload Blocklist
  • ตั้ง Remote Blocklist Update
  • Firmware OTA
  • Forget Wi-Fi
  • ดู System Information

Custom Blocked Domain ยังถูกเก็บแยกจาก Main Flash Blocklist และ Source Code ตรวจรายการ Custom ก่อน จึงสามารถเพิ่ม Domain เพิ่มเติมผ่าน Runtime ได้

Blocklist และ Firmware Update ผ่าน Wi-Fi ได้

หลัง Flash ครั้งแรก Project รองรับการ Update ผ่าน Network ทั้งฝั่ง Blocklist และ Firmware ภายใต้ Configuration ที่รองรับ OTA

Blocklist Update

ผู้ใช้สามารถ Upload `blocklist.bin` ผ่าน Dashboard หรือกำหนด URL สำหรับ Remote Auto-update

Official README ระบุว่า Default List ถูก Build ใหม่ทุกวันจันทร์ผ่าน GitHub Actions และเผยแพร่ผ่าน Stable Release URL สำหรับ Device ที่ต้องการดึง Update อัตโนมัติ

Firmware OTA

Dual-app Partition มี App Slots สองชุด เพื่อรองรับการ Update Firmware โดยไม่ต้องเสียบ USB ทุกครั้ง

แต่พื้นที่ที่ใช้กับ App Slot ชุดที่สอง ก็คือพื้นที่ที่หายไปจาก Blocklist จึงเกิด Trade-off ประมาณ 250k vs 537k Domains

Security: มี Auth แล้ว แต่ไม่ได้แปลว่าการเชื่อมต่อถูกเข้ารหัส

Official GitHub ปัจจุบันให้รายละเอียดเรื่อง Security มากกว่าการระบุว่า Dashboard มี Password เพียงอย่างเดียว

State-changing Endpoint ใช้ HTTP Basic Auth

Endpoint ที่สามารถเปลี่ยน State เช่นเพิ่ม Domain, Ban Client, Upload Blocklist หรือทำ Firmware OTA ต้องใช้ Username และ Password

Network OTA ยังมี OTA Password แยกอีกส่วนหนึ่ง

มีการลด Stored XSS

Custom Domain ถูก HTML Escape ก่อนแสดงบน Dashboard เพื่อป้องกัน Domain String ที่มี Markup ถูก Render เป็น Script หรือ HTML

มี CSRF Hardening เพิ่ม

Mutating Endpoint ต้องมี Custom Request Header ที่ Dashboard ของโปรเจกต์ส่งเอง เพื่อป้องกันหน้าเว็บภายนอก เรียก Action บางประเภทผ่าน Browser ได้ง่าย ๆ

แต่ Dashboard ยังใช้ HTTP

HTTP Basic Auth ไม่ใช่ Encryption: Dashboard ทำงานผ่าน HTTP Port 80 และ Basic Auth Credential เป็น Base64 ไม่ได้ถูก Encrypt ผู้พัฒนาระบุชัดว่ามาตรการนี้เป็น LAN Trust-boundary Control ไม่ใช่การป้องกัน Attacker ที่สามารถดัก Traffic บน Network ได้อยู่แล้ว

อีกเรื่องที่ Developer เตือนคือ ห้ามปล่อย Password ค่า Placeholder จากไฟล์ Example ไว้ใช้งานจริง เพราะค่าเหล่านั้นอยู่ใน Public Repository

หากนำไปทดลอง ควรทำบน Network ที่ผู้ใช้เป็นเจ้าของหรือได้รับอนุญาต และไม่ควรถือว่า Device นี้เป็น Security Appliance ที่มี TLS หรือ Enterprise-grade Authentication หาก Source ไม่ได้ระบุเช่นนั้น

มี STL เคสให้พิมพ์ 3D จริงใน Official Repository

Project มีไฟล์: hardware/esp32-c3-supermini-enclosure.stl สำหรับ ESP32-C3 SuperMini

รอบนี้สามารถพูดถึง Print Settings ได้ เพราะ README ระบุค่ามาโดยตรง

รายการ ค่าที่ Source ระบุ
Layer Height 0.2 mm
Infill ประมาณ 15%
Support ไม่จำเป็นตาม Notes ของผู้พัฒนา
Antenna ต้องเว้นบริเวณปลายเสา PCB Antenna และหลีกเลี่ยงพลาสติกหนาหรือโลหะใกล้เสา
Ventilation ผู้พัฒนาแนะนำไม่ให้ปิดช่องระบายอากาศ

README ยังระบุว่า Board ขณะ Idle อยู่ประมาณ 45–55 °C จึงไม่ควรออกแบบ Enclosure ที่ปิด Ventilation โดยไม่จำเป็น

หากมีไฟล์ STL แล้วแต่ไม่มีเครื่องพิมพ์ สามารถส่งไฟล์ให้ทีม GlobalByte ช่วยประเมินบริการพิมพ์ 3D ได้

สามารถเปิดไฟล์ต้นฉบับได้ที่ STL Enclosure บน Official GitHub

Code และ Build Flow จาก Official GitHub

Repository มี Source Code C++, PlatformIO Build Instructions และ Script สำหรับสร้าง Blocklist

ด้านล่างเป็นเพียง Excerpt สำหรับอธิบายแนวคิด ควรเปิด Repository ต้นฉบับควบคู่กันก่อน Build จริง

40-bit FNV-1a — excerpt จาก main.cpp
static uint64_t fnv40(const char* s, size_t n) {
  uint64_t h = 0xcbf29ce484222325ULL;
  for (size_t i = 0; i < n; i++) {
    h ^= (uint8_t)s[i];
    h *= 0x100000001b3ULL;
  }
  return h & HASH_MASK;
}

Function นี้คำนวณ FNV-1a แล้ว Mask ผลลัพธ์ให้เหลือขนาดตาม HASH_BYTES ซึ่ง Current Source กำหนดไว้ 5 Bytes

Basic Build Flow — Official README
cp src/secrets.example.h src/secrets.h

python3 tools/build_blocklist.py data/blocklist.bin

pio run -t upload
pio run -t uploadfs

pio device monitor

ก่อน Build จริงต้องแก้ค่า Credential ใน `src/secrets.h` โดยเฉพาะ Web Password และ OTA Password ไม่ควรปล่อยค่า Placeholder ตามไฟล์ Example

อย่าคัดลอก Command แล้ว Flash ทันทีโดยไม่อ่าน README: Version ของ PlatformIO, Partition Layout, Credential และ Blocklist Configuration มีผลกับการ Build และความปลอดภัยของระบบ

ข้อจำกัดที่ควรรู้ก่อนเอาไปใช้จริง

1. 537k Domains ไม่ได้มาพร้อม Firmware OTA

Maximum Blocklist Configuration ต้องใช้ Single-app Partition จึงไม่มีพื้นที่ App Slot ชุดที่สองสำหรับ Firmware OTA

2. Dashboard ไม่ได้ใช้ HTTPS

Basic Auth ป้องกันการเรียก Endpoint โดยไม่มี Credential ในกรณีทั่วไปบน LAN แต่ไม่ได้ Encrypt Traffic

3. Captive Portal เป็น Open AP ระหว่าง Setup

ผู้พัฒนาออกแบบให้ Join ได้ง่าย แต่หมายความว่าช่วง Provisioning ควรทำในพื้นที่ Network ที่ควบคุมได้

4. Source ไม่รับรอง Router ทุกยี่ห้อ

การเสียบ USB กับ Router ในตัวอย่าง เป็นการใช้เป็นแหล่งจ่ายไฟ ไม่ใช่หลักฐานว่า Router ทุก Model จะตั้ง DNS หรือรองรับ Workflow นี้อัตโนมัติ

5. DNS Client ต้องใช้ Resolver นี้

README ระบุให้ชี้ DNS ของ Device ไปยัง C3 หรือจัดให้ C3 อยู่ใน DNS Path ดังนั้นประสิทธิผลของระบบขึ้นกับ Network Configuration ที่ใช้จริงด้วย

6. Source ไม่ได้ระบุ Ad-block Percentage

ไม่มีข้อมูลจาก Source ที่ให้ตัวเลขว่า Block โฆษณาได้กี่เปอร์เซ็นต์ จึงไม่ควรเขียนว่าแทนระบบ Ad Blocking ทุกแบบได้ 100%

Maker เรียนรู้อะไรจากโปรเจกต์นี้ได้?

สิ่งที่น่าเรียนรู้ที่สุดอาจไม่ใช่เรื่อง Ad Blocking แต่คือวิธีคิดเรื่อง Memory

แทนที่จะถามว่า “ต้องเพิ่ม RAM เท่าไรถึงจะเก็บข้อมูลทั้งหมดได้?” Project นี้กลับถามว่า “จำเป็นต้องเก็บข้อมูลในรูปแบบเดิมหรือไม่?”

  • ลด String ให้เป็น Fixed-size Hash
  • ย้าย Dataset ขนาดใหญ่ไป Flash
  • เลือก Hash Width จาก Memory Budget และ Collision Risk
  • ใช้ Sorted Data เพื่อช่วยค้นหา
  • สร้าง First-level Index และ Cache เพิ่มใน Current Source
  • แบ่ง Partition ตาม Trade-off ระหว่าง Data Capacity กับ OTA
  • เพิ่ม Web Dashboard ให้ Embedded Device ดูแลตัวเองได้
  • คิดเรื่อง Security ของ Local Web Interface ตั้งแต่ต้น

แนวคิดเดียวกันยังประยุกต์ได้กับ Embedded Project ที่ต้องเก็บ Lookup Table หรือ Dataset จำนวนมาก โดย Hardware มี RAM จำกัด

ผู้พัฒนายังยกตัวอย่างเชิงแนวคิดว่า Chip ที่มี Flash มากขึ้นอย่าง ESP32-S3 สามารถใช้แนวทาง Hash-in-Flash แบบเดียวกัน เพื่อขยายจำนวน Entry ได้อีก

ถ้ากำลังทดลอง ESP32-C3, Networking หรือ Embedded DNS Project สามารถสอบถามทีม GlobalByte เรื่อง Development Board และ Maker Accessories ที่เหมาะกับ Requirement ได้

โปรเจกต์นี้มีทั้ง Network, Security และ Partition Trade-off แนะนำอ่านต้นฉบับควบคู่กัน

โดยเฉพาะก่อน Flash Firmware, เปลี่ยน Partition, ตั้ง Password หรือเปิด OTA ควรตรวจ README และ Source Code ล่าสุดโดยตรง

FAQ — คำถามเกี่ยวกับ ESP32-C3 DNS Ad Blocker

1. โปรเจกต์นี้ต้องใช้ PSRAM หรือไม่?

ไม่ต้องใช้ PSRAM จุดเด่นหลักของโปรเจกต์คือเก็บ Blocklist เป็น 40-bit Hash ใน Flash แทนการเก็บ Domain String ใน PSRAM

2. ใช้ ESP32-C3 รุ่นไหน?

Target หลักคือ ESP32-C3 และผู้พัฒนาระบุว่าทดสอบกับ ESP32-C3 SuperMini ที่มี Flash 4 MB

3. ESP32 รุ่นเก่าใช้ได้ไหม?

Official README ระบุว่ามี Build Target สำหรับ Classic ESP32 DevKit / WROOM จาก Community และผ่าน Compile Test แต่ C3 เป็น Target หลักที่ผู้พัฒนาทดสอบ

4. 40-bit Hash มีขนาดกี่ Bytes?

40 Bits เท่ากับ 5 Bytes ต่อ Hash Entry

5. Blocklist 140,000 Domains ใช้พื้นที่เท่าไร?

ผู้พัฒนารายงานประมาณ 0.67–0.7 MB ของ Flash

6. ใช้ RAM เท่าไร?

Official README รายงานประมาณ 50 KB สำหรับแนวทางที่อธิบายไว้

7. Lookup ใช้เวลานานไหม?

Developer รายงานประมาณ 10 ms โดยตัวเลขดังกล่าวรวม Wi-Fi Round-trip Time และไม่ควรตีความเป็น Benchmark คงที่ของทุก Network

8. รองรับ 537,000 Domains จริงไหม?

Source ระบุ Configuration สูงสุดประมาณ 537k Domains แต่ต้องใช้ Single-app Partition และแลกกับการไม่มี Firmware OTA

9. ถ้าอยากใช้ Firmware OTA รองรับกี่ Domains?

Official README ระบุประมาณ 250k Domains ใน Dual-app Partition บน Flash 4 MB

10. ถ้า Domain ถูก Block จะเกิดอะไรขึ้น?

Firmware ตอบ DNS ด้วย 0.0.0.0 ตาม DNS Sinkhole Logic ของโปรเจกต์

11. Dashboard เข้า URL อะไร?

Source ระบุ URL http://c3adblock.local สำหรับ Web Dashboard บน Network ที่ Resolve mDNS ได้

12. Dashboard ใช้ HTTPS หรือไม่?

ไม่ใช้ HTTPS ตาม Documentation ปัจจุบัน Web Interface ทำงานผ่าน HTTP Port 80

13. HTTP Basic Auth ปลอดภัยเท่ากับ HTTPS ไหม?

ไม่เท่ากัน Developer ระบุเองว่า Basic Auth เป็น LAN Trust-boundary Control และ Credential ไม่ได้ถูก Encrypt ระหว่างทาง

14. ตั้ง Wi-Fi โดยไม่แก้ Source Code ได้ไหม?

ได้ Firmware มี Captive Portal สำหรับ Provision Wi-Fi เมื่อไม่สามารถ Connect หรือไม่มี Credential ที่บันทึกไว้

15. Blocklist Update อัตโนมัติได้ไหม?

ได้ Source รองรับ Remote Blocklist URL และ Scheduled Update รวมถึง Default Blocklist ที่ Project สร้างใหม่ผ่าน GitHub Actions

16. มีไฟล์เคส 3D Print หรือไม่?

มี Official Repository มี STL สำหรับ ESP32-C3 SuperMini Enclosure

17. ใช้ Print Settings อะไร?

README ระบุ Layer Height 0.2 mm, Infill ประมาณ 15% และไม่ต้องใช้ Support พร้อมเตือนให้เว้นพื้นที่บริเวณ PCB Antenna

18. บล็อกโฆษณาได้ 100% หรือไม่?

Source ไม่ได้ระบุ Success Rate หรือรับรองว่า Block โฆษณาได้ทุกประเภท จึงไม่สามารถสรุปเป็น 100% ได้จากข้อมูลที่มี

สรุป: จุดเด่นไม่ใช่แค่บล็อก 500,000 Domains แต่คือการใช้ Memory ให้ฉลาดขึ้น

esp32-c3-adblock เป็นตัวอย่างที่ดีว่า Hardware ราคาประหยัดและ RAM จำกัด ไม่จำเป็นต้องแก้ด้วยการเพิ่ม Memory เสมอไป

การเปลี่ยน Domain String ให้กลายเป็น Fixed-size 40-bit Hash แล้วเก็บลง Flash ทำให้ ESP32-C3 ที่ไม่มี PSRAM สามารถทำงานกับ Blocklist หลักแสนรายการได้

แต่ทุกอย่างมี Trade-off: ต้องเลือกระหว่าง Firmware OTA กับ Blocklist ความจุสูงสุด, ต้องยอมรับความเสี่ยงของ Hash Collision ในระดับที่ Developer ประเมิน และต้องเข้าใจว่า Web Dashboard ใช้ HTTP ไม่ใช่ HTTPS

สำหรับ Maker นี่จึงไม่ใช่แค่โปรเจกต์ Ad Blocker แต่เป็น Case Study เรื่อง Data Structure, Flash Storage, Hashing, DNS, OTA, Partitioning, Embedded Web UI และ Security ที่รวมอยู่ใน ESP32-C3 ตัวเดียว

References / แหล่งข้อมูลต้นฉบับ

อยากลอง ESP32-C3, Networking หรือ Embedded Project?

ถ้ากำลังทดลอง ESP32-C3, Development Board, DNS, IoT หรือ Embedded Networking Project สามารถสอบถามทีม GlobalByte เรื่องบอร์ดและอุปกรณ์ที่เหมาะกับ Requirement ของงานได้

และถ้าต้องการทำ Enclosure Project นี้มีไฟล์ STL ต้นฉบับให้แล้ว สามารถส่งไฟล์ให้ทีม GlobalByte ช่วยประเมินบริการพิมพ์ 3D ได้เช่นกัน

Disclaimer: บทความนี้เป็นการสรุปและเรียบเรียงจากแหล่งข้อมูลภาษาอังกฤษ อาจมีความคลาดเคลื่อน กรุณาตรวจสอบ Source ต้นฉบับก่อนลงมือทำ

ตัวเลข Blocklist Capacity เช่นประมาณ 141k, 250k และ 537k Domains ขึ้นกับ Partition Layout และ Configuration ไม่ควรตีความว่า ESP32-C3 ทุกชุดสามารถใช้ Maximum Blocklist พร้อม Firmware OTA ได้พร้อมกัน

ค่า RAM Usage ประมาณ 50 KB, Lookup ประมาณ 10 ms, จำนวน Flash Reads และ Hash Collision เป็นข้อมูลที่ผู้พัฒนาเผยแพร่ใน Project Documentation ไม่ใช่ Benchmark ที่ GlobalByte ทดสอบซ้ำเอง

Current Source Code มี Index และ Cache Optimization เพิ่มจากคำอธิบาย Binary Search แบบพื้นฐาน จึงไม่ควรใช้ตัวเลข Flash Reads จาก Documentation เป็นค่าคงที่สำหรับทุก Query และทุก Version

Dashboard ใช้ HTTP Basic Auth แต่ไม่ใช่ HTTPS และ Credential ไม่ได้ถูก Encrypt ระหว่างทาง Captive Portal Access Point ในช่วง Setup ยังเป็น Open Network ตามการออกแบบของ Project

ควรทดลองบน Network และ Hardware ที่ผู้ใช้เป็นเจ้าของหรือได้รับอนุญาตเท่านั้น พร้อมตั้ง Web Password และ OTA Password จริง แทนค่า Placeholder ก่อนนำ Device ไปใช้งานบน Network ที่มีอุปกรณ์อื่นร่วมอยู่

 

แท็ก


Blog posts