
Table of Contents
Request Throttling
TetherX uses multiple layers of protection to prevent abuse, brute-force attacks, and malicious requests. This article documents all rate limiting and blocking mechanisms.
Security Layers
Protection is applied at four levels:
- Nginx - Infrastructure-level blocking for known attack patterns
- Rack::Attack - Application-level rate limiting and attack detection
- Rails Controllers - Endpoint-specific rate limits for sensitive actions
- Per-account lockout - Failed sign-ins counted against the account itself, see Account Lockout
Rate Limits
General Web Requests
| Endpoint | Limit | Period | Response |
|---|---|---|---|
| Web pages | 100,000 requests | 5 minutes | HTTP 429 |
| Live view | 150,000 requests | 5 minutes | HTTP 429 |
| Login attempts | 30 requests | 5 minutes | HTTP 429 |
| Two-factor code attempts | 20 requests | 5 minutes | HTTP 429 |
| Password resets | 5 requests | 5 minutes | HTTP 429 |
All of these are counted per IP address. The general web and live view limits are deliberately high because TetherBoxes and multi-camera live views generate large volumes of legitimate requests.
Excluded from general limit: Assets, live view, WebSocket connections, and API endpoints have separate handling.
Tip: The login limit is per IP, so it is intentionally looser than the per-account lockout. A control room shares one WAN address, and a tight per-IP login limit would lock out every operator in the room because of one person's typing. The per-account lockout is the real brute-force gate.
Per-Account Lockout
Counted against the account rather than the address, so a distributed attack using one attempt per IP is still stopped:
| Trigger | Attempts | Window | Lock |
|---|---|---|---|
| Wrong password | 10 | Rolling 15 minutes | 15 minutes |
| Wrong two-factor code | 5 | Rolling 15 minutes | 15 minutes |
| Locked again with no successful sign-in in between | - | - | 1 hour |
A pending sign-in (password accepted, code not yet entered) expires after 5 minutes. Two-factor codes cannot be replayed: once a code is accepted it is refused for the rest of its window.
Locks always expire on their own and a password reset clears them immediately. Full behaviour is in Account Lockout.
API Rate Limits
| API Version | Limit | Period | Response |
|---|---|---|---|
| Public API (v3p) | 100 requests | 1 minute | HTTP 429 |
| Webhooks | 60 requests | 1 minute | HTTP 429 |
Tip: The private API (v3) is designed for TetherBoxes and authenticated users. TetherBox communication uses a pre-authenticated MQTT connection with message queuing, allowing requests to backlog gracefully during high load rather than being rejected.
Attack Blocking
Immediate Blocks (HTTP 444)
These patterns are blocked immediately with a connection close:
- SQL Injection in Host Header - Keywords like
union,select,drop,exec,sleep( - Invalid Host Characters - Characters outside
a-z,0-9,.,-,: - Path Traversal - Patterns like
..,/etc/passwd,/proc/self - CMS Admin Paths - Requests to
wp-admin,phpmyadmin,admin.php - Malicious Script Extensions - Files ending in
.php,.asp,.jsp,.cgi
Fail2Ban-Style Backoff
Repeated suspicious requests trigger a ban:
- Trigger: 3 suspicious requests within 10 minutes
- Ban Duration: 10 minutes per IP address
- Tracked Patterns: Scanner user agents, path traversal, SQL injection, invalid host characters, invalid content types
Per-User Access Restrictions
Administrators can lock a user's access to specific IP addresses. When enabled, the user can only access TetherX from the listed IPs - all other addresses are blocked.
- Location: Users → Edit User → Permissions → CCTV → Restrict Access from Specific IP(s)
- Format: Comma-separated list of IP addresses
- Effect: User is blocked from ALL access unless connecting from a listed IP
- Response when blocked: HTTP 403 Forbidden
Warning: This is a security restriction, not a whitelist. Enabling this feature locks the user out of all IP addresses except those explicitly listed. Users cannot modify their own IP restrictions.
Infrastructure Blocking
Bot Blocking
Known bots are blocked at the nginx level to reduce noise:
- YandexBot, Googlebot, Bingbot
- DuckDuckBot, BaiduSpider
- AhrefsBot, SemrushBot
SSH Protection
Server SSH access is protected by fail2ban:
- Trigger: 10 failed attempts within 10 minutes
- Ban Duration: 10 minutes per IP address
Error Responses
HTTP 429 - Rate Limit Exceeded
When throttled, you receive a JSON response with retry information:
{
"error": "Rate limit exceeded",
"ip": "203.0.113.1",
"throttle": "req/ip",
"count": 3001,
"limit": 3000,
"retry_after": 300
}
The Retry-After header indicates seconds until the limit resets.
HTTP 444 - Connection Closed
Attack patterns receive an immediate connection close with no response body. This minimises information disclosure to attackers.
HTTP 403 - IP Restricted
Users with IP restrictions accessing from unauthorised addresses receive:
"IP restricted"
Common Questions
Why am I getting 429 errors?
Your IP has exceeded the rate limit. Wait for the period specified in retry_after before retrying. If you need higher limits for legitimate use cases, contact support.
Why does the sign-in page say too many attempts when I have only tried once?
That message comes from the per-account lockout, not from the rate limit, and it counts attempts on the account rather than from your address. Somebody else has been trying passwords on it. See Account Lockout.
Can I get higher API limits?
The public API has fixed limits. If you have a legitimate use case requiring higher limits, contact support to discuss your requirements.
Referenced in: