MAC Protection
Per-device rate limiting for MAG/STB endpoints using MAC addresses
MAC protection adds a device-level firewall layer on top of the
existing IP-based rate limiting. It's designed for endpoints like /c
that are called by MAG set-top boxes and similar IPTV devices which
send their hardware MAC address as a query parameter.
Regular IP rate limiting can't tell the difference between one device making 5 requests and 50 bots sharing a proxy. MAC protection can — it tracks each device independently and catches bots that cycle through stolen MAC addresses.
How it works
When a request hits a protected path (e.g. /c), the firewall:
- Extracts the MAC from
?mac=,?sn=, or theX-Device-MACheader - Validates the format — must be a valid
XX:XX:XX:XX:XX:XXpattern (colon or dash separated) - Checks the per-MAC rate limit — each MAC address has its own token bucket
- Tracks unique MACs per IP — if one IP sends too many different MACs in a time window, it's auto-banned (this catches bot farms cycling through MAC lists)
Whitelisted IPs bypass MAC protection entirely, same as all other firewall checks.
Configuration
Sidebar → Firewall → MAC Protection card:
| Field | Default | Notes |
|---|---|---|
| Enabled | off | Master toggle |
| Paths | ["/c"] | URL prefixes to protect. Use exact prefixes — /c matches /c and /c/... but not /config |
| Requests/sec | 3 | Sustained per-MAC rate limit |
| Burst | 20 | Allows short spikes (e.g. portal boot) |
| Require MAC | off | Block requests that have no ?mac= parameter at all |
| Max MACs per IP | 25 | Unique MACs from one IP before auto-ban |
| Window (seconds) | 600 | Time window for counting unique MACs |
| Ban duration (minutes) | 15 | How long to ban IPs that exceed MAC thresholds |
Recommended settings
These defaults balance protection against bots while being safe for real users in various network setups:
{
"enabled": true,
"paths": ["/c"],
"requests_per_second": 3,
"burst": 20,
"max_macs_per_ip": 25,
"mac_window_seconds": 600,
"ban_duration_minutes": 15,
"require_mac": false
}Why these numbers?
3 req/s + burst 20 — A person switching channels on a MAG box makes 1-2 requests per second at most. But when the portal boots (power-on, app restart), the device fires 8-15 requests in a quick burst to load channels, EPG, categories, and logos. A burst of 20 gives comfortable headroom so a slow portal or retry never gets flagged. 3 req/s sustained means even fast channel surfing is fine — a bot doing 50+ req/s gets caught immediately.
25 max MACs per IP — A household has 1-3 MAG boxes. But hotels, businesses, and carrier-grade NAT (CGNAT) can put 20+ real devices behind one public IP. Setting 25 accommodates these scenarios. A bot cycling through a stolen MAC list will blow past 25 in seconds and get banned.
600s (10 min) window — Long enough to catch slow-drip bots that pace their MAC cycling to avoid detection. Real users behind CGNAT won't hit 25 unique MACs in 10 minutes — even a 50-room hotel doesn't have 25 MAGs booting simultaneously under normal conditions.
15 min ban — Short enough that a false positive self-heals quickly. A banned bot still has to wait 15 minutes, then gets banned again on the next burst — effective deterrence with minimal risk to real users.
require_mac off — Some legitimate third-party players (TiviMate,
IPTV Smarters, VLC) don't send a ?mac= parameter. Keep this off
unless you're certain all your users are on MAG hardware.
When to use "Require MAC"
Turn this on only if:
- All your users are on MAG/Infomir hardware (which always sends
?mac=) - You're seeing bots that hit
/cwithout any MAC parameter - You don't support third-party players like TiviMate or Smarters
When enabled, any request to a protected path without a ?mac=
query parameter gets a 403 Forbidden immediately.
Tuning
False positives (real users getting blocked)
- Raise
burst— if users complain about blocks during app startup, their device may send more boot requests than expected - Raise
max_macs_per_ip— if you serve hotels or large NAT networks, increase to 50+ - Lower
ban_duration_minutes— reduce the impact per false positive (e.g. 5 minutes instead of 15) - Add the IP to the whitelist — for known business customers with many devices behind one IP
False negatives (bots getting through)
- Lower
requests_per_second— drop to 2 or even 1 if you see bots making sustained low-rate requests per MAC - Lower
max_macs_per_ip— if bots are staying under 25 MACs, tighten to 10-15 (be careful with CGNAT users) - Turn on
require_mac— forces all requests to include a MAC, blocking simple scrapers - Shorten
mac_window_seconds— a 60s window catches faster bursts but forgives legitimate slow accumulation
Interaction with other firewall rules
The order of checks per request:
- Image redirect → bypass
- Whitelist hit → bypass everything below
- Banned IP →
403 - VPN/proxy check →
403if enabled and flagged - IP rate limit →
429if over limit - MAC protection →
403if MAC invalid, rate exceeded, or too many MACs per IP - Country block →
403if blocked - Forward to backend
MAC protection runs after the general IP rate limit. This means a bot hammering from one IP gets caught by IP rate limiting first (cheaper check). MAC protection then catches the smarter bots that distribute across IPs but reuse or cycle MACs.
Logging
Every MAC request is logged for audit. Look for these patterns in Sidebar → Logs:
| Log prefix | Meaning |
|---|---|
MAC_REQUEST | Valid MAC request processed (ip, mac, path, country) |
MAC_BLOCK | Blocked — missing or invalid MAC format |
MAC_RATELIMIT | Blocked — per-MAC rate limit exceeded |
MAC_AUTOBAN | IP auto-banned — too many unique MACs in window |
Example log lines:
MAC_REQUEST ip=185.22.174.8 mac=00:1A:79:AA:BB:CC path=/c country=DE
MAC_RATELIMIT ip=45.134.26.9 mac=00:1A:79:11:22:33 path=/c country=US reason=MAC rate limit exceeded (mac=00:1A:79:11:22:33, limit=3/s)
MAC_AUTOBAN ip=91.108.4.55 mac=AA:BB:CC:DD:EE:FF path=/c country=RU reason=too many unique MACs from IP (>25 in window) ban_minutes=15Monitoring
MAC protection stats are available at:
- Dashboard — the firewall stats overview shows
MAC blockedcount alongside VPN blocked - API —
GET /internal/firewall/mac-statsreturns active MAC buckets, tracked IPs, and total blocked count
Persistence
Like auto-ban, MAC tracking is in-memory. A proxy restart clears all MAC buckets and IP-MAC trackers. Bans triggered by MAC protection are also in-memory and clear on restart.