Rate Limiting¶
WireBuddy implements progressive rate limiting to prevent abuse and brute-force attacks.
Overview¶
Rate limiting protects against:
- 🔒 Brute-force password attacks
- 🚫 API abuse
- 💥 Denial of Service (DoS)
- 🤖 Automated scraping
Rate Limit Tiers¶
| Endpoint | Authenticated | Unauthenticated |
|---|---|---|
| Login | 5/15min | 5/15min |
| MFA Verify | 5/5min | 5/5min |
| Password Reset | 3/hour | 3/hour |
| API GET | 100/min | 10/min |
| API POST/PUT/DELETE | 30/min | 5/min |
| Status Page | 60/min | 60/min |
Progressive Lockout¶
Failed attempts trigger exponential backoff:
| Violation | Lockout Duration |
|---|---|
| 1st | 1 minute |
| 2nd | 5 minutes |
| 3rd | 15 minutes |
| 4th+ | 1 hour |
Lockout duration resets after 24 hours of no violations.
Rate Limit Headers¶
API responses include rate limit information:
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1679143200
Retry-After: 60
- X-RateLimit-Limit: Maximum requests in window
- X-RateLimit-Remaining: Requests remaining
- X-RateLimit-Reset: Timestamp when limit resets (Unix epoch)
- Retry-After: Seconds until retry (when rate limited)
Rate Limit Responses¶
429 Too Many Requests¶
When rate limit is exceeded:
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Try again in 60 seconds",
"retry_after": 60,
"limit": 100,
"window": 60
}
Configuration¶
Global Settings¶
Settings → Security → Rate Limiting
- Enable Rate Limiting: Master toggle
- Strict Mode: More aggressive limits
Per-Endpoint Limits¶
Settings → Security → Rate Limiting → Endpoints
Customize limits per endpoint:
{
"login": {
"attempts": 5,
"window": 900,
"lockout": 60
},
"api_read": {
"authenticated": 100,
"unauthenticated": 10,
"window": 60
}
}
IP Whitelist¶
Exempt trusted IPs from rate limiting:
Settings → Security → Rate Limiting → Whitelist
Warning
Use sparingly. Whitelisted IPs can abuse the system.
Implementation Details¶
Storage Backend¶
WireBuddy uses in-memory storage for rate limits:
- Fast: No database queries
- Scalable: Handles high request volume
- Automatic cleanup: Expired entries removed
Key Generation¶
Rate limits are tracked per:
# IP-based (unauthenticated)
key = f"ratelimit:{endpoint}:{client_ip}"
# User-based (authenticated)
key = f"ratelimit:{endpoint}:user:{user_id}"
Sliding Window¶
WireBuddy uses sliding window algorithm:
def check_rate_limit(key: str, limit: int, window: int) -> bool:
now = time.time()
window_start = now - window
# Get requests in window
requests = [ts for ts in get_requests(key) if ts > window_start]
# Check limit
if len(requests) >= limit:
return False # Rate limited
# Record request
add_request(key, now)
return True # Allowed
Monitoring¶
View Rate Limits¶
Dashboard → Security → Rate Limits
- Current limits for each endpoint
- Active lockouts
- Top offending IPs
Audit Logs¶
Rate limit violations are logged:
{
"timestamp": "2026-03-15T14:30:00Z",
"event": "rate_limit_exceeded",
"endpoint": "/api/peers",
"ip": "203.0.113.42",
"user": "admin",
"limit": 100,
"window": 60,
"lockout_duration": 60
}
Alerts¶
(Future feature)
Configure alerts for:
- Multiple rate limit violations from same IP
- Distributed attack patterns
- Unusual traffic spikes
Bypassing Rate Limits¶
For Legitimate Use¶
If you're getting rate limited legitimately:
- Increase limits: Settings → Security → Rate Limiting
- Use authentication: Authenticated requests have higher limits
- Whitelist IP: Add your IP to whitelist
- Implement backoff: Exponential backoff in scripts
For Automation¶
Best practices for scripts/automation:
import time
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
# Retry strategy
retry_strategy = Retry(
total=3,
status_forcelist=[429, 500, 502, 503, 504],
backoff_factor=2, # 1s, 2s, 4s
respect_retry_after_header=True
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session = requests.Session()
session.mount("https://", adapter)
# Use session for requests
response = session.get(
"https://vpn.example.com/api/peers",
headers={"Authorization": f"Bearer {TOKEN}"}
)
# Check rate limit headers
remaining = int(response.headers.get('X-RateLimit-Remaining', 0))
if remaining < 10:
reset = int(response.headers.get('X-RateLimit-Reset', 0))
wait_time = max(0, reset - time.time())
print(f"Approaching limit, waiting {wait_time}s")
time.sleep(wait_time)
Integration with fail2ban¶
Automatically ban IPs with repeated violations:
# /etc/fail2ban/filter.d/wirebuddy.conf
[Definition]
failregex = ^.*rate_limit_exceeded.*ip=<HOST>$
ignoreregex =
# /etc/fail2ban/jail.d/wirebuddy.conf
[wirebuddy-ratelimit]
enabled = true
port = http,https
filter = wirebuddy
logpath = /var/log/wirebuddy/audit.log
maxretry = 10
findtime = 600
bantime = 3600
Security Considerations¶
Distributed Attacks¶
Rate limiting by IP may not stop:
- Distributed attacks: Multiple IPs
- Botnets: Large IP pools
Additional protection:
- Cloudflare or similar WAF
- CrowdSec for collaborative defense
- CAPTCHA for suspicious patterns (future feature)
IP Spoofing¶
Behind reverse proxy, ensure:
- Only trusted proxies can set
X-Forwarded-For - Use Trusted Proxies configuration
- Validate
X-Forwarded-Forformat
Troubleshooting¶
Legitimate Users Getting Blocked¶
Problem: Users reporting "rate limit exceeded"
Solutions:
- Review rate limit configuration (too strict?)
- Check for misconfigured scripts/automation
- Temporarily increase limits
- Whitelist specific IPs if justified
Rate Limits Not Working¶
Problem: Attackers bypassing rate limits
Causes:
- Rate limiting disabled
- IP extracted incorrectly (proxy misconfiguration)
- Attacker using multiple IPs
Solutions:
- Verify rate limiting is enabled
- Check Trusted Proxies configuration
- Implement additional layers (WAF, CrowdSec)
False Positives¶
Problem: Internal services getting rate limited
Solutions:
- Whitelist internal IP ranges
- Use API tokens (higher limits)
- Implement proper retry logic with backoff
Best Practices¶
For Admins¶
- ✅ Keep rate limiting enabled
- ✅ Monitor audit logs for violations
- ✅ Whitelist only when necessary
- ✅ Set reasonable limits (not too strict)
- ✅ Configure reverse proxy correctly
- ✅ Use fail2ban for repeat offenders
For Developers¶
- ✅ Implement exponential backoff
- ✅ Respect
Retry-Afterheader - ✅ Cache responses when possible
- ✅ Use authenticated requests
- ✅ Monitor
X-RateLimit-Remaining - ❌ Don't retry immediately on 429
Next Steps¶
- Authentication - Login security
- Security Overview - Complete security docs
- Best Practices - Security hardening
- API Authentication - API tokens