

The recent dismantling of a 17-million-device botnet serves as a stark reminder: modern infrastructure is under constant siege from distributed, high-velocity attacks. As architects, our goal isn't just to build features, but to build defensive intelligence.
To defend against such scale, developers must move beyond simple rate limiting and implement Anomaly Detection Systems (ADS). This guide provides a production-ready implementation of a monitoring layer designed to detect the "heartbeat" of a botnet attack before it saturates your infrastructure.
Before implementing defensive monitoring, ensure you have the following:
# Create a virtual environment
python -m venv venv
source venv/bin/activate # Linux/macOS
# venv\Scripts\activate # Windows
# Install core dependencies
pip install fastapi uvicorn redis pydantic python-dotenv requests
# Initialize project
npm init -y
# Install dependencies
npm install express redis dotenv ioredis cors dotenv
# Install dev dependencies for TypeScript
npm install --save-dev typescript @types/node @types/express ts-node
We will implement a Sliding Window Rate Limiter and Anomaly Detector. This pattern is critical for identifying the sudden, synchronized spikes characteristic of a 17M-device botnet.
This implementation uses an asynchronous sliding window to track request velocity per IP.
import time
import os
from typing import Dict
from fastapi import FastAPI, Request, HTTPException, status
from redis import asyncio as aioredis
from dotenv import load_dotenv
load_dotenv()
app = FastAPI(title="ICARAX Defensive Shield")
# Configuration
REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379")
THRESHOLD_REQUESTS = 100 # Max requests allowed in window
WINDOW_SECONDS = 60 # Time window in seconds
class AnomalyDetector:
def __init__(self):
self.redis = None
async def connect(self):
self.redis = await aioredis.from_url(REDIS_URL, decode_responses=True)
async def is_anomaly(self, client_ip: str) -> bool:
"""
Uses a Redis Sorted Set to implement a sliding window rate limiter.
This is highly efficient for high-concurrency botnet detection.
"""
now = time.time()
key = f"ratelimit:{client_ip}"
async with self.redis.pipeline(transaction=True) as pipe:
# 1. Remove timestamps older than our window
pipe.zremrangebyscore(key, 0, now - WINDOW_SECONDS)
# 2. Add current request timestamp
pipe.zadd(key, {str(now): now})
# 3. Count requests in current window
pipe.zcard(key)
# 4. Set expiry on the key to clean up idle IPs
pipe.expire(key, WINDOW_SECONDS)
results = await pipe.execute()
request_count = results[2]
return request_count > THRESHOLD_REQUESTS
detector = AnomalyDetector()
@app.on_event("startup")
async def startup():
await detector.connect()
@app.middleware("http")
async def security_middleware(request: Request, call_next):
client_ip = request.client.host
# Detect botnet-like behavior
if await detector.is_anomaly(client_ip):
# In production, log this to a SIEM (Security Information and Event Management)
print(f"CRITICAL: Anomaly detected from IP: {client_ip}")
raise HTTPException(
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
detail="Security policy violation: Unusual activity detected."
)
return await call_next(request)
@app.get("/")
async def root():
return {"status": "secure", "message": "Traffic is within normal parameters."}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
This version is optimized for high-throughput Node.js environments.
import express, { Request, Response, NextFunction } from 'express';
import Redis from 'ioredis';
import dotenv from 'dotenv';
dotenv.config();
const app = express();
const redis = new Redis(process.env.REDIS_URL || 'redis://localhost:6379');
const THRESHOLD = 100;
const WINDOW_MS = 60 * 1000; // 60 seconds
interface SecurityContext {
isAnomaly: boolean;
}
/**
* Middleware to detect rapid-fire request patterns characteristic of botnets
*/
const anomalyDetectionMiddleware = async (req: Request, res: Response, next: NextFunction) => {
const clientIp = req.ip || req.socket.remoteAddress || 'unknown';
const now = Date.now();
const key = `ratelimit:${clientIp}`;
try {
// Multi/Exec transaction for atomic operations
const multi = redis.multi();
// Remove expired entries
multi.zremrangebyscore(key, 0, now - WINDOW_MS);
// Add current request
multi.zadd(key, now, now.toString());
// Get current count
multi.zcard(key);
// Set TTL to prevent memory leaks
multi.expire(key, 60);
const results = await multi.exec();
// Result index 2 contains the ZCARD result
const requestCount = results?.[2] as number;
if (requestCount > THRESHOLD) {
console.error(`[SECURITY ALERT] Botnet signature detected from IP: ${clientIp}`);
return res.status(429).json({
error: "Too Many Requests",
message: "Automated activity detected. Please try again later."
});
}
next();
} catch (error) {
console.error("Security Middleware Error:", error);
// Fail open or closed based on your risk appetite.
// Here we fail open to ensure availability.
next();
}
};
app.use(anomalyDetectionMiddleware);
app.get('/api/data', (req: Request, res: Response) => {
res.json({ data: "Sensitive information accessed securely." });
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`🛡️ Defensive API running on port ${PORT}`);
});
Create a .env file in your root directory. Never commit this file to version control.
# Redis connection string
REDIS_URL=redis://default:yourpassword@your-redis-endpoint:6379
# Security Thresholds
MAX_REQUESTS_PER_MINUTE=100
# Environment
NODE_ENV=production
PYTHON_ENV=production
# Third-party Threat Intel (Optional)
ABUSE_IP_DB_API_KEY=your_api_key_here
Don't just rely on IP. Botnets use IP rotation. Combine IP with:
User-Agent string analysis./login without ever requesting / first).| Error | Likely Cause | Solution |
|---|---|---|
Redis Connection Refused | Redis service is down or wrong port. | Check REDIS_URL and ensure Redis is running via docker ps or system service. |
429 Too Many Requests (False Positive) | Threshold is too low for legitimate power users. | Increase THRESHOLD_REQUESTS or implement "Allow-lists" for known good IPs. |
Memory Leak in Redis | Keys aren't expiring. | Ensure expire command is called in your Redis pipeline/transaction. |
Latency Spikes | Middleware is blocking the event loop. | Ensure you are using async/await (Python) or non-blocking drivers (ioredis). |
Before deploying your defensive layer to a live environment:
X-RateLimit-Limit and X-RateLimit-Remaining headers to help legitimate clients?Locust or k6) to see if the security middleware becomes the bottleneck?Source: Ars Technica AI
Follow ICARAX for more AI insights and tutorials.
