The ESP32 AdBlock device provides an onboard HTTP REST API served on port 80. The API enables automation, integration with Home Assistant or Grafana, and remote administration.
All mutating endpoints (/ban, /addblock, /unblock, /fetchnow, /setupdate, /upload, /setname, /delclient) require administrative authentication.
- HTTP Header (Recommended):
X-Admin-Token: your_admin_password - Query Parameter (Fallback):
POST /endpoint?t=your_admin_password&...
- Default Token Lockout: If
ADMIN_TOKENis set to"changeme"in firmware, all mutating endpoints return401 Unauthorizeduntil changed. - CSRF Host Protection: The server strictly verifies
OriginandRefererheaders against the device IP andesp32adblock.local. Cross-origin browser requests from external websites are blocked. - Constant-Time Verification: Token comparison runs in a fixed 64-iteration loop (
constantTimeCompare) to resist timing side-channel attacks. - Progressive Brute-Force Lockout: Tracks failed administrative authentication attempts per client IP. After 5 consecutive invalid tokens, the client IP is quarantined for 30 seconds, returning
429 Too Many Requestsacross all API endpoints.
Retrieves real-time throughput metrics, system telemetry, connected client states, and custom blocked domains.
- URL:
/stats.json - Method:
GET - Auth Required: Optional. When unauthenticated, client MAC addresses are masked as
--:--:--:--:--:--for LAN privacy.
curl -s -H "X-Admin-Token: your_token" http://<device-ip>/stats.json{
"ip": "192.168.1.50",
"blocked": 129,
"allowed": 662,
"domains": 215430,
"rssi": -36,
"temp": -999.0,
"heap": 105664,
"min_heap": 82612,
"largest_heap_block": 90112,
"rst_reason": 1,
"cpu_mhz": 240,
"cores": 2,
"core0": "DNS Engine (UDP :53)",
"core1": "Web Server & Maintenance",
"lan_count": 1,
"wifi_count": 2,
"uptime": "0d 0h 20m",
"upurl": "https://raw.githubusercontent.com/user/repo/main/blocklist.bin",
"upiv": 24,
"upstat": "never",
"rebind": 3,
"ratelimited": 977,
"clients": [
{
"ip": "192.168.1.100",
"mac": "aa:bb:cc:dd:ee:01",
"name": "Desktop Workstation",
"conn": "LAN",
"blocked": 128,
"allowed": 630,
"banned": false,
"lastSeenSec": 2
},
{
"ip": "192.168.1.105",
"mac": "aa:bb:cc:dd:ee:02",
"name": "Living Room TV",
"conn": "WIFI",
"blocked": 1,
"allowed": 32,
"banned": false,
"lastSeenSec": 15
}
],
"custom": [
"fake-store-checkout.shop"
]
}Retrieves the onboard circular buffer (up to 64 entries) of recent blocked DNS queries with timestamps, client IP, friendly device name, and query details.
- URL:
/log.json - Method:
GET - Auth Required: Optional (client MAC masked as
--:--:--:--:--:--if unauthenticated)
[
{
"time": 1726932450,
"ip": "192.168.1.105",
"name": "Living Room TV",
"mac": "aa:bb:cc:dd:ee:02",
"domain": "graph.facebook.com",
"type": "A",
"action": "0.0.0.0",
"rebind": false
},
{
"time": 1726932445,
"ip": "192.168.1.100",
"name": "Desktop Workstation",
"mac": "aa:bb:cc:dd:ee:01",
"domain": "192.168.1.1.nip.io",
"type": "A",
"action": "REBIND_DEFENSE",
"rebind": true
},
{
"time": 1726932442,
"ip": "192.168.1.100",
"name": "Desktop Workstation",
"mac": "aa:bb:cc:dd:ee:01",
"domain": "doubleclick.net",
"type": "AAAA",
"action": "NODATA",
"rebind": false
}
]Assigns or clears a custom friendly name and physical interface classification for a client IP address. Persisted atomically to /lfs/names.txt across reboots.
- URL:
/setname?ip=<client_ip>&name=<friendly_name>&conn=<interface> - Method:
POST - Auth Required: Yes
| Name | Type | Description |
|---|---|---|
ip |
String | Client IPv4 address (e.g. 192.168.1.100) |
name |
String | URL-encoded device alias (max 31 chars). Leave empty to clear alias. |
conn |
String | Connection interface: LAN (Wired Ethernet) or WIFI (Wireless). |
curl -X POST -H "X-Admin-Token: your_token" "http://<device-ip>/setname?ip=192.168.1.100&name=Desktop%20Workstation&conn=LAN"ok (HTTP 200)
Manually purges a device from the client tracking table and clears any stored alias from /lfs/names.txt.
- URL:
/delclient?ip=<client_ip> - Method:
POST - Auth Required: Yes
curl -X POST -H "X-Admin-Token: your_token" "http://<device-ip>/delclient?ip=192.168.1.199"ok (HTTP 200)
Adds a domain to the custom blacklist. Stored persistently in /lfs/custom.txt.
- URL:
/addblock?d=<domain> - Method:
POST - Auth Required: Yes
curl -X POST -H "X-Admin-Token: your_token" "http://<device-ip>/addblock?d=ads.example.com"ok (HTTP 200)
Removes a previously added custom domain from the blacklist.
- URL:
/unblock?d=<domain> - Method:
POST - Auth Required: Yes
curl -X POST -H "X-Admin-Token: your_token" "http://<device-ip>/unblock?d=ads.example.com"ok (HTTP 200)
Toggles DNS resolution ban for a specific client IP address. Banned clients receive 0.0.0.0 for all DNS queries.
- URL:
/ban?ip=<client_ip> - Method:
POST - Auth Required: Yes
curl -X POST -H "X-Admin-Token: your_token" "http://<device-ip>/ban?ip=192.168.1.105"ok (HTTP 200)
Uploads a pre-compiled, sorted 40-bit binary blocklist to flash memory.
- URL:
/upload - Method:
POST - Headers:
Content-Type: application/octet-stream - Auth Required: Yes
- Size must be
$>0$ and$\le 1.20\text{ MB}$ ($1,228,800$ bytes). - Size must be an exact multiple of 5 bytes (
size % 5 == 0). - Hashes must be strictly pre-sorted in ascending order.
curl -X POST -H "X-Admin-Token: your_token" \
--data-binary @blocklist.bin \
http://<device-ip>/uploadok (HTTP 200)
Configures remote blocklist auto-update parameters with exponential backoff on fetch failures.
- URL:
/setupdate?u=<https_url>&h=<hours> - Method:
POST - Auth Required: Yes
| Name | Type | Constraints | Description |
|---|---|---|---|
u |
String | Must start with https:// |
Remote binary blocklist URL |
h |
Integer | Range: 1 to 720 |
Check interval in hours |
curl -X POST -H "X-Admin-Token: your_token" \
"http://<device-ip>/setupdate?u=https://example.com/blocklist.bin&h=48"ok (HTTP 200)
Asynchronously triggers an immediate background blocklist download using the configured update URL.
- URL:
/fetchnow - Method:
POST - Auth Required: Yes
curl -X POST -H "X-Admin-Token: your_token" http://<device-ip>/fetchnowfetch scheduled (HTTP 202 Accepted)