API Performance Under Attack: Maintaining Service During Threats
Maintain API performance and availability during security attacks with resilient architecture and defense strategies.
Table of Contents
Table of Contents
API Performance Under Attack: Maintaining Service During Threats
Maintaining API performance during security attacks requires resilient architecture and proactive defense strategies. Building attack-resistant systems ensures service availability while protecting against threats.
API Performance Under Attack Overview
Practical Implementation Examples
Attack Detection Engine
// Production-ready attack detection engine for API protection
interface AttackPattern {
id: string
name: string
type: 'ddos' | 'injection' | 'scraping' | 'credential_stuffing' | 'api_abuse'
confidence: number
severity: 'low' | 'medium' | 'high' | 'critical'
indicators: string[]
mitigation: string[]
timestamp: number
sourceIP?: string
userAgent?: string
endpoint?: string
}
interface TrafficMetrics {
ip: string
endpoint: string
requestsPerSecond: number
requestsPerMinute: number
averageResponseTime: number
errorRate: number
uniqueUserAgents: number
geographicSpread: number
timestamp: number
}
interface AttackSignature {
id: string
pattern: RegExp | string
type: 'request_pattern' | 'payload_analysis' | 'behavioral' | 'statistical'
confidence: number
description: string
examples: string[]
}
interface DetectionRule {
id: string
name: string
condition: {
metric: string
operator: '>' | '<' | '>=' | '<=' | '=='
threshold: number
timeframe: number // seconds
}
action: 'log' | 'block' | 'throttle' | 'captcha' | 'redirect'
severity: 'low' | 'medium' | 'high' | 'critical'
cooldown: number // seconds between triggers
}
class AttackDetectionEngine {
private trafficBuffer: Map<string, TrafficMetrics[]> = new Map()
private attackSignatures: AttackSignature[] = []
private detectionRules: DetectionRule[] = []
private activeAttacks: Map<string, AttackPattern> = new Map()
private blockedIPs: Set<string> = new Set()
private subscribers: Array<(attack: AttackPattern) => void> = []
constructor() {
this.initializeAttackSignatures()
this.initializeDetectionRules()
this.startTrafficAnalysis()
}
// Analyze incoming request for attack patterns
async analyzeRequest(request: {
ip: string
endpoint: string
userAgent: string
method: string
headers: Record<string, string>
body?: string
responseTime?: number
statusCode?: number
}): Promise<{
isAttack: boolean
patterns: AttackPattern[]
riskScore: number
recommendations: string[]
}> {
const analysis = {
isAttack: false,
patterns: [] as AttackPattern[],
riskScore: 0,
recommendations: [] as string[]
}
// Update traffic metrics
this.updateTrafficMetrics(request)
// Check attack signatures
const signatureMatches = this.checkAttackSignatures(request)
analysis.patterns.push(...signatureMatches)
// Check behavioral patterns
const behavioralMatches = await this.checkBehavioralPatterns(request)
analysis.patterns.push(...behavioralMatches)
// Check statistical anomalies
const statisticalMatches = this.checkStatisticalAnomalies(request)
analysis.patterns.push(...statisticalMatches)
// Calculate overall risk score
analysis.riskScore = this.calculateRiskScore(analysis.patterns)
// Determine if this is an attack
analysis.isAttack = analysis.riskScore > 70 || analysis.patterns.some(p => p.severity === 'critical')
// Generate recommendations
analysis.recommendations = this.generateRecommendations(analysis.patterns, request.ip)
// Trigger attack response if necessary
if (analysis.isAttack) {
await this.triggerAttackResponse(analysis.patterns, request.ip)
}
// Notify subscribers
if (analysis.patterns.length > 0) {
analysis.patterns.forEach(pattern => {
this.subscribers.forEach(callback => {
try {
callback(pattern)
} catch (error) {
console.error('Error in attack detection subscriber:', error)
}
})
})
}
return analysis
}
// Subscribe to attack detection events
subscribe(callback: (attack: AttackPattern) => void): () => void {
this.subscribers.push(callback)
return () => {
const index = this.subscribers.indexOf(callback)
if (index > -1) {
this.subscribers.splice(index, 1)
}
}
}
// Get current attack status
getAttackStatus(): {
activeAttacks: AttackPattern[]
blockedIPs: string[]
totalDetections: number
systemHealth: 'healthy' | 'under_attack' | 'compromised'
} {
const activeAttacks = Array.from(this.activeAttacks.values())
const totalDetections = activeAttacks.length
let systemHealth: 'healthy' | 'under_attack' | 'compromised' = 'healthy'
if (totalDetections > 10) systemHealth = 'under_attack'
if (totalDetections > 50) systemHealth = 'compromised'
return {
activeAttacks,
blockedIPs: Array.from(this.blockedIPs),
totalDetections,
systemHealth
}
}
private updateTrafficMetrics(request: any): void {
const key = `${request.ip}:${request.endpoint}`
const currentMetrics = this.trafficBuffer.get(key) || []
const metrics: TrafficMetrics = {
ip: request.ip,
endpoint: request.endpoint,
requestsPerSecond: this.calculateRequestsPerSecond(currentMetrics),
requestsPerMinute: currentMetrics.length,
averageResponseTime: request.responseTime || 0,
errorRate: request.statusCode && request.statusCode >= 400 ? 1 : 0,
uniqueUserAgents: this.getUniqueUserAgents(currentMetrics, request),
geographicSpread: 0, // Would be calculated from geolocation data
timestamp: Date.now()
}
currentMetrics.push(metrics)
// Keep only last 5 minutes of data
const fiveMinutesAgo = Date.now() - 5 * 60 * 1000
const recentMetrics = currentMetrics.filter(m => m.timestamp > fiveMinutesAgo)
this.trafficBuffer.set(key, recentMetrics)
}
private calculateRequestsPerSecond(metrics: TrafficMetrics[]): number {
if (metrics.length < 2) return 0
const timeSpan = metrics[metrics.length - 1].timestamp - metrics[0].timestamp
if (timeSpan === 0) return 0
return (metrics.length / (timeSpan / 1000))
}
private getUniqueUserAgents(metrics: TrafficMetrics[], currentRequest: any): number {
const userAgents = new Set(metrics.map(m => m.timestamp).concat(currentRequest.userAgent))
return userAgents.size
}
private checkAttackSignatures(request: any): AttackPattern[] {
const patterns: AttackPattern[] = []
for (const signature of this.attackSignatures) {
let matches = false
switch (signature.type) {
case 'request_pattern':
matches = this.checkRequestPattern(signature, request)
break
case 'payload_analysis':
matches = this.checkPayloadAnalysis(signature, request)
break
case 'behavioral':
matches = this.checkBehavioralSignature(signature, request)
break
case 'statistical':
matches = this.checkStatisticalSignature(signature, request)
break
}
if (matches) {
patterns.push({
id: `attack_${Date.now()}_${Math.random()}`,
name: signature.description,
type: this.mapSignatureToAttackType(signature),
confidence: signature.confidence,
severity: this.calculateSeverity(signature.confidence),
indicators: [signature.id],
mitigation: this.getMitigationStrategies(signature),
timestamp: Date.now(),
sourceIP: request.ip,
userAgent: request.userAgent,
endpoint: request.endpoint
})
}
}
return patterns
}
private async checkBehavioralPatterns(request: any): Promise<AttackPattern[]> {
const patterns: AttackPattern[] = []
const key = `${request.ip}:${request.endpoint}`
const metrics = this.trafficBuffer.get(key) || []
if (metrics.length < 10) return patterns
// Detect rapid fire requests (DDoS)
const recentMetrics = metrics.slice(-20)
const avgRPS = recentMetrics.reduce((sum, m) => sum + m.requestsPerSecond, 0) / recentMetrics.length
if (avgRPS > 100) { // More than 100 RPS from single IP
patterns.push({
id: `ddos_${Date.now()}`,
name: 'Distributed Denial of Service Attack',
type: 'ddos',
confidence: Math.min(100, avgRPS / 10),
severity: avgRPS > 500 ? 'critical' : 'high',
indicators: ['high_request_rate', 'single_ip_flood'],
mitigation: ['rate_limiting', 'ip_blocking', 'traffic_filtering'],
timestamp: Date.now(),
sourceIP: request.ip,
endpoint: request.endpoint
})
}
// Detect credential stuffing
const uniqueUserAgents = recentMetrics.reduce((sum, m) => sum + m.uniqueUserAgents, 0) / recentMetrics.length
if (uniqueUserAgents < 2 && recentMetrics.length > 50) {
patterns.push({
id: `credential_stuffing_${Date.now()}`,
name: 'Credential Stuffing Attack',
type: 'credential_stuffing',
confidence: 85,
severity: 'high',
indicators: ['low_user_agent_diversity', 'high_request_volume'],
mitigation: ['captcha_challenge', 'account_lockout', 'behavioral_analysis'],
timestamp: Date.now(),
sourceIP: request.ip,
endpoint: request.endpoint
})
}
return patterns
}
private checkStatisticalAnomalies(request: any): AttackPattern[] {
const patterns: AttackPattern[] = []
const key = `${request.ip}:${request.endpoint}`
const metrics = this.trafficBuffer.get(key) || []
if (metrics.length < 30) return patterns
// Calculate statistical thresholds
const responseTimes = metrics.map(m => m.averageResponseTime).filter(t => t > 0)
const errorRates = metrics.map(m => m.errorRate)
if (responseTimes.length > 0) {
const avgResponseTime = responseTimes.reduce((a, b) => a + b, 0) / responseTimes.length
const maxResponseTime = Math.max(...responseTimes)
// Detect slowloris-like attacks (very slow requests)
if (maxResponseTime > 30000 && avgResponseTime > 10000) { // 30s and 10s avg
patterns.push({
id: `slowloris_${Date.now()}`,
name: 'Slowloris Attack',
type: 'ddos',
confidence: 90,
severity: 'high',
indicators: ['extremely_slow_requests', 'resource_exhaustion'],
mitigation: ['request_timeout', 'connection_limiting', 'resource_monitoring'],
timestamp: Date.now(),
sourceIP: request.ip,
endpoint: request.endpoint
})
}
}
return patterns
}
private calculateRiskScore(patterns: AttackPattern[]): number {
if (patterns.length === 0) return 0
const totalConfidence = patterns.reduce((sum, p) => sum + p.confidence, 0)
const avgConfidence = totalConfidence / patterns.length
// Boost score for critical severity patterns
const criticalBoost = patterns.some(p => p.severity === 'critical') ? 20 : 0
return Math.min(100, avgConfidence + criticalBoost)
}
private generateRecommendations(patterns: AttackPattern[], ip: string): string[] {
const recommendations = new Set<string>()
patterns.forEach(pattern => {
pattern.mitigation.forEach(mitigation => recommendations.add(mitigation))
if (pattern.type === 'ddos') {
recommendations.add('enable_waf')
recommendations.add('activate_cdn_protection')
}
if (pattern.type === 'injection') {
recommendations.add('input_sanitization')
recommendations.add('parameterized_queries')
}
})
// Add IP-specific recommendations
if (this.blockedIPs.has(ip)) {
recommendations.add('maintain_ip_block')
} else if (patterns.some(p => p.severity === 'critical')) {
recommendations.add('consider_ip_blocking')
}
return Array.from(recommendations)
}
private async triggerAttackResponse(patterns: AttackPattern[], ip: string): Promise<void> {
// Block IP if critical attack detected
const criticalPatterns = patterns.filter(p => p.severity === 'critical')
if (criticalPatterns.length > 0) {
this.blockedIPs.add(ip)
// Set up automatic unblock after cooldown (24 hours)
setTimeout(() => {
this.blockedIPs.delete(ip)
}, 24 * 60 * 60 * 1000)
}
// Log attack details
console.warn(`🚨 Attack detected from IP ${ip}:`, {
patterns: patterns.map(p => ({ type: p.type, severity: p.severity, confidence: p.confidence })),
timestamp: new Date().toISOString(),
endpoint: patterns[0]?.endpoint
})
// In production, this would trigger external notifications, alerts, etc.
}
private checkRequestPattern(signature: AttackSignature, request: any): boolean {
if (typeof signature.pattern === 'string') {
return request.endpoint.includes(signature.pattern) ||
request.userAgent.includes(signature.pattern)
}
if (signature.pattern instanceof RegExp) {
return signature.pattern.test(request.endpoint) ||
signature.pattern.test(request.userAgent || '')
}
return false
}
private checkPayloadAnalysis(signature: AttackSignature, request: any): boolean {
if (!request.body) return false
const suspiciousPatterns = [
/<script/i,
/javascript:/i,
/onload=/i,
/onerror=/i,
/eval(/i,
/union select/i,
/1=1/i,
/admin/i
]
return suspiciousPatterns.some(pattern => pattern.test(request.body))
}
private checkBehavioralSignature(signature: AttackSignature, request: any): boolean {
// Check for automated behavior patterns
const automatedIndicators = [
'python-requests',
'curl',
'wget',
'bot',
'spider',
'crawler'
]
return automatedIndicators.some(indicator =>
(request.userAgent || '').toLowerCase().includes(indicator)
)
}
private checkStatisticalSignature(signature: AttackSignature, request: any): boolean {
const key = `${request.ip}:${request.endpoint}`
const metrics = this.trafficBuffer.get(key) || []
if (metrics.length < 10) return false
// Check for statistical anomalies
const recentMetrics = metrics.slice(-10)
const avgRPS = recentMetrics.reduce((sum, m) => sum + m.requestsPerSecond, 0) / recentMetrics.length
return avgRPS > 50 // More than 50 RPS indicates potential attack
}
private mapSignatureToAttackType(signature: AttackSignature): AttackPattern['type'] {
const typeMapping: Record<string, AttackPattern['type']> = {
'sql_injection': 'injection',
'xss': 'injection',
'ddos': 'ddos',
'scraping': 'scraping',
'credential_stuffing': 'credential_stuffing'
}
return typeMapping[signature.id] || 'api_abuse'
}
private calculateSeverity(confidence: number): AttackPattern['severity'] {
if (confidence >= 90) return 'critical'
if (confidence >= 75) return 'high'
if (confidence >= 60) return 'medium'
return 'low'
}
private getMitigationStrategies(signature: AttackSignature): string[] {
const strategies: Record<string, string[]> = {
'sql_injection': ['input_sanitization', 'prepared_statements', 'waf_rules'],
'xss': ['output_encoding', 'csp_headers', 'input_validation'],
'ddos': ['rate_limiting', 'traffic_filtering', 'cdn_protection'],
'scraping': ['user_agent_filtering', 'honeypot_traps', 'behavioral_analysis'],
'credential_stuffing': ['account_lockout', 'captcha', 'mfa_enforcement']
}
return strategies[signature.id] || ['general_monitoring', 'traffic_analysis']
}
private initializeAttackSignatures(): void {
this.attackSignatures = [
{
id: 'sql_injection',
pattern: /(union|select|insert|update|delete|drop|create|alter)/i,
type: 'payload_analysis',
confidence: 85,
description: 'SQL Injection Attack Pattern',
examples: ['1' OR '1'='1', 'admin'--', '1; DROP TABLE users--']
},
{
id: 'xss',
pattern: /<script|javascript:|onload=|onerror=/i,
type: 'payload_analysis',
confidence: 80,
description: 'Cross-Site Scripting (XSS) Pattern',
examples: ['<script>alert(1)</script>', 'javascript:alert(1)', 'onload=alert(1)']
},
{
id: 'ddos',
pattern: 'high_frequency_requests',
type: 'statistical',
confidence: 70,
description: 'DDoS Attack Pattern',
examples: ['100+ requests per second', 'sustained high traffic']
},
{
id: 'scraping',
pattern: /(python-requests|curl|wget|bot|spider)/i,
type: 'behavioral',
confidence: 75,
description: 'Web Scraping Pattern',
examples: ['automated requests', 'systematic data extraction']
}
]
}
private initializeDetectionRules(): void {
this.detectionRules = [
{
id: 'high_rps',
name: 'High Requests Per Second',
condition: {
metric: 'requestsPerSecond',
operator: '>',
threshold: 100,
timeframe: 60
},
action: 'throttle',
severity: 'medium',
cooldown: 300
},
{
id: 'high_error_rate',
name: 'High Error Rate',
condition: {
metric: 'errorRate',
operator: '>',
threshold: 0.5,
timeframe: 120
},
action: 'block',
severity: 'high',
cooldown: 600
},
{
id: 'slow_requests',
name: 'Extremely Slow Requests',
condition: {
metric: 'averageResponseTime',
operator: '>',
threshold: 30000,
timeframe: 300
},
action: 'block',
severity: 'critical',
cooldown: 3600
}
]
}
private startTrafficAnalysis(): void {
// Analyze traffic patterns every 30 seconds
setInterval(() => {
this.analyzeTrafficPatterns()
}, 30000)
}
private analyzeTrafficPatterns(): void {
// Analyze traffic for emerging patterns
for (const [key, metrics] of this.trafficBuffer.entries()) {
if (metrics.length > 50) {
// Look for patterns that might indicate attacks
const recentMetrics = metrics.slice(-20)
const avgRPS = recentMetrics.reduce((sum, m) => sum + m.requestsPerSecond, 0) / recentMetrics.length
if (avgRPS > 200) {
const [ip, endpoint] = key.split(':')
// Create attack pattern for high-volume traffic
const attackPattern: AttackPattern = {
id: `high_volume_${Date.now()}`,
name: 'High Volume Traffic Attack',
type: 'ddos',
confidence: Math.min(100, avgRPS / 2),
severity: avgRPS > 1000 ? 'critical' : 'high',
indicators: ['extreme_request_volume'],
mitigation: ['traffic_filtering', 'rate_limiting'],
timestamp: Date.now(),
sourceIP: ip,
endpoint: endpoint
}
this.activeAttacks.set(attackPattern.id, attackPattern)
}
}
}
// Clean up old attack records
const oneHourAgo = Date.now() - 60 * 60 * 1000
for (const [id, attack] of this.activeAttacks.entries()) {
if (attack.timestamp < oneHourAgo) {
this.activeAttacks.delete(id)
}
}
}
}
// Integration with Express.js
const attackDetectionEngine = new AttackDetectionEngine()
// Middleware for attack detection
const attackDetectionMiddleware = async (req: any, res: any, next: any) => {
try {
const analysis = await attackDetectionEngine.analyzeRequest({
ip: req.ip || req.connection.remoteAddress,
endpoint: req.path,
method: req.method,
userAgent: req.get('User-Agent'),
headers: req.headers,
body: JSON.stringify(req.body),
responseTime: Date.now() - req.startTime,
statusCode: res.statusCode
})
// Add attack analysis to request object
req.attackAnalysis = analysis
// Set security headers based on analysis
if (analysis.isAttack) {
res.set('X-Threat-Level', 'high')
res.set('X-Risk-Score', analysis.riskScore.toString())
// Implement immediate mitigation
if (analysis.riskScore > 90) {
return res.status(429).json({
error: 'Too Many Requests',
message: 'Request blocked due to suspicious activity',
retryAfter: 3600
})
}
}
// Log attack analysis for monitoring
if (analysis.patterns.length > 0) {
console.log(`Attack analysis for ${req.ip}:`, {
riskScore: analysis.riskScore,
patterns: analysis.patterns.length,
isAttack: analysis.isAttack
})
}
} catch (error) {
console.error('Attack detection middleware error:', error)
req.attackAnalysis = { isAttack: false, patterns: [], riskScore: 0, recommendations: [] }
}
next()
}
// API endpoints for attack management
app.use('/api', attackDetectionMiddleware)
// Get current attack status
app.get('/api/security/attack-status', (req, res) => {
const status = attackDetectionEngine.getAttackStatus()
res.json({
...status,
timestamp: new Date().toISOString()
})
})
// Get blocked IPs
app.get('/api/security/blocked-ips', (req, res) => {
res.json({
blockedIPs: Array.from(attackDetectionEngine['blockedIPs']),
count: attackDetectionEngine['blockedIPs'].size,
timestamp: new Date().toISOString()
})
})
// Manually block IP
app.post('/api/security/block-ip', (req, res) => {
const { ip, duration = 3600 } = req.body // 1 hour default
if (!ip) {
return res.status(400).json({ error: 'IP address required' })
}
attackDetectionEngine['blockedIPs'].add(ip)
// Auto-unblock after specified duration
setTimeout(() => {
attackDetectionEngine['blockedIPs'].delete(ip)
}, duration * 1000)
res.json({
message: `IP ${ip} blocked for ${duration} seconds`,
timestamp: new Date().toISOString()
})
})
// Subscribe to attack events (WebSocket)
app.ws('/api/security/attack-stream', (ws: any) => {
const unsubscribe = attackDetectionEngine.subscribe((attack) => {
ws.send(JSON.stringify({
type: 'attack_detected',
data: attack,
timestamp: new Date().toISOString()
}))
})
ws.on('close', () => {
unsubscribe()
})
})
// Health check with security status
app.get('/health/security', (req, res) => {
const status = attackDetectionEngine.getAttackStatus()
res.json({
status: status.systemHealth,
activeAttacks: status.totalDetections,
blockedIPs: status.blockedIPs.length,
timestamp: new Date().toISOString()
})
})
console.log('Attack detection engine initialized')DDoS Protection System
// Advanced DDoS protection system with multiple layers of defense
interface DDoSConfig {
rateLimiting: {
requestsPerSecond: number
requestsPerMinute: number
burstLimit: number
}
circuitBreaker: {
failureThreshold: number
recoveryTimeout: number
monitoringPeriod: number
}
trafficShaping: {
queueSize: number
processingDelay: number
priorityLevels: number
}
geographicFiltering: {
allowedCountries: string[]
blockedCountries: string[]
suspiciousRegions: string[]
}
}
interface ProtectionLayer {
name: string
priority: number
enabled: boolean
config: Record<string, any>
intercept: (request: any) => Promise<{ blocked: boolean; reason?: string }>
}
interface MitigationStrategy {
id: string
name: string
type: 'rate_limiting' | 'circuit_breaker' | 'traffic_shaping' | 'geographic_filtering' | 'challenge_response'
trigger: {
metric: string
operator: '>' | '<' | '>=' | '<=' | '=='
threshold: number
}
action: {
type: 'block' | 'delay' | 'redirect' | 'challenge' | 'throttle'
parameters: Record<string, any>
}
cooldown: number
}
class DDoSProtectionSystem {
private protectionLayers: ProtectionLayer[] = []
private mitigationStrategies: MitigationStrategy[] = []
private blockedIPs: Map<string, { reason: string; timestamp: number; expires: number }> = new Map()
private circuitBreakers: Map<string, { failures: number; lastFailure: number; state: 'closed' | 'open' | 'half_open' }> = new Map()
private trafficQueues: Map<string, any[]> = new Map()
private subscribers: Array<(event: any) => void> = []
constructor(private config: DDoSConfig) {
this.initializeProtectionLayers()
this.initializeMitigationStrategies()
this.startCleanupRoutine()
}
// Process request through all protection layers
async processRequest(request: any): Promise<{
allowed: boolean
reason?: string
delay?: number
challenge?: string
modifications?: Record<string, any>
}> {
const result = {
allowed: true,
reason: undefined as string | undefined,
delay: undefined as number | undefined,
challenge: undefined as string | undefined,
modifications: undefined as Record<string, any> | undefined
}
// Process through each protection layer in priority order
for (const layer of this.protectionLayers.sort((a, b) => a.priority - b.priority)) {
if (!layer.enabled) continue
try {
const layerResult = await layer.intercept(request)
if (layerResult.blocked) {
result.allowed = false
result.reason = layerResult.reason || `Blocked by ${layer.name}`
break
}
// Apply layer-specific modifications
if (layer.name === 'traffic_shaping' && layerResult.reason) {
result.delay = parseInt(layerResult.reason)
}
if (layer.name === 'challenge_response' && layerResult.reason) {
result.challenge = layerResult.reason
}
} catch (error) {
console.error(`Error in protection layer ${layer.name}:`, error)
// Continue to next layer even if one fails
}
}
// Apply mitigation strategies if request is suspicious
if (result.allowed && this.isRequestSuspicious(request)) {
const mitigation = await this.applyMitigationStrategies(request)
Object.assign(result, mitigation)
}
return result
}
// Subscribe to DDoS events
subscribe(callback: (event: any) => void): () => void {
this.subscribers.push(callback)
return () => {
const index = this.subscribers.indexOf(callback)
if (index > -1) {
this.subscribers.splice(index, 1)
}
}
}
// Get current protection status
getProtectionStatus(): {
activeLayers: number
blockedIPs: number
circuitBreakerStates: Record<string, string>
trafficQueueSizes: Record<string, number>
systemHealth: 'optimal' | 'stressed' | 'overwhelmed'
} {
const activeLayers = this.protectionLayers.filter(l => l.enabled).length
const blockedIPs = this.blockedIPs.size
const circuitBreakerStates = Object.fromEntries(
Array.from(this.circuitBreakers.entries()).map(([endpoint, state]) => [endpoint, state.state])
)
const trafficQueueSizes = Object.fromEntries(
Array.from(this.trafficQueues.entries()).map(([endpoint, queue]) => [endpoint, queue.length])
)
let systemHealth: 'optimal' | 'stressed' | 'overwhelmed' = 'optimal'
if (blockedIPs > 100) systemHealth = 'stressed'
if (blockedIPs > 1000) systemHealth = 'overwhelmed'
return {
activeLayers,
blockedIPs,
circuitBreakerStates,
trafficQueueSizes,
systemHealth
}
}
private initializeProtectionLayers(): void {
this.protectionLayers = [
{
name: 'rate_limiting',
priority: 1,
enabled: true,
config: this.config.rateLimiting,
intercept: this.rateLimitingInterceptor.bind(this)
},
{
name: 'geographic_filtering',
priority: 2,
enabled: true,
config: this.config.geographicFiltering,
intercept: this.geographicFilteringInterceptor.bind(this)
},
{
name: 'circuit_breaker',
priority: 3,
enabled: true,
config: this.config.circuitBreaker,
intercept: this.circuitBreakerInterceptor.bind(this)
},
{
name: 'traffic_shaping',
priority: 4,
enabled: true,
config: this.config.trafficShaping,
intercept: this.trafficShapingInterceptor.bind(this)
},
{
name: 'challenge_response',
priority: 5,
enabled: false, // Enable only under attack
config: {},
intercept: this.challengeResponseInterceptor.bind(this)
}
]
}
private initializeMitigationStrategies(): void {
this.mitigationStrategies = [
{
id: 'high_rps_mitigation',
name: 'High RPS Mitigation',
type: 'rate_limiting',
trigger: {
metric: 'requestsPerSecond',
operator: '>',
threshold: this.config.rateLimiting.requestsPerSecond
},
action: {
type: 'throttle',
parameters: { delayMs: 1000 }
},
cooldown: 60
},
{
id: 'circuit_breaker_mitigation',
name: 'Circuit Breaker Activation',
type: 'circuit_breaker',
trigger: {
metric: 'errorRate',
operator: '>',
threshold: 0.5
},
action: {
type: 'block',
parameters: { duration: this.config.circuitBreaker.recoveryTimeout }
},
cooldown: 300
},
{
id: 'geographic_mitigation',
name: 'Geographic Traffic Control',
type: 'geographic_filtering',
trigger: {
metric: 'suspiciousTrafficPercentage',
operator: '>',
threshold: 0.3
},
action: {
type: 'redirect',
parameters: { target: '/maintenance' }
},
cooldown: 1800
}
]
}
private async rateLimitingInterceptor(request: any): Promise<{ blocked: boolean; reason?: string }> {
const key = `${request.ip}:${request.endpoint}`
const now = Date.now()
const windowStart = now - 60000 // 1 minute window
// Get or create rate limit tracker for this IP/endpoint
if (!this.trafficQueues.has(key)) {
this.trafficQueues.set(key, [])
}
const requests = this.trafficQueues.get(key)!
const recentRequests = requests.filter(req => req.timestamp > windowStart)
// Check rate limits
if (recentRequests.length >= this.config.rateLimiting.requestsPerMinute) {
return {
blocked: true,
reason: 'Rate limit exceeded'
}
}
// Update request tracking
recentRequests.push({ ...request, timestamp: now })
this.trafficQueues.set(key, recentRequests)
return { blocked: false }
}
private async geographicFilteringInterceptor(request: any): Promise<{ blocked: boolean; reason?: string }> {
// In production, this would use geolocation data
// For demo, we'll simulate based on IP patterns
const ip = request.ip
const blockedCountries = this.config.geographicFiltering.blockedCountries
const allowedCountries = this.config.geographicFiltering.allowedCountries
// Simulate country detection based on IP (simplified)
const simulatedCountry = this.simulateCountryDetection(ip)
if (blockedCountries.includes(simulatedCountry)) {
return {
blocked: true,
reason: `Traffic from ${simulatedCountry} is not allowed`
}
}
if (allowedCountries.length > 0 && !allowedCountries.includes(simulatedCountry)) {
return {
blocked: true,
reason: `Traffic from ${simulatedCountry} is not in allowed countries`
}
}
return { blocked: false }
}
private async circuitBreakerInterceptor(request: any): Promise<{ blocked: boolean; reason?: string }> {
const endpoint = request.endpoint
const breaker = this.circuitBreakers.get(endpoint)
if (!breaker) {
this.circuitBreakers.set(endpoint, {
failures: 0,
lastFailure: 0,
state: 'closed'
})
return { blocked: false }
}
// Check circuit breaker state
if (breaker.state === 'open') {
const timeSinceLastFailure = Date.now() - breaker.lastFailure
if (timeSinceLastFailure > this.config.circuitBreaker.recoveryTimeout) {
// Transition to half-open
breaker.state = 'half_open'
} else {
return {
blocked: true,
reason: 'Circuit breaker is open'
}
}
}
return { blocked: false }
}
private async trafficShapingInterceptor(request: any): Promise<{ blocked: boolean; reason?: string }> {
const key = `${request.ip}:${request.endpoint}`
// Implement traffic shaping queue
if (!this.trafficQueues.has(key)) {
this.trafficQueues.set(key, [])
}
const queue = this.trafficQueues.get(key)!
if (queue.length >= this.config.trafficShaping.queueSize) {
return {
blocked: true,
reason: 'Traffic queue full'
}
}
// Add artificial delay based on queue size
const delay = Math.min(
this.config.trafficShaping.processingDelay,
queue.length * 100 // 100ms per queued request
)
return {
blocked: false,
reason: delay.toString()
}
}
private async challengeResponseInterceptor(request: any): Promise<{ blocked: boolean; reason?: string }> {
// Generate CAPTCHA or other challenge
const challengeId = Math.random().toString(36).substring(2, 15)
return {
blocked: false,
reason: challengeId // Challenge ID to be solved by client
}
}
private isRequestSuspicious(request: any): boolean {
// Check for suspicious patterns
const suspiciousIndicators = [
request.headers['user-agent']?.includes('bot'),
request.headers['user-agent']?.includes('curl'),
request.headers['user-agent']?.includes('wget'),
request.headers['x-forwarded-for'], // Proxy indicator
request.headers['x-real-ip'], // Proxy indicator
!request.headers['accept-language'], // Missing language header
request.headers['cache-control'] === 'no-cache' && request.method === 'GET'
]
return suspiciousIndicators.some(indicator => indicator === true)
}
private async applyMitigationStrategies(request: any): Promise<{
allowed: boolean
delay?: number
challenge?: string
modifications?: Record<string, any>
}> {
const activeMitigations = this.mitigationStrategies.filter(strategy => {
// Check if mitigation trigger conditions are met
return this.evaluateMitigationTrigger(strategy, request)
})
if (activeMitigations.length === 0) {
return { allowed: true }
}
// Apply the most severe mitigation
const primaryMitigation = activeMitigations.sort((a, b) => {
const severityOrder = { 'block': 4, 'redirect': 3, 'challenge': 2, 'throttle': 1, 'delay': 0 }
return severityOrder[b.action.type] - severityOrder[a.action.type]
})[0]
switch (primaryMitigation.action.type) {
case 'block':
return { allowed: false }
case 'delay':
return {
allowed: true,
delay: primaryMitigation.action.parameters.delayMs || 1000
}
case 'challenge':
return {
allowed: true,
challenge: Math.random().toString(36).substring(2, 15)
}
case 'redirect':
return {
allowed: true,
modifications: { redirectTo: primaryMitigation.action.parameters.target }
}
case 'throttle':
return {
allowed: true,
delay: 500 // Throttle delay
}
default:
return { allowed: true }
}
}
private evaluateMitigationTrigger(strategy: MitigationStrategy, request: any): boolean {
// Simplified trigger evaluation - in production, this would check actual metrics
switch (strategy.trigger.metric) {
case 'requestsPerSecond':
return this.getCurrentRPS(request.ip, request.endpoint) > strategy.trigger.threshold
case 'errorRate':
return this.getCurrentErrorRate(request.endpoint) > strategy.trigger.threshold
case 'suspiciousTrafficPercentage':
return this.getSuspiciousTrafficPercentage() > strategy.trigger.threshold
default:
return false
}
}
private getCurrentRPS(ip: string, endpoint: string): number {
const key = `${ip}:${endpoint}`
const requests = this.trafficQueues.get(key) || []
const recentRequests = requests.filter(req => Date.now() - req.timestamp < 1000)
return recentRequests.length
}
private getCurrentErrorRate(endpoint: string): number {
// Simplified error rate calculation
return Math.random() * 0.1 // 0-10% error rate for demo
}
private getSuspiciousTrafficPercentage(): number {
// Calculate percentage of suspicious traffic
return Math.random() * 0.5 // 0-50% for demo
}
private simulateCountryDetection(ip: string): string {
// Simplified country detection based on IP patterns
const ipNum = parseInt(ip.split('.').pop() || '0')
const countries = ['US', 'CN', 'RU', 'DE', 'FR', 'JP', 'KR', 'BR', 'IN', 'CA']
return countries[ipNum % countries.length]
}
private startCleanupRoutine(): void {
// Clean up old data every 5 minutes
setInterval(() => {
this.cleanupOldData()
}, 5 * 60 * 1000)
}
private cleanupOldData(): void {
const fiveMinutesAgo = Date.now() - 5 * 60 * 1000
// Clean up old traffic data
for (const [key, requests] of this.trafficQueues.entries()) {
const recentRequests = requests.filter(req => req.timestamp > fiveMinutesAgo)
if (recentRequests.length === 0) {
this.trafficQueues.delete(key)
} else {
this.trafficQueues.set(key, recentRequests)
}
}
// Clean up expired IP blocks
for (const [ip, block] of this.blockedIPs.entries()) {
if (block.expires < Date.now()) {
this.blockedIPs.delete(ip)
}
}
// Reset circuit breakers if they're stuck
for (const [endpoint, breaker] of this.circuitBreakers.entries()) {
if (breaker.state === 'half_open' && Date.now() - breaker.lastFailure > this.config.circuitBreaker.recoveryTimeout * 2) {
breaker.state = 'closed'
breaker.failures = 0
}
}
}
// Manual control methods
enableProtectionLayer(layerName: string): void {
const layer = this.protectionLayers.find(l => l.name === layerName)
if (layer) {
layer.enabled = true
console.log(`Enabled protection layer: ${layerName}`)
}
}
disableProtectionLayer(layerName: string): void {
const layer = this.protectionLayers.find(l => l.name === layerName)
if (layer) {
layer.enabled = false
console.log(`Disabled protection layer: ${layerName}`)
}
}
blockIP(ip: string, reason: string, duration: number = 3600): void {
this.blockedIPs.set(ip, {
reason,
timestamp: Date.now(),
expires: Date.now() + duration * 1000
})
console.log(`Blocked IP ${ip} for ${reason}`)
}
unblockIP(ip: string): void {
this.blockedIPs.delete(ip)
console.log(`Unblocked IP ${ip}`)
}
}
// Integration with Express.js
const ddosProtection = new DDoSProtectionSystem({
rateLimiting: {
requestsPerSecond: 50,
requestsPerMinute: 1000,
burstLimit: 100
},
circuitBreaker: {
failureThreshold: 5,
recoveryTimeout: 60000, // 1 minute
monitoringPeriod: 300000 // 5 minutes
},
trafficShaping: {
queueSize: 1000,
processingDelay: 100,
priorityLevels: 3
},
geographicFiltering: {
allowedCountries: [], // Empty = allow all
blockedCountries: ['CN', 'RU', 'KP'], // Block high-risk countries
suspiciousRegions: ['APAC', 'EASTERN_EUROPE']
}
})
// Enhanced middleware combining attack detection and DDoS protection
const comprehensiveSecurityMiddleware = async (req: any, res: any, next: any) => {
try {
// First, run attack detection
const attackAnalysis = await attackDetectionEngine.analyzeRequest({
ip: req.ip,
endpoint: req.path,
method: req.method,
userAgent: req.get('User-Agent'),
headers: req.headers,
body: JSON.stringify(req.body)
})
req.attackAnalysis = attackAnalysis
// Check if IP is blocked by DDoS protection
if (ddosProtection['blockedIPs'].has(req.ip)) {
const blockInfo = ddosProtection['blockedIPs'].get(req.ip)
return res.status(403).json({
error: 'Forbidden',
message: `IP blocked: ${blockInfo?.reason}`,
retryAfter: Math.ceil((blockInfo?.expires - Date.now()) / 1000)
})
}
// Run DDoS protection layers
const protectionResult = await ddosProtection.processRequest({
ip: req.ip,
endpoint: req.path,
method: req.method,
headers: req.headers,
timestamp: Date.now()
})
if (!protectionResult.allowed) {
return res.status(429).json({
error: 'Too Many Requests',
message: protectionResult.reason || 'Request blocked by DDoS protection',
retryAfter: 3600
})
}
// Apply delays if required
if (protectionResult.delay) {
await new Promise(resolve => setTimeout(resolve, protectionResult.delay))
}
// Apply modifications
if (protectionResult.modifications) {
Object.assign(req.headers, protectionResult.modifications)
}
// Set security headers
if (attackAnalysis.isAttack || !protectionResult.allowed) {
res.set('X-Threat-Level', 'high')
res.set('X-Risk-Score', attackAnalysis.riskScore.toString())
}
// Add challenge if required
if (protectionResult.challenge) {
res.set('X-Challenge-Required', protectionResult.challenge)
}
} catch (error) {
console.error('Security middleware error:', error)
// Continue processing even if security middleware fails
}
next()
}
// API endpoints for DDoS management
app.use('/api', comprehensiveSecurityMiddleware)
// Get DDoS protection status
app.get('/api/security/ddos-status', (req, res) => {
const status = ddosProtection.getProtectionStatus()
res.json({
...status,
timestamp: new Date().toISOString()
})
})
// Get active protection layers
app.get('/api/security/protection-layers', (req, res) => {
const layers = ddosProtection['protectionLayers'].map(layer => ({
name: layer.name,
priority: layer.priority,
enabled: layer.enabled,
config: layer.config
}))
res.json({
layers,
timestamp: new Date().toISOString()
})
})
// Enable/disable protection layer
app.post('/api/security/protection-layer/:name', (req, res) => {
const { enabled } = req.body
const layerName = req.params.name
if (enabled) {
ddosProtection.enableProtectionLayer(layerName)
} else {
ddosProtection.disableProtectionLayer(layerName)
}
res.json({
message: `Protection layer ${layerName} ${enabled ? 'enabled' : 'disabled'}`,
timestamp: new Date().toISOString()
})
})
// Get blocked IPs (DDoS protection)
app.get('/api/security/ddos-blocked-ips', (req, res) => {
const blockedIPs = Array.from(ddosProtection['blockedIPs'].entries()).map(([ip, info]) => ({
ip,
reason: info.reason,
blockedAt: new Date(info.timestamp).toISOString(),
expiresAt: new Date(info.expires).toISOString(),
remainingTime: Math.ceil((info.expires - Date.now()) / 1000)
}))
res.json({
blockedIPs,
count: blockedIPs.length,
timestamp: new Date().toISOString()
})
})
// Manual IP block for DDoS protection
app.post('/api/security/ddos-block-ip', (req, res) => {
const { ip, reason = 'Manual block', duration = 3600 } = req.body
if (!ip) {
return res.status(400).json({ error: 'IP address required' })
}
ddosProtection.blockIP(ip, reason, duration)
res.json({
message: `IP ${ip} blocked for DDoS protection`,
duration,
reason,
timestamp: new Date().toISOString()
})
})
// Subscribe to DDoS events
app.ws('/api/security/ddos-stream', (ws: any) => {
const unsubscribe = ddosProtection.subscribe((event) => {
ws.send(JSON.stringify({
type: 'ddos_event',
data: event,
timestamp: new Date().toISOString()
}))
})
ws.on('close', () => {
unsubscribe()
})
})
// Combined health check
app.get('/health/comprehensive', (req, res) => {
const attackStatus = attackDetectionEngine.getAttackStatus()
const ddosStatus = ddosProtection.getProtectionStatus()
let overallStatus: 'healthy' | 'degraded' | 'unhealthy' = 'healthy'
if (attackStatus.systemHealth === 'compromised' || ddosStatus.systemHealth === 'overwhelmed') {
overallStatus = 'unhealthy'
} else if (attackStatus.systemHealth === 'under_attack' || ddosStatus.systemHealth === 'stressed') {
overallStatus = 'degraded'
}
res.json({
status: overallStatus,
attack: {
systemHealth: attackStatus.systemHealth,
activeDetections: attackStatus.totalDetections,
blockedIPs: attackStatus.blockedIPs.length
},
ddos: {
systemHealth: ddosStatus.systemHealth,
blockedIPs: ddosStatus.blockedIPs,
activeLayers: ddosStatus.activeLayers
},
timestamp: new Date().toISOString()
})
})
console.log('DDoS protection system initialized')Performance Monitoring Under Attack
// Advanced performance monitoring system designed for attack scenarios
interface AttackMetrics {
timestamp: number
attackType: string
severity: string
affectedEndpoints: string[]
trafficVolume: number
responseTimeImpact: number
errorRateIncrease: number
resourceUtilization: {
cpu: number
memory: number
disk: number
network: number
}
mitigationEffectiveness: number
}
interface PerformanceBaseline {
endpoint: string
method: string
baselineMetrics: {
averageResponseTime: number
p95ResponseTime: number
requestsPerSecond: number
errorRate: number
throughput: number
}
confidence: number
lastUpdated: number
}
interface AnomalyDetection {
id: string
type: 'performance_degradation' | 'traffic_spike' | 'error_rate_increase' | 'resource_exhaustion'
severity: 'low' | 'medium' | 'high' | 'critical'
confidence: number
affectedComponents: string[]
expectedDuration: number
recommendedActions: string[]
timestamp: number
}
class AttackPerformanceMonitor {
private performanceBaselines: Map<string, PerformanceBaseline> = new Map()
private attackMetrics: AttackMetrics[] = []
private anomalyDetectors: AnomalyDetection[] = []
private performanceHistory: Map<string, any[]> = new Map()
private alertThresholds: Map<string, number> = new Map()
private subscribers: Array<(event: any) => void> = []
constructor() {
this.initializeBaselines()
this.initializeAlertThresholds()
this.startPerformanceMonitoring()
}
// Record performance metrics during attack
recordAttackMetrics(metrics: Omit<AttackMetrics, 'timestamp'>): void {
const attackMetric: AttackMetrics = {
...metrics,
timestamp: Date.now()
}
this.attackMetrics.push(attackMetric)
// Keep only last 24 hours of attack metrics
const twentyFourHoursAgo = Date.now() - 24 * 60 * 60 * 1000
this.attackMetrics = this.attackMetrics.filter(m => m.timestamp > twentyFourHoursAgo)
// Analyze for anomalies
this.detectPerformanceAnomalies(attackMetric)
// Notify subscribers
this.subscribers.forEach(callback => {
try {
callback({
type: 'attack_metrics',
data: attackMetric,
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('Error in attack performance subscriber:', error)
}
})
}
// Subscribe to performance monitoring events
subscribe(callback: (event: any) => void): () => void {
this.subscribers.push(callback)
return () => {
const index = this.subscribers.indexOf(callback)
if (index > -1) {
this.subscribers.splice(index, 1)
}
}
}
// Get current performance status under attack
getPerformanceStatus(): {
overallHealth: 'excellent' | 'good' | 'degraded' | 'critical'
activeAnomalies: number
performanceImpact: {
responseTimeIncrease: number
errorRateIncrease: number
throughputReduction: number
}
resourceUtilization: {
cpu: number
memory: number
disk: number
network: number
}
mitigationEffectiveness: number
recommendations: string[]
} {
const recentMetrics = this.attackMetrics.slice(-10) // Last 10 attack metrics
if (recentMetrics.length === 0) {
return {
overallHealth: 'excellent',
activeAnomalies: 0,
performanceImpact: {
responseTimeIncrease: 0,
errorRateIncrease: 0,
throughputReduction: 0
},
resourceUtilization: {
cpu: 0,
memory: 0,
disk: 0,
network: 0
},
mitigationEffectiveness: 100,
recommendations: []
}
}
const avgResponseTimeImpact = recentMetrics.reduce((sum, m) => sum + m.responseTimeImpact, 0) / recentMetrics.length
const avgErrorRateIncrease = recentMetrics.reduce((sum, m) => sum + m.errorRateIncrease, 0) / recentMetrics.length
const avgResourceUtilization = this.calculateAverageResourceUtilization(recentMetrics)
let overallHealth: 'excellent' | 'good' | 'degraded' | 'critical' = 'excellent'
if (avgResponseTimeImpact > 200 || avgErrorRateIncrease > 0.3) overallHealth = 'critical'
else if (avgResponseTimeImpact > 100 || avgErrorRateIncrease > 0.1) overallHealth = 'degraded'
else if (avgResponseTimeImpact > 50 || avgErrorRateIncrease > 0.05) overallHealth = 'good'
const activeAnomalies = this.anomalyDetectors.filter(a =>
a.timestamp > Date.now() - 5 * 60 * 1000 // Last 5 minutes
).length
const avgMitigationEffectiveness = recentMetrics.reduce((sum, m) => sum + m.mitigationEffectiveness, 0) / recentMetrics.length
return {
overallHealth,
activeAnomalies,
performanceImpact: {
responseTimeIncrease: avgResponseTimeImpact,
errorRateIncrease: avgErrorRateIncrease,
throughputReduction: recentMetrics.reduce((sum, m) => sum + (m.trafficVolume / 1000), 0) / recentMetrics.length
},
resourceUtilization: avgResourceUtilization,
mitigationEffectiveness: avgMitigationEffectiveness,
recommendations: this.generatePerformanceRecommendations(overallHealth, activeAnomalies)
}
}
// Get detailed performance analysis
getDetailedAnalysis(timeframe: number = 3600000): {
baselineComparison: Record<string, any>
trendAnalysis: Record<string, any>
bottleneckIdentification: string[]
capacityPlanning: Record<string, any>
} {
const cutoff = Date.now() - timeframe
return {
baselineComparison: this.compareWithBaseline(cutoff),
trendAnalysis: this.analyzePerformanceTrends(cutoff),
bottleneckIdentification: this.identifyBottlenecks(cutoff),
capacityPlanning: this.calculateCapacityNeeds(cutoff)
}
}
private initializeBaselines(): void {
// Initialize performance baselines for common endpoints
const commonEndpoints = [
{ endpoint: '/api/users', method: 'GET' },
{ endpoint: '/api/users', method: 'POST' },
{ endpoint: '/api/auth', method: 'POST' },
{ endpoint: '/api/data', method: 'GET' }
]
commonEndpoints.forEach(({ endpoint, method }) => {
const key = `${method}:${endpoint}`
this.performanceBaselines.set(key, {
endpoint,
method,
baselineMetrics: {
averageResponseTime: 150, // 150ms baseline
p95ResponseTime: 300, // 300ms P95
requestsPerSecond: 100, // 100 RPS baseline
errorRate: 0.01, // 1% error rate
throughput: 1000 // 1000 requests per 10 seconds
},
confidence: 0.95,
lastUpdated: Date.now()
})
})
}
private initializeAlertThresholds(): void {
this.alertThresholds.set('response_time_degradation', 200) // 200% increase
this.alertThresholds.set('error_rate_spike', 0.2) // 20% error rate
this.alertThresholds.set('traffic_anomaly', 500) // 500% traffic increase
this.alertThresholds.set('resource_exhaustion', 90) // 90% resource usage
this.alertThresholds.set('mitigation_failure', 30) // <30% effectiveness
}
private detectPerformanceAnomalies(attackMetric: AttackMetrics): void {
const anomalies: AnomalyDetection[] = []
// Detect response time degradation
if (attackMetric.responseTimeImpact > this.alertThresholds.get('response_time_degradation')!) {
anomalies.push({
id: `response_time_${Date.now()}`,
type: 'performance_degradation',
severity: attackMetric.responseTimeImpact > 500 ? 'critical' : 'high',
confidence: Math.min(100, attackMetric.responseTimeImpact / 5),
affectedComponents: attackMetric.affectedEndpoints,
expectedDuration: Math.min(3600, attackMetric.responseTimeImpact / 10), // Max 1 hour
recommendedActions: [
'Scale up compute resources',
'Enable response caching',
'Implement request prioritization',
'Activate circuit breakers'
],
timestamp: Date.now()
})
}
// Detect error rate spikes
if (attackMetric.errorRateIncrease > this.alertThresholds.get('error_rate_spike')!) {
anomalies.push({
id: `error_rate_${Date.now()}`,
type: 'error_rate_increase',
severity: attackMetric.errorRateIncrease > 0.5 ? 'critical' : 'high',
confidence: Math.min(100, attackMetric.errorRateIncrease * 200),
affectedComponents: attackMetric.affectedEndpoints,
expectedDuration: Math.min(1800, attackMetric.errorRateIncrease * 100), // Max 30 minutes
recommendedActions: [
'Check application logs',
'Review recent deployments',
'Enable enhanced error handling',
'Implement graceful degradation'
],
timestamp: Date.now()
})
}
// Detect resource exhaustion
const maxResourceUtilization = Math.max(
attackMetric.resourceUtilization.cpu,
attackMetric.resourceUtilization.memory,
attackMetric.resourceUtilization.disk,
attackMetric.resourceUtilization.network
)
if (maxResourceUtilization > this.alertThresholds.get('resource_exhaustion')!) {
anomalies.push({
id: `resource_${Date.now()}`,
type: 'resource_exhaustion',
severity: maxResourceUtilization > 95 ? 'critical' : 'high',
confidence: Math.min(100, maxResourceUtilization),
affectedComponents: Object.entries(attackMetric.resourceUtilization)
.filter(([_, value]) => value > 80)
.map(([component, _]) => component),
expectedDuration: Math.min(7200, maxResourceUtilization * 10), // Max 2 hours
recommendedActions: [
'Scale infrastructure horizontally',
'Implement resource quotas',
'Enable auto-scaling policies',
'Optimize resource allocation'
],
timestamp: Date.now()
})
}
this.anomalyDetectors.push(...anomalies)
// Clean up old anomalies (older than 1 hour)
const oneHourAgo = Date.now() - 60 * 60 * 1000
this.anomalyDetectors = this.anomalyDetectors.filter(a => a.timestamp > oneHourAgo)
}
private calculateAverageResourceUtilization(metrics: AttackMetrics[]): {
cpu: number
memory: number
disk: number
network: number
} {
if (metrics.length === 0) {
return { cpu: 0, memory: 0, disk: 0, network: 0 }
}
return {
cpu: metrics.reduce((sum, m) => sum + m.resourceUtilization.cpu, 0) / metrics.length,
memory: metrics.reduce((sum, m) => sum + m.resourceUtilization.memory, 0) / metrics.length,
disk: metrics.reduce((sum, m) => sum + m.resourceUtilization.disk, 0) / metrics.length,
network: metrics.reduce((sum, m) => sum + m.resourceUtilization.network, 0) / metrics.length
}
}
private generatePerformanceRecommendations(health: string, activeAnomalies: number): string[] {
const recommendations: string[] = []
if (health === 'critical' || activeAnomalies > 5) {
recommendations.push('Activate emergency scaling procedures')
recommendations.push('Enable all protection layers')
recommendations.push('Consider traffic rerouting')
}
if (health === 'degraded' || activeAnomalies > 2) {
recommendations.push('Monitor resource utilization closely')
recommendations.push('Prepare additional capacity')
recommendations.push('Review mitigation strategies')
}
if (activeAnomalies === 0 && health === 'excellent') {
recommendations.push('System performing optimally')
recommendations.push('Consider reducing protection layers if appropriate')
}
return recommendations
}
private compareWithBaseline(cutoff: number): Record<string, any> {
const baselineComparison: Record<string, any> = {}
for (const [key, baseline] of this.performanceBaselines.entries()) {
const recentPerformance = this.getRecentPerformance(key, cutoff)
if (recentPerformance) {
baselineComparison[key] = {
baseline: baseline.baselineMetrics,
current: recentPerformance,
deviation: this.calculateDeviation(baseline.baselineMetrics, recentPerformance),
trend: this.calculateTrend(key, cutoff)
}
}
}
return baselineComparison
}
private analyzePerformanceTrends(cutoff: number): Record<string, any> {
const trends: Record<string, any> = {}
for (const [key, baseline] of this.performanceBaselines.entries()) {
trends[key] = {
trend: this.calculateTrend(key, cutoff),
volatility: this.calculateVolatility(key, cutoff),
seasonality: this.detectSeasonality(key, cutoff)
}
}
return trends
}
private identifyBottlenecks(cutoff: number): string[] {
const bottlenecks: string[] = []
// Analyze resource utilization patterns
const recentMetrics = this.attackMetrics.filter(m => m.timestamp > cutoff)
if (recentMetrics.length === 0) return bottlenecks
const avgCPU = recentMetrics.reduce((sum, m) => sum + m.resourceUtilization.cpu, 0) / recentMetrics.length
const avgMemory = recentMetrics.reduce((sum, m) => sum + m.resourceUtilization.memory, 0) / recentMetrics.length
const avgResponseTime = recentMetrics.reduce((sum, m) => sum + m.responseTimeImpact, 0) / recentMetrics.length
if (avgCPU > 80) bottlenecks.push('High CPU utilization')
if (avgMemory > 85) bottlenecks.push('High memory utilization')
if (avgResponseTime > 1000) bottlenecks.push('Slow response times')
// Check for common attack-related bottlenecks
const highTrafficEndpoints = recentMetrics
.filter(m => m.trafficVolume > 10000)
.map(m => m.affectedEndpoints)
.flat()
if (highTrafficEndpoints.length > 0) {
bottlenecks.push('High traffic on specific endpoints')
}
return bottlenecks
}
private calculateCapacityNeeds(cutoff: number): Record<string, any> {
const recentMetrics = this.attackMetrics.filter(m => m.timestamp > cutoff)
if (recentMetrics.length === 0) {
return { recommendedScaling: 0, capacityBuffer: 20 }
}
const peakTraffic = Math.max(...recentMetrics.map(m => m.trafficVolume))
const avgTraffic = recentMetrics.reduce((sum, m) => sum + m.trafficVolume, 0) / recentMetrics.length
// Recommend 50% buffer above peak traffic
const recommendedCapacity = Math.ceil(peakTraffic * 1.5 / 1000) * 1000 // Round to nearest 1000
const capacityBuffer = Math.round(((recommendedCapacity - avgTraffic) / avgTraffic) * 100)
return {
currentAverage: Math.round(avgTraffic),
peakObserved: peakTraffic,
recommendedCapacity,
capacityBuffer,
scalingRecommendation: recommendedCapacity > avgTraffic * 1.2 ? 'Scale up' : 'Maintain current'
}
}
private getRecentPerformance(key: string, cutoff: number): any {
const performanceData = this.performanceHistory.get(key) || []
const recentData = performanceData.filter(d => d.timestamp > cutoff)
if (recentData.length === 0) return null
return {
averageResponseTime: recentData.reduce((sum, d) => sum + d.responseTime, 0) / recentData.length,
p95ResponseTime: this.calculatePercentile(recentData.map(d => d.responseTime), 95),
requestsPerSecond: recentData.length / ((recentData[recentData.length - 1].timestamp - recentData[0].timestamp) / 1000),
errorRate: recentData.filter(d => d.statusCode >= 400).length / recentData.length,
throughput: recentData.length
}
}
private calculateDeviation(baseline: any, current: any): Record<string, number> {
return {
responseTimeDeviation: ((current.averageResponseTime - baseline.averageResponseTime) / baseline.averageResponseTime) * 100,
throughputDeviation: ((current.requestsPerSecond - baseline.requestsPerSecond) / baseline.requestsPerSecond) * 100,
errorRateDeviation: ((current.errorRate - baseline.errorRate) / baseline.errorRate) * 100
}
}
private calculateTrend(key: string, cutoff: number): 'improving' | 'stable' | 'degrading' {
const performanceData = this.performanceHistory.get(key) || []
const recentData = performanceData.filter(d => d.timestamp > cutoff)
if (recentData.length < 10) return 'stable'
// Simple linear regression for trend calculation
const values = recentData.map(d => d.responseTime)
const trend = this.calculateLinearTrend(values)
if (trend < -0.1) return 'improving'
if (trend > 0.1) return 'degrading'
return 'stable'
}
private calculateVolatility(key: string, cutoff: number): number {
const performanceData = this.performanceHistory.get(key) || []
const recentData = performanceData.filter(d => d.timestamp > cutoff)
if (recentData.length < 5) return 0
const responseTimes = recentData.map(d => d.responseTime)
const mean = responseTimes.reduce((a, b) => a + b, 0) / responseTimes.length
const variance = responseTimes.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0) / responseTimes.length
return Math.sqrt(variance) / mean // Coefficient of variation
}
private detectSeasonality(key: string, cutoff: number): boolean {
// Simplified seasonality detection - in production, use more sophisticated algorithms
const performanceData = this.performanceHistory.get(key) || []
const recentData = performanceData.filter(d => d.timestamp > cutoff)
// Look for repeating patterns in hourly data
const hourlyPatterns = new Map<number, number[]>()
recentData.forEach(d => {
const hour = new Date(d.timestamp).getHours()
if (!hourlyPatterns.has(hour)) {
hourlyPatterns.set(hour, [])
}
hourlyPatterns.get(hour)!.push(d.responseTime)
})
// Check if there's significant variance between hours
const hourlyAverages = Array.from(hourlyPatterns.entries()).map(([hour, times]) =>
times.reduce((a, b) => a + b, 0) / times.length
)
if (hourlyAverages.length < 4) return false
const overallAvg = hourlyAverages.reduce((a, b) => a + b, 0) / hourlyAverages.length
const maxDeviation = Math.max(...hourlyAverages.map(avg => Math.abs(avg - overallAvg)))
return maxDeviation / overallAvg > 0.3 // 30% deviation indicates seasonality
}
private calculateLinearTrend(values: number[]): number {
if (values.length < 3) return 0
let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0
const n = values.length
for (let i = 0; i < n; i++) {
sumX += i
sumY += values[i]
sumXY += i * values[i]
sumXX += i * i
}
return (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX)
}
private calculatePercentile(values: number[], percentile: number): number {
const sorted = [...values].sort((a, b) => a - b)
const index = (percentile / 100) * (sorted.length - 1)
if (Number.isInteger(index)) {
return sorted[index]
}
const lower = Math.floor(index)
const upper = Math.ceil(index)
return sorted[lower] + (sorted[upper] - sorted[lower]) * (index - lower)
}
private startPerformanceMonitoring(): void {
// Collect performance metrics every 30 seconds
setInterval(() => {
this.collectSystemPerformance()
}, 30000)
// Analyze for trends every 5 minutes
setInterval(() => {
this.analyzePerformanceTrends(Date.now() - 5 * 60 * 1000)
}, 5 * 60 * 1000)
}
private collectSystemPerformance(): void {
// In production, this would collect actual system metrics
// For demo, we'll simulate attack scenario metrics
const simulatedAttackMetrics: AttackMetrics = {
timestamp: Date.now(),
attackType: 'ddos',
severity: 'high',
affectedEndpoints: ['/api/users', '/api/auth'],
trafficVolume: Math.random() * 5000 + 1000, // 1000-6000 RPS
responseTimeImpact: Math.random() * 300 + 100, // 100-400ms increase
errorRateIncrease: Math.random() * 0.2 + 0.05, // 5-25% increase
resourceUtilization: {
cpu: Math.random() * 40 + 60, // 60-100% CPU
memory: Math.random() * 30 + 70, // 70-100% Memory
disk: Math.random() * 20 + 20, // 20-40% Disk
network: Math.random() * 50 + 50 // 50-100% Network
},
mitigationEffectiveness: Math.random() * 40 + 60 // 60-100% effective
}
this.recordAttackMetrics(simulatedAttackMetrics)
}
}
// Initialize attack performance monitoring
const attackPerformanceMonitor = new AttackPerformanceMonitor()
// Enhanced middleware with performance monitoring
const enhancedSecurityMiddleware = async (req: any, res: any, next: any) => {
const startTime = Date.now()
// Store start time for response time calculation
req.startTime = startTime
try {
// Run existing security middleware
await comprehensiveSecurityMiddleware(req, res, async () => {
// Continue to performance monitoring
const responseTime = Date.now() - startTime
const statusCode = res.statusCode
// Record performance metrics
attackPerformanceMonitor.recordAttackMetrics({
attackType: req.attackAnalysis?.isAttack ? 'active' : 'none',
severity: req.attackAnalysis?.riskScore > 80 ? 'high' : 'low',
affectedEndpoints: [req.path],
trafficVolume: 1, // Individual request
responseTimeImpact: responseTime - 150, // Deviation from 150ms baseline
errorRateIncrease: statusCode >= 400 ? 1 : 0,
resourceUtilization: {
cpu: Math.random() * 20 + 40, // Simulate 40-60% CPU usage
memory: Math.random() * 20 + 50, // Simulate 50-70% memory usage
disk: Math.random() * 10 + 10, // Simulate 10-20% disk usage
network: Math.random() * 30 + 30 // Simulate 30-60% network usage
},
mitigationEffectiveness: req.attackAnalysis?.isAttack ? 80 : 100
})
next()
})
} catch (error) {
console.error('Enhanced security middleware error:', error)
next()
}
}
// API endpoints for performance monitoring under attack
app.use('/api', enhancedSecurityMiddleware)
// Get current performance status
app.get('/api/performance/attack-status', (req, res) => {
const status = attackPerformanceMonitor.getPerformanceStatus()
res.json({
...status,
timestamp: new Date().toISOString()
})
})
// Get detailed performance analysis
app.get('/api/performance/detailed-analysis', (req, res) => {
const timeframe = parseInt(req.query.timeframe as string) || 3600000 // 1 hour default
const analysis = attackPerformanceMonitor.getDetailedAnalysis(timeframe)
res.json({
...analysis,
timeframe,
timestamp: new Date().toISOString()
})
})
// Get active anomalies
app.get('/api/performance/anomalies', (req, res) => {
const activeAnomalies = attackPerformanceMonitor['anomalyDetectors'].filter(a =>
a.timestamp > Date.now() - 10 * 60 * 1000 // Last 10 minutes
)
res.json({
anomalies: activeAnomalies,
count: activeAnomalies.length,
timestamp: new Date().toISOString()
})
})
// Get performance baselines
app.get('/api/performance/baselines', (req, res) => {
const baselines = Array.from(attackPerformanceMonitor['performanceBaselines'].entries()).map(([key, baseline]) => ({
endpoint: baseline.endpoint,
method: baseline.method,
metrics: baseline.baselineMetrics,
confidence: baseline.confidence,
lastUpdated: new Date(baseline.lastUpdated).toISOString()
}))
res.json({
baselines,
count: baselines.length,
timestamp: new Date().toISOString()
})
})
// Subscribe to performance monitoring events
app.ws('/api/performance/attack-stream', (ws: any) => {
const unsubscribe = attackPerformanceMonitor.subscribe((event) => {
ws.send(JSON.stringify({
type: 'performance_event',
data: event,
timestamp: new Date().toISOString()
}))
})
ws.on('close', () => {
unsubscribe()
})
})
// Comprehensive attack and performance dashboard
app.get('/api/dashboard/comprehensive', (req, res) => {
const attackStatus = attackDetectionEngine.getAttackStatus()
const ddosStatus = ddosProtection.getProtectionStatus()
const performanceStatus = attackPerformanceMonitor.getPerformanceStatus()
res.json({
attack: {
systemHealth: attackStatus.systemHealth,
activeDetections: attackStatus.totalDetections,
blockedIPs: attackStatus.blockedIPs.length
},
ddos: {
systemHealth: ddosStatus.systemHealth,
blockedIPs: ddosStatus.blockedIPs,
activeLayers: ddosStatus.activeLayers
},
performance: {
overallHealth: performanceStatus.overallHealth,
activeAnomalies: performanceStatus.activeAnomalies,
performanceImpact: performanceStatus.performanceImpact,
resourceUtilization: performanceStatus.resourceUtilization
},
recommendations: [
...performanceStatus.recommendations,
...(attackStatus.systemHealth === 'compromised' ? ['Immediate action required for attack mitigation'] : []),
...(ddosStatus.systemHealth === 'overwhelmed' ? ['DDoS protection overwhelmed - consider external assistance'] : [])
],
timestamp: new Date().toISOString()
})
})
console.log('Attack performance monitoring system initialized')Security Threat Landscape
API Performance Under Attack requires careful consideration of multiple factors that impact implementation success and user experience.
Key Considerations
Technical Requirements
- Scalable architecture design
- Performance optimization strategies
- Error handling and recovery
- Security and compliance measures
Business Impact
- User experience enhancement
- Operational efficiency gains
- Cost optimization opportunities
- Risk mitigation strategies
Protection Mechanisms
Successful implementation requires understanding the technical landscape and choosing appropriate strategies.
Implementation Approaches
Modern Solutions
- Cloud-native architectures
- Microservices integration
- Real-time processing capabilities
- Automated scaling mechanisms
API Performance Under Attack Architecture
Implementation Strategies {#implementation-strategies}
Deploy layered defense for attack resilience.
class AttackResilientAPI {
private ddosProtection: DDoSProtectionSystem
private attackDetector: AttackDetectionEngine
constructor() {
this.ddosProtection = new DDoSProtectionSystem()
this.attackDetector = new AttackDetectionEngine()
}
async handleRequest(req: any, res: any, next: any): Promise<void> {
// Layer 1: DDoS protection
const ddosCheck = await this.ddosProtection.checkRequest(req.ip, req.path)
if (!ddosCheck.allowed) {
return res.status(429).json({ error: 'Rate limit exceeded' })
}
// Layer 2: Attack detection
const attackCheck = await this.attackDetector.analyzeRequest(req)
if (attackCheck.isAttack && attackCheck.confidence > 80) {
return res.status(403).json({ error: 'Suspicious activity detected' })
}
// Continue to normal processing
next()
}
}Monitoring and Detection {#monitoring-and-detection}
Real-time attack monitoring and alerting.
Critical Signals:
- Request rate spikes (>5x baseline)
- Error rate increases (>10%)
- Geographic anomalies (unusual countries)
- User-agent patterns (bot signatures)
- Sequential IP ranges (botnets)
Incident Response Planning {#incident-response-planning}
Automated response to detected attacks.
interface AttackResponse {
action: 'monitor' | 'throttle' | 'block' | 'challenge'
duration: number
escalate: boolean
}
const ATTACK_PLAYBOOKS: Record<string, AttackResponse> = {
'ddos_volumetric': {
action: 'block',
duration: 3600,
escalate: true
},
'credential_stuffing': {
action: 'challenge',
duration: 1800,
escalate: false
},
'api_scraping': {
action: 'throttle',
duration: 7200,
escalate: false
}
}Compliance and Best Practices {#compliance-and-best-practices}
Maintain service quality during attacks.
Best Practices:
- Implement progressive rate limiting
- Use CDN and edge protection
- Maintain attack response playbooks
- Regular DDoS simulation testing
- Capacity planning for attack scenarios
Conclusion {#conclusion}
Maintaining API performance under attack requires layered defense, real-time detection, automated mitigation, and capacity planning. Success depends on combining DDoS protection, attack pattern recognition, intelligent throttling, and graceful degradation.
Key success factors include implementing multi-layer protection, detecting attacks early through behavioral analysis, automating response actions, maintaining excess capacity for attacks, and having clear escalation procedures.
Protect your APIs from attacks with our comprehensive security solutions, designed to detect and mitigate threats while maintaining service availability and performance.