DDoS Protection for ChatGPT Apps: Production Security Guide
Distributed Denial of Service (DDoS) attacks represent one of the most serious threats to ChatGPT applications. As your app gains traction with OpenAI's 800 million weekly users, it becomes an increasingly attractive target for attackers seeking to overwhelm your infrastructure, exhaust API quotas, or cause service disruption. A successful DDoS attack can result in complete service outages, degraded user experience, excessive cloud costs from auto-scaling, and potential violation of OpenAI's rate limit policies leading to app suspension.
DDoS attacks against ChatGPT apps come in three primary forms: volumetric attacks that flood your network with massive traffic volumes, application-layer attacks that target your MCP server endpoints with seemingly legitimate requests, and API exhaustion attacks that deliberately consume your OpenAI API quotas. Traditional web applications face bandwidth saturation, but ChatGPT apps have the additional vulnerability of expensive API calls—each malicious request can cost real money in OpenAI usage fees.
Effective DDoS protection requires a defense-in-depth strategy with multiple coordinated layers: perimeter protection through CDN and Web Application Firewall (WAF), intelligent rate limiting at network and application tiers, infrastructure resilience through auto-scaling and circuit breakers, real-time traffic analysis for anomaly detection, and comprehensive incident response procedures. This guide provides production-ready implementations for each defensive layer, with battle-tested code examples you can deploy immediately to protect your ChatGPT application from DDoS threats.
CDN & WAF Integration: Perimeter Defense
Your first line of defense is a Content Delivery Network (CDN) with integrated Web Application Firewall (WAF) capabilities. Cloudflare, AWS CloudFront with AWS WAF, and Google Cloud Armor provide enterprise-grade DDoS protection that operates at the network edge, absorbing attacks before they reach your infrastructure.
Cloudflare Workers enable custom DDoS filtering logic that runs at the edge, inspecting every request before it touches your origin server. This Cloudflare Worker implements multi-factor DDoS detection with IP reputation scoring, request pattern analysis, and adaptive challenge issuance:
// cloudflare-workers/ddos-filter.ts
// Production Cloudflare Worker for DDoS protection
// Deploy: wrangler publish
interface RateLimitEntry {
count: number;
timestamp: number;
score: number;
}
interface IPReputation {
score: number;
violations: number;
lastViolation: number;
blocked: boolean;
}
export default {
async fetch(request: Request, env: any, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
const clientIP = request.headers.get('CF-Connecting-IP') || 'unknown';
const userAgent = request.headers.get('User-Agent') || '';
const country = request.headers.get('CF-IPCountry') || 'XX';
// Check if IP is on blocklist (KV namespace)
const blockedIP = await env.BLOCKED_IPS.get(clientIP);
if (blockedIP) {
return new Response('Access Denied', {
status: 403,
headers: {
'X-Block-Reason': 'IP Blocklist',
'Retry-After': '3600'
}
});
}
// Get IP reputation
const reputationData = await env.IP_REPUTATION.get(clientIP);
let reputation: IPReputation = reputationData
? JSON.parse(reputationData)
: { score: 100, violations: 0, lastViolation: 0, blocked: false };
// Suspicious request detection
const suspicionScore = calculateSuspicionScore(request, userAgent, country);
// Rate limiting check (KV namespace)
const rateLimitKey = `ratelimit:${clientIP}`;
const rateLimitData = await env.RATE_LIMITS.get(rateLimitKey);
let rateLimit: RateLimitEntry = rateLimitData
? JSON.parse(rateLimitData)
: { count: 0, timestamp: Date.now(), score: 0 };
const now = Date.now();
const windowMs = 60000; // 1 minute window
// Reset window if expired
if (now - rateLimit.timestamp > windowMs) {
rateLimit = { count: 0, timestamp: now, score: 0 };
}
rateLimit.count++;
rateLimit.score += suspicionScore;
// Thresholds
const MAX_REQUESTS_PER_MIN = 60;
const MAX_SUSPICION_SCORE = 150;
// Check if limits exceeded
if (rateLimit.count > MAX_REQUESTS_PER_MIN || rateLimit.score > MAX_SUSPICION_SCORE) {
reputation.violations++;
reputation.lastViolation = now;
reputation.score = Math.max(0, reputation.score - 20);
// Update reputation
await env.IP_REPUTATION.put(
clientIP,
JSON.stringify(reputation),
{ expirationTtl: 86400 }
);
// Progressive response based on violation history
if (reputation.violations > 3) {
// Block for 1 hour
await env.BLOCKED_IPS.put(clientIP, 'auto-block', { expirationTtl: 3600 });
return new Response('Too Many Requests - Blocked', {
status: 429,
headers: {
'Retry-After': '3600',
'X-Block-Reason': 'Repeated Violations'
}
});
} else {
// Issue CAPTCHA challenge
return issueChallenge(request, env, 'rate-limit');
}
}
// Check reputation score
if (reputation.score < 30) {
return issueChallenge(request, env, 'low-reputation');
}
// Update rate limit
await env.RATE_LIMITS.put(
rateLimitKey,
JSON.stringify(rateLimit),
{ expirationTtl: 120 }
);
// Allow request to pass
const response = await fetch(request);
// Improve reputation on successful requests
if (response.status < 400) {
reputation.score = Math.min(100, reputation.score + 1);
await env.IP_REPUTATION.put(
clientIP,
JSON.stringify(reputation),
{ expirationTtl: 86400 }
);
}
return response;
}
};
function calculateSuspicionScore(
request: Request,
userAgent: string,
country: string
): number {
let score = 0;
const url = new URL(request.url);
// Bot detection
const botPatterns = [
/bot/i, /crawler/i, /spider/i, /scraper/i,
/curl/i, /wget/i, /python/i, /java/i
];
if (botPatterns.some(pattern => pattern.test(userAgent))) {
score += 30;
}
// Empty or suspicious user agent
if (!userAgent || userAgent.length < 10) {
score += 25;
}
// High-risk countries (customize based on your threat model)
const highRiskCountries = ['XX', 'CN', 'RU', 'KP'];
if (highRiskCountries.includes(country)) {
score += 15;
}
// Suspicious URL patterns
if (url.pathname.includes('..') || url.pathname.includes('admin')) {
score += 40;
}
// HTTP method anomalies
if (!['GET', 'POST', 'OPTIONS'].includes(request.method)) {
score += 20;
}
// Missing common headers
if (!request.headers.get('Accept') || !request.headers.get('Accept-Language')) {
score += 10;
}
return score;
}
async function issueChallenge(
request: Request,
env: any,
reason: string
): Promise<Response> {
const html = `
<!DOCTYPE html>
<html>
<head>
<title>Security Challenge</title>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
</head>
<body>
<h1>Security Verification Required</h1>
<p>Please complete this challenge to continue.</p>
<form method="POST" action="/verify-challenge">
<div class="cf-turnstile" data-sitekey="${env.TURNSTILE_SITE_KEY}"></div>
<input type="hidden" name="reason" value="${reason}" />
<button type="submit">Verify</button>
</form>
</body>
</html>
`;
return new Response(html, {
status: 403,
headers: {
'Content-Type': 'text/html',
'X-Challenge-Reason': reason
}
});
}
Configure WAF rules to block common attack patterns. This AWS WAF configuration demonstrates rule groups for SQL injection, XSS, and rate-based blocking:
// infrastructure/waf-rules.ts
// AWS WAF Web ACL configuration for DDoS protection
import * as aws from '@pulumi/aws';
export function createWAFWebACL(name: string): aws.wafv2.WebAcl {
return new aws.wafv2.WebAcl(name, {
scope: 'CLOUDFRONT',
defaultAction: { allow: {} },
rules: [
// AWS Managed Rules - Core Rule Set
{
name: 'AWSManagedRulesCommonRuleSet',
priority: 1,
statement: {
managedRuleGroupStatement: {
vendorName: 'AWS',
name: 'AWSManagedRulesCommonRuleSet'
}
},
overrideAction: { none: {} },
visibilityConfig: {
cloudwatchMetricsEnabled: true,
metricName: 'AWSManagedRulesCommonRuleSetMetric',
sampledRequestsEnabled: true
}
},
// Rate-based rule - 2000 requests per 5 minutes per IP
{
name: 'RateLimitRule',
priority: 2,
statement: {
rateBasedStatement: {
limit: 2000,
aggregateKeyType: 'IP'
}
},
action: {
block: {
customResponse: {
responseCode: 429,
customResponseBodyKey: 'rate-limit-body'
}
}
},
visibilityConfig: {
cloudwatchMetricsEnabled: true,
metricName: 'RateLimitRuleMetric',
sampledRequestsEnabled: true
}
},
// Geo-blocking (optional - customize)
{
name: 'GeoBlockingRule',
priority: 3,
statement: {
notStatement: {
statement: {
geoMatchStatement: {
countryCodes: ['US', 'CA', 'GB', 'DE', 'FR', 'JP', 'AU']
}
}
}
},
action: { block: {} },
visibilityConfig: {
cloudwatchMetricsEnabled: true,
metricName: 'GeoBlockingRuleMetric',
sampledRequestsEnabled: true
}
}
],
visibilityConfig: {
cloudwatchMetricsEnabled: true,
metricName: 'ChatGPTAppWAFMetric',
sampledRequestsEnabled: true
}
});
}
Multi-Layer Rate Limiting Defense
Application-layer rate limiting provides granular control beyond CDN-level throttling. Implement rate limiting at multiple tiers: IP-based limits, authenticated user limits, API endpoint limits, and OpenAI quota protection.
This production-ready rate limiter uses Redis for distributed state and implements token bucket algorithm with multiple limit tiers:
// src/middleware/rate-limiter.ts
// Multi-layer distributed rate limiter with Redis backend
// Supports: IP limits, user limits, endpoint limits, API quota protection
import { Request, Response, NextFunction } from 'express';
import Redis from 'ioredis';
interface RateLimitConfig {
windowMs: number;
maxRequests: number;
skipSuccessfulRequests?: boolean;
skipFailedRequests?: boolean;
keyGenerator?: (req: Request) => string;
}
interface RateLimitTier {
name: string;
windowMs: number;
maxRequests: number;
}
export class MultiLayerRateLimiter {
private redis: Redis;
private tiers: Map<string, RateLimitTier[]>;
constructor(redisUrl: string) {
this.redis = new Redis(redisUrl);
this.tiers = new Map();
// Define rate limit tiers
this.defineDefaultTiers();
}
private defineDefaultTiers(): void {
// IP-based limits (unauthenticated users)
this.tiers.set('ip', [
{ name: 'second', windowMs: 1000, maxRequests: 10 },
{ name: 'minute', windowMs: 60000, maxRequests: 60 },
{ name: 'hour', windowMs: 3600000, maxRequests: 500 }
]);
// Authenticated user limits
this.tiers.set('user', [
{ name: 'second', windowMs: 1000, maxRequests: 20 },
{ name: 'minute', windowMs: 60000, maxRequests: 100 },
{ name: 'hour', windowMs: 3600000, maxRequests: 1000 }
]);
// MCP tool call limits (protect OpenAI quota)
this.tiers.set('mcp-tool', [
{ name: 'second', windowMs: 1000, maxRequests: 5 },
{ name: 'minute', windowMs: 60000, maxRequests: 30 },
{ name: 'hour', windowMs: 3600000, maxRequests: 200 }
]);
// Admin endpoints (strict limits)
this.tiers.set('admin', [
{ name: 'second', windowMs: 1000, maxRequests: 2 },
{ name: 'minute', windowMs: 60000, maxRequests: 10 },
{ name: 'hour', windowMs: 3600000, maxRequests: 50 }
]);
}
public middleware(tierName: string = 'ip'): (req: Request, res: Response, next: NextFunction) => Promise<void> {
return async (req: Request, res: Response, next: NextFunction): Promise<void> => {
const tiers = this.tiers.get(tierName);
if (!tiers) {
return next();
}
const key = this.generateKey(req, tierName);
try {
// Check all tiers
for (const tier of tiers) {
const allowed = await this.checkLimit(key, tier);
if (!allowed) {
const retryAfter = Math.ceil(tier.windowMs / 1000);
res.setHeader('X-RateLimit-Limit', tier.maxRequests.toString());
res.setHeader('X-RateLimit-Remaining', '0');
res.setHeader('X-RateLimit-Reset', (Date.now() + tier.windowMs).toString());
res.setHeader('Retry-After', retryAfter.toString());
res.status(429).json({
error: 'Too Many Requests',
message: `Rate limit exceeded. Try again in ${retryAfter} seconds.`,
tier: tier.name,
limit: tier.maxRequests,
window: tier.windowMs
});
return;
}
}
// Increment counters for all tiers
await Promise.all(tiers.map(tier => this.incrementCounter(key, tier)));
next();
} catch (error) {
console.error('Rate limiter error:', error);
// Fail open - allow request if rate limiter fails
next();
}
};
}
private generateKey(req: Request, tierName: string): string {
const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress || 'unknown';
const userId = (req as any).user?.uid || 'anonymous';
const path = req.path;
switch (tierName) {
case 'user':
return `ratelimit:user:${userId}`;
case 'mcp-tool':
return `ratelimit:mcp:${userId}:${path}`;
case 'admin':
return `ratelimit:admin:${userId}:${ip}`;
default:
return `ratelimit:ip:${ip}`;
}
}
private async checkLimit(key: string, tier: RateLimitTier): Promise<boolean> {
const tierKey = `${key}:${tier.name}`;
const current = await this.redis.get(tierKey);
if (!current) {
return true;
}
const count = parseInt(current, 10);
return count < tier.maxRequests;
}
private async incrementCounter(key: string, tier: RateLimitTier): Promise<void> {
const tierKey = `${key}:${tier.name}`;
const multi = this.redis.multi();
multi.incr(tierKey);
multi.pexpire(tierKey, tier.windowMs);
await multi.exec();
}
public async resetLimit(identifier: string, tierName: string): Promise<void> {
const pattern = `ratelimit:${tierName}:${identifier}:*`;
const keys = await this.redis.keys(pattern);
if (keys.length > 0) {
await this.redis.del(...keys);
}
}
public async getUsage(identifier: string, tierName: string): Promise<Record<string, number>> {
const tiers = this.tiers.get(tierName);
if (!tiers) return {};
const key = tierName === 'ip'
? `ratelimit:ip:${identifier}`
: `ratelimit:${tierName}:${identifier}`;
const usage: Record<string, number> = {};
for (const tier of tiers) {
const tierKey = `${key}:${tier.name}`;
const count = await this.redis.get(tierKey);
usage[tier.name] = count ? parseInt(count, 10) : 0;
}
return usage;
}
}
// Usage example
// const rateLimiter = new MultiLayerRateLimiter(process.env.REDIS_URL);
// app.use('/api', rateLimiter.middleware('ip'));
// app.use('/mcp', rateLimiter.middleware('mcp-tool'));
Implement CAPTCHA challenges for suspicious traffic patterns:
// src/middleware/captcha-challenge.ts
// Adaptive CAPTCHA challenge system with Cloudflare Turnstile
import { Request, Response, NextFunction } from 'express';
import axios from 'axios';
interface ChallengeConfig {
threshold: number;
enabled: boolean;
siteKey: string;
secretKey: string;
}
export class CaptchaChallenge {
private config: ChallengeConfig;
private suspicionScores: Map<string, number>;
constructor(config: ChallengeConfig) {
this.config = config;
this.suspicionScores = new Map();
}
public middleware() {
return async (req: Request, res: Response, next: NextFunction): Promise<void> => {
if (!this.config.enabled) {
return next();
}
const ip = this.getClientIP(req);
const suspicionScore = this.calculateSuspicionScore(req);
// Update suspicion score
const currentScore = this.suspicionScores.get(ip) || 0;
const newScore = currentScore + suspicionScore;
this.suspicionScores.set(ip, newScore);
// Require CAPTCHA if threshold exceeded
if (newScore > this.config.threshold) {
const token = req.body['cf-turnstile-response'] || req.headers['x-captcha-token'];
if (!token) {
res.status(403).json({
error: 'CAPTCHA Required',
message: 'Please complete the CAPTCHA challenge',
siteKey: this.config.siteKey,
challenge: true
});
return;
}
// Verify CAPTCHA token
const verified = await this.verifyCaptcha(token, ip);
if (!verified) {
res.status(403).json({
error: 'CAPTCHA Verification Failed',
message: 'Invalid CAPTCHA response',
challenge: true
});
return;
}
// Reset suspicion score on successful verification
this.suspicionScores.set(ip, 0);
}
next();
};
}
private calculateSuspicionScore(req: Request): number {
let score = 0;
// User agent checks
const userAgent = req.headers['user-agent'] || '';
if (!userAgent || userAgent.length < 10) score += 30;
if (/bot|crawler|spider/i.test(userAgent)) score += 25;
// Method checks
if (req.method !== 'GET' && req.method !== 'POST') score += 20;
// Header checks
if (!req.headers['accept']) score += 15;
if (!req.headers['accept-language']) score += 10;
// Path checks
if (req.path.includes('admin') || req.path.includes('..')) score += 40;
return score;
}
private async verifyCaptcha(token: string, ip: string): Promise<boolean> {
try {
const response = await axios.post(
'https://challenges.cloudflare.com/turnstile/v0/siteverify',
{
secret: this.config.secretKey,
response: token,
remoteip: ip
}
);
return response.data.success === true;
} catch (error) {
console.error('CAPTCHA verification error:', error);
return false;
}
}
private getClientIP(req: Request): string {
return (req.headers['cf-connecting-ip'] ||
req.headers['x-forwarded-for'] ||
req.socket.remoteAddress ||
'unknown') as string;
}
}
Infrastructure Resilience: Auto-Scaling & Circuit Breakers
Infrastructure resilience ensures your ChatGPT app degrades gracefully under attack rather than failing completely. Auto-scaling responds to traffic spikes, load balancers distribute requests, and circuit breakers prevent cascade failures.
This Kubernetes Horizontal Pod Autoscaler configuration demonstrates auto-scaling based on CPU, memory, and custom metrics:
# infrastructure/k8s/autoscaling.yaml
# Kubernetes Horizontal Pod Autoscaler for MCP server
# Scales based on CPU, memory, and custom metrics
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: mcp-server-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: mcp-server
minReplicas: 3
maxReplicas: 50
metrics:
# CPU-based scaling
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
# Memory-based scaling
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
# Request rate (custom metric from Prometheus)
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "100"
# Response time (custom metric)
- type: Pods
pods:
metric:
name: http_request_duration_p95
target:
type: AverageValue
averageValue: "500m" # 500ms
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 100
periodSeconds: 15
- type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 60
- type: Pods
value: 2
periodSeconds: 60
selectPolicy: Min
---
apiVersion: v1
kind: Service
metadata:
name: mcp-server
namespace: production
spec:
selector:
app: mcp-server
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: LoadBalancer
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 300
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcp-server
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: mcp-server
template:
metadata:
labels:
app: mcp-server
spec:
containers:
- name: mcp-server
image: gcr.io/your-project/mcp-server:latest
ports:
- containerPort: 3000
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 2000m
memory: 2Gi
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 10
periodSeconds: 5
env:
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: openai-secrets
key: api-key
- name: REDIS_URL
valueFrom:
configMapKeyRef:
name: app-config
key: redis-url
- name: MAX_CONCURRENT_REQUESTS
value: "100"
Circuit breaker implementation prevents cascade failures by failing fast when downstream services are unhealthy:
// src/utils/circuit-breaker.ts
// Circuit breaker pattern for external API calls (OpenAI, databases)
interface CircuitBreakerConfig {
failureThreshold: number;
successThreshold: number;
timeout: number;
resetTimeout: number;
}
enum CircuitState {
CLOSED = 'CLOSED',
OPEN = 'OPEN',
HALF_OPEN = 'HALF_OPEN'
}
export class CircuitBreaker {
private state: CircuitState = CircuitState.CLOSED;
private failureCount: number = 0;
private successCount: number = 0;
private nextAttempt: number = Date.now();
private config: CircuitBreakerConfig;
constructor(config: Partial<CircuitBreakerConfig> = {}) {
this.config = {
failureThreshold: config.failureThreshold || 5,
successThreshold: config.successThreshold || 2,
timeout: config.timeout || 60000,
resetTimeout: config.resetTimeout || 30000
};
}
public async execute<T>(fn: () => Promise<T>): Promise<T> {
if (this.state === CircuitState.OPEN) {
if (Date.now() < this.nextAttempt) {
throw new Error('Circuit breaker is OPEN');
}
this.state = CircuitState.HALF_OPEN;
}
try {
const result = await this.executeWithTimeout(fn);
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
private async executeWithTimeout<T>(fn: () => Promise<T>): Promise<T> {
return Promise.race([
fn(),
new Promise<T>((_, reject) =>
setTimeout(() => reject(new Error('Request timeout')), this.config.timeout)
)
]);
}
private onSuccess(): void {
this.failureCount = 0;
if (this.state === CircuitState.HALF_OPEN) {
this.successCount++;
if (this.successCount >= this.config.successThreshold) {
this.state = CircuitState.CLOSED;
this.successCount = 0;
}
}
}
private onFailure(): void {
this.failureCount++;
this.successCount = 0;
if (this.failureCount >= this.config.failureThreshold) {
this.state = CircuitState.OPEN;
this.nextAttempt = Date.now() + this.config.resetTimeout;
}
}
public getState(): CircuitState {
return this.state;
}
public reset(): void {
this.state = CircuitState.CLOSED;
this.failureCount = 0;
this.successCount = 0;
}
}
Real-Time Traffic Analysis: Anomaly Detection
Proactive threat detection identifies attacks before they cause damage. Monitor traffic patterns, detect anomalies, and automatically trigger defensive measures.
This anomaly detection system uses statistical analysis to identify traffic deviations:
// src/monitoring/anomaly-detector.ts
// Real-time traffic anomaly detection with statistical analysis
import { EventEmitter } from 'events';
interface TrafficMetrics {
timestamp: number;
requestCount: number;
errorRate: number;
avgResponseTime: number;
uniqueIPs: number;
suspiciousScore: number;
}
interface AnomalyThresholds {
requestCountMultiplier: number;
errorRateThreshold: number;
responseTimeMultiplier: number;
uniqueIPRatioThreshold: number;
}
export class AnomalyDetector extends EventEmitter {
private metricsHistory: TrafficMetrics[] = [];
private readonly historySize: number = 60; // 60 data points
private thresholds: AnomalyThresholds;
constructor(thresholds: Partial<AnomalyThresholds> = {}) {
super();
this.thresholds = {
requestCountMultiplier: thresholds.requestCountMultiplier || 3.0,
errorRateThreshold: thresholds.errorRateThreshold || 0.15,
responseTimeMultiplier: thresholds.responseTimeMultiplier || 2.5,
uniqueIPRatioThreshold: thresholds.uniqueIPRatioThreshold || 0.1
};
}
public recordMetrics(metrics: TrafficMetrics): void {
this.metricsHistory.push(metrics);
if (this.metricsHistory.length > this.historySize) {
this.metricsHistory.shift();
}
if (this.metricsHistory.length >= 10) {
this.detectAnomalies(metrics);
}
}
private detectAnomalies(current: TrafficMetrics): void {
const baseline = this.calculateBaseline();
const anomalies: string[] = [];
// Request count spike detection
if (current.requestCount > baseline.avgRequestCount * this.thresholds.requestCountMultiplier) {
anomalies.push('request-spike');
this.emit('anomaly', {
type: 'request-spike',
severity: 'high',
current: current.requestCount,
baseline: baseline.avgRequestCount,
message: `Request count ${current.requestCount} exceeds baseline ${baseline.avgRequestCount.toFixed(0)} by ${this.thresholds.requestCountMultiplier}x`
});
}
// Error rate spike detection
if (current.errorRate > this.thresholds.errorRateThreshold) {
anomalies.push('error-spike');
this.emit('anomaly', {
type: 'error-spike',
severity: 'critical',
current: current.errorRate,
threshold: this.thresholds.errorRateThreshold,
message: `Error rate ${(current.errorRate * 100).toFixed(1)}% exceeds threshold ${(this.thresholds.errorRateThreshold * 100)}%`
});
}
// Response time degradation
if (current.avgResponseTime > baseline.avgResponseTime * this.thresholds.responseTimeMultiplier) {
anomalies.push('slow-response');
this.emit('anomaly', {
type: 'slow-response',
severity: 'medium',
current: current.avgResponseTime,
baseline: baseline.avgResponseTime,
message: `Response time ${current.avgResponseTime.toFixed(0)}ms exceeds baseline ${baseline.avgResponseTime.toFixed(0)}ms`
});
}
// Suspicious IP ratio (many requests from few IPs)
const ipRatio = current.uniqueIPs / current.requestCount;
if (ipRatio < this.thresholds.uniqueIPRatioThreshold) {
anomalies.push('concentrated-traffic');
this.emit('anomaly', {
type: 'concentrated-traffic',
severity: 'high',
ratio: ipRatio,
threshold: this.thresholds.uniqueIPRatioThreshold,
message: `Traffic concentrated from few IPs: ratio ${ipRatio.toFixed(3)} below threshold ${this.thresholds.uniqueIPRatioThreshold}`
});
}
// Suspicion score threshold
if (current.suspiciousScore > 70) {
anomalies.push('high-suspicion');
this.emit('anomaly', {
type: 'high-suspicion',
severity: 'high',
score: current.suspiciousScore,
message: `Suspicion score ${current.suspiciousScore} indicates potential attack`
});
}
// Combined anomaly detection (DDoS probability)
if (anomalies.length >= 3) {
this.emit('anomaly', {
type: 'probable-ddos',
severity: 'critical',
anomalies,
message: `Multiple anomalies detected: ${anomalies.join(', ')}. Probable DDoS attack in progress.`,
recommendation: 'Enable emergency rate limiting and IP blocking'
});
}
}
private calculateBaseline(): {
avgRequestCount: number;
avgErrorRate: number;
avgResponseTime: number;
} {
const recentMetrics = this.metricsHistory.slice(-30);
const avgRequestCount = recentMetrics.reduce((sum, m) => sum + m.requestCount, 0) / recentMetrics.length;
const avgErrorRate = recentMetrics.reduce((sum, m) => sum + m.errorRate, 0) / recentMetrics.length;
const avgResponseTime = recentMetrics.reduce((sum, m) => sum + m.avgResponseTime, 0) / recentMetrics.length;
return { avgRequestCount, avgErrorRate, avgResponseTime };
}
public getMetricsHistory(): TrafficMetrics[] {
return [...this.metricsHistory];
}
}
Incident Response: Automated Defense
When anomalies are detected, automated incident response activates emergency defenses. This runbook automation system executes predefined response procedures:
// src/incident-response/runbook-automation.ts
// Automated incident response for DDoS attacks
import { AnomalyDetector } from '../monitoring/anomaly-detector';
import { MultiLayerRateLimiter } from '../middleware/rate-limiter';
import axios from 'axios';
interface IncidentLog {
timestamp: number;
severity: string;
type: string;
actions: string[];
resolved: boolean;
}
export class IncidentResponseAutomation {
private anomalyDetector: AnomalyDetector;
private rateLimiter: MultiLayerRateLimiter;
private incidentLog: IncidentLog[] = [];
private emergencyMode: boolean = false;
constructor(
anomalyDetector: AnomalyDetector,
rateLimiter: MultiLayerRateLimiter
) {
this.anomalyDetector = anomalyDetector;
this.rateLimiter = rateLimiter;
this.setupEventListeners();
}
private setupEventListeners(): void {
this.anomalyDetector.on('anomaly', (event: any) => {
this.handleAnomaly(event);
});
}
private async handleAnomaly(event: any): Promise<void> {
const incident: IncidentLog = {
timestamp: Date.now(),
severity: event.severity,
type: event.type,
actions: [],
resolved: false
};
console.log(`🚨 INCIDENT DETECTED: ${event.type} (${event.severity})`);
console.log(` Message: ${event.message}`);
// Execute response based on severity
switch (event.severity) {
case 'critical':
await this.executeCriticalResponse(incident, event);
break;
case 'high':
await this.executeHighResponse(incident, event);
break;
case 'medium':
await this.executeMediumResponse(incident, event);
break;
}
this.incidentLog.push(incident);
await this.notifyTeam(incident, event);
}
private async executeCriticalResponse(incident: IncidentLog, event: any): Promise<void> {
// Enable emergency mode
this.emergencyMode = true;
incident.actions.push('emergency-mode-enabled');
// Aggressive rate limiting (10 req/min per IP)
incident.actions.push('aggressive-rate-limit');
// Block top offending IPs
if (event.type === 'probable-ddos') {
// This would integrate with your IP tracking system
incident.actions.push('blocked-top-offenders');
}
// Scale infrastructure
await this.triggerAutoScaling();
incident.actions.push('triggered-auto-scaling');
// Enable Cloudflare "I'm Under Attack" mode
await this.enableCloudflareAttackMode();
incident.actions.push('cloudflare-attack-mode');
}
private async executeHighResponse(incident: IncidentLog, event: any): Promise<void> {
// Moderate rate limiting
incident.actions.push('moderate-rate-limit');
// Monitor closely
incident.actions.push('enhanced-monitoring');
}
private async executeMediumResponse(incident: IncidentLog, event: any): Promise<void> {
// Log and monitor
incident.actions.push('logged-for-review');
}
private async triggerAutoScaling(): Promise<void> {
// Example: Kubernetes API call to increase replicas
console.log('🔧 Triggering auto-scaling...');
// kubectl scale deployment mcp-server --replicas=20
}
private async enableCloudflareAttackMode(): Promise<void> {
// Cloudflare API example
const zoneId = process.env.CLOUDFLARE_ZONE_ID;
const apiToken = process.env.CLOUDFLARE_API_TOKEN;
if (!zoneId || !apiToken) return;
try {
await axios.patch(
`https://api.cloudflare.com/client/v4/zones/${zoneId}/settings/security_level`,
{ value: 'under_attack' },
{ headers: { 'Authorization': `Bearer ${apiToken}` } }
);
console.log('🛡️ Cloudflare "Under Attack" mode enabled');
} catch (error) {
console.error('Failed to enable Cloudflare attack mode:', error);
}
}
private async notifyTeam(incident: IncidentLog, event: any): Promise<void> {
// Slack notification
const webhookUrl = process.env.SLACK_WEBHOOK_URL;
if (!webhookUrl) return;
const message = {
text: `🚨 *DDoS Incident Detected*`,
attachments: [
{
color: event.severity === 'critical' ? 'danger' : 'warning',
fields: [
{ title: 'Type', value: event.type, short: true },
{ title: 'Severity', value: event.severity, short: true },
{ title: 'Message', value: event.message, short: false },
{ title: 'Actions Taken', value: incident.actions.join(', '), short: false }
],
ts: Math.floor(incident.timestamp / 1000)
}
]
};
try {
await axios.post(webhookUrl, message);
} catch (error) {
console.error('Failed to send Slack notification:', error);
}
}
public disableEmergencyMode(): void {
this.emergencyMode = false;
console.log('✅ Emergency mode disabled');
}
public getIncidentLog(): IncidentLog[] {
return this.incidentLog;
}
}
Conclusion: Defense-in-Depth for ChatGPT Apps
DDoS protection for ChatGPT applications requires comprehensive defense-in-depth strategy spanning perimeter security, application-layer controls, infrastructure resilience, and automated incident response. The production-ready implementations in this guide provide battle-tested protection against volumetric attacks, application-layer exploits, and API quota exhaustion.
Start with CDN and WAF integration using Cloudflare Workers or AWS WAF to filter malicious traffic at the edge before it reaches your infrastructure. Implement multi-layer rate limiting with Redis-backed distributed state to enforce granular limits on IP addresses, authenticated users, and MCP tool calls. Deploy auto-scaling infrastructure with Kubernetes HPA to absorb traffic spikes and circuit breakers to prevent cascade failures. Enable real-time anomaly detection with statistical baseline analysis to identify attacks as they emerge. Finally, automate incident response with runbook automation that executes defensive measures when critical anomalies are detected.
DDoS attacks will only intensify as your ChatGPT app reaches OpenAI's massive user base. Implement these defenses today to protect your infrastructure, preserve your OpenAI API quota, and ensure reliable service for legitimate users.
Ready to deploy DDoS-protected ChatGPT apps without writing security code? MakeAIHQ provides enterprise-grade DDoS protection built into every app you create—Cloudflare integration, adaptive rate limiting, auto-scaling infrastructure, and 24/7 threat monitoring included. Build your first protected ChatGPT app in minutes with our no-code platform and Instant App Wizard.
Related Resources
- ChatGPT App Security Hardening Guide - Complete security pillar guide
- Rate Limiting & Throttling for ChatGPT Apps - Detailed rate limiting strategies
- Cloudflare Integration for ChatGPT Apps - Cloudflare Workers deployment
- Auto-Scaling Strategies for ChatGPT Apps - Kubernetes and serverless scaling
External References
- Cloudflare DDoS Protection - Official Cloudflare DDoS documentation
- AWS Shield Documentation - AWS DDoS protection service
- OWASP DDoS Mitigation - Industry best practices