Distributed Denial Of Service in Feathersjs
How Distributed Denial Of Service Manifests in Feathersjs
Distributed Denial of Service (DDoS) attacks in Feathersjs applications typically exploit the framework's real-time capabilities and service architecture. The most common vectors target Feathersjs's Socket.io integration and service hooks, overwhelming the event loop with legitimate-looking requests that consume server resources.
Socket.io connections are particularly vulnerable because Feathersjs maintains persistent connections by default. An attacker can establish thousands of concurrent WebSocket connections, each consuming memory and event loop time. The framework's default configuration allows unlimited connections without rate limiting, making it trivial for attackers to exhaust server resources.
Service hooks create another attack surface. Feathersjs executes all hooks registered on a service for every request, and complex hook chains can introduce significant latency. When attackers flood services with requests, the accumulated hook execution time multiplies, causing request queues to grow and eventually crash the Node.js process. This is especially problematic for services with database operations in hooks, as connection pools can be exhausted.
Real-time events amplify DDoS impact in Feathersjs. When a service emits events through app.channel, every connected client receives the data. A single malicious client can trigger events that propagate to all users, creating a broadcast amplification effect. Combined with the framework's default broadcast behavior, this can quickly saturate network bandwidth and CPU resources.
Authentication endpoints are prime DDoS targets. Feathersjs's default authentication strategy processes every login attempt through bcrypt or similar hashing algorithms, which are intentionally CPU-intensive. Attackers can exploit this by sending massive numbers of authentication requests, forcing the server to perform expensive cryptographic operations and potentially causing CPU throttling or crashes.
The framework's flexible service architecture allows custom methods that may contain infinite loops or blocking operations. Without proper input validation and timeout handling, these methods can hang indefinitely under attack, consuming resources until the process becomes unresponsive.
Feathersjs-Specific Detection
Detecting DDoS attacks in Feathersjs requires monitoring both application-level metrics and network traffic patterns. The framework's built-in logging provides basic request counting, but comprehensive detection needs additional instrumentation.
Socket.io connection monitoring is critical. Track concurrent connection counts using Socket.io's nsps namespace statistics. Set thresholds for maximum allowed connections per IP address or user agent. Feathersjs doesn't provide this natively, so implement middleware that tracks connection metadata and enforces limits.
Service request rate limiting should be implemented at the Feathersjs service level. Create a middleware that tracks requests per endpoint, per user, and per IP address. Use sliding window algorithms rather than simple counters to handle burst traffic more effectively. The express-rate-limit package works well with Feathersjs's Express integration.
Monitor hook execution times using Feathersjs's app.hooks system. Add timing hooks that log execution duration for each service method. Set up alerts when hook chains exceed typical execution times, indicating potential resource exhaustion attacks.
CPU and memory monitoring is essential for DDoS detection. Use Node.js's process API to track heap usage and event loop lag. Implement health check endpoints that report current resource utilization. When memory usage exceeds 80% or event loop lag exceeds 100ms, trigger defensive measures.
middleBrick's API security scanning can detect DDoS vulnerabilities in Feathersjs applications without requiring credentials or code access. The scanner tests for missing rate limiting on authentication endpoints, excessive socket.io connection allowances, and unprotected service methods. It identifies configuration weaknesses that make DDoS attacks more likely to succeed.
Network-level detection complements application monitoring. Use reverse proxies like Nginx or Cloudflare to identify and block traffic patterns characteristic of DDoS attacks. Look for sudden traffic spikes, unusual geographic distribution, or requests from known bad IP ranges.
Log analysis is crucial for post-attack forensics. Feathersjs's structured logging makes it easier to correlate attack patterns with specific services or endpoints. Track failed authentication attempts, connection establishment failures, and service method timeouts to identify attack signatures.
Feathersjs-Specific Remediation
Implementing DDoS protection in Feathersjs requires a multi-layered approach combining application-level defenses with infrastructure hardening. Start with Socket.io configuration to limit connection abuse.
// src/middleware/socketio.js
const socketio = require('socket.io');
const io = socketio(server, {
maxHttpBufferSize: 1e6, // limit message size
pingTimeout: 60000,
pingInterval: 25000,
perMessageDeflate: false
});
// Connection rate limiting
const connectionTracker = new Map();
io.use((socket, next) => {
const ip = socket.handshake.address;
const count = connectionTracker.get(ip) || 0;
if (count > 100) {
return next(new Error('Too many connections'));
}
connectionTracker.set(ip, count + 1);
socket.on('disconnect', () => {
connectionTracker.set(ip, Math.max(0, count - 1));
});
next();
});
Service-level rate limiting protects against API abuse. Implement a Feathersjs hook that enforces rate limits on a per-service basis.
// src/hooks/rate-limit.js
const { RateLimiterMemory } = require('rate-limiter-flexible');
const rateLimiter = new RateLimiterMemory({
keyGenerator: (req) => req.feathers.user?.id || req.feathers.params.query.apiKey || req.ip,
points: 100, // 100 requests
duration: 60 // per minute
});
module.exports = () => async (context) => {
const res = await rateLimiter.consume(context.params.provider);
if (!res.accepted) {
throw new Error('Too many requests');
}
return context;
};
// Apply to services
app.service('messages').hooks({
before: {
all: [ rateLimit() ]
}
});
Authentication endpoint hardening prevents credential stuffing attacks. Add proof-of-work requirements and exponential backoff.
// src/services/authentication/strategies/local.js
const { LocalStrategy } = require('@feathersjs/authentication-local');
const { NotAuthenticated } = require('@feathersjs/errors');
class SecureLocalStrategy extends LocalStrategy {
async authenticate(data, params) {
const { email, password } = data;
// Rate limiting check
const attempts = await this.app.service('auth-attempts').get(email);
if (attempts && attempts.count > 5) {
const waitTime = Math.pow(2, attempts.count - 5) * 1000;
if (Date.now() - attempts.lastAttempt < waitTime) {
throw new NotAuthenticated('Too many attempts');
}
}
return super.authenticate(data, params);
}
}
Service method timeouts prevent resource exhaustion. Wrap service methods with timeout logic.
// src/services/messages/hooks/timeout.js
module.exports = () => async (context) => {
const originalMethod = context.service[context.method];
return Promise.race([
originalMethod.call(context.service, context.id, context.data, context.params),
new Promise((_, reject) =>
setTimeout(() =>
reject(new Error('Request timeout')),
10000 // 10 second timeout
)
)
]);
};
Database connection pooling prevents resource exhaustion. Configure connection limits and timeouts.
// src/middleware/database.js
const { Pool } = require('pg');
const pool = new Pool({
max: 20, // maximum connections
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000
});
app.set('postgres', pool);
Implement circuit breakers for external service calls. Use libraries like opossum to prevent cascading failures.
// src/hooks/circuit-breaker.js
const { CircuitBreaker } = require('opossum');
const breaker = new CircuitBreaker(async (params) => {
return await someExternalService.call(params);
}, {
timeout: 10000,
errorThresholdPercentage: 50,
resetTimeout: 30000
});
module.exports = () => async (context) => {
return await breaker.fire(context.params);
};
Frequently Asked Questions
How does middleBrick detect DDoS vulnerabilities in Feathersjs applications?
middleBrick performs black-box scanning of Feathersjs endpoints without requiring credentials or source code access. The scanner tests for missing rate limiting on authentication endpoints, unlimited Socket.io connections, and unprotected service methods. It identifies configuration weaknesses that make DDoS attacks more likely to succeed by simulating attack patterns and measuring response times. The scanner checks for exposed admin endpoints, missing timeout configurations, and services that could be used for amplification attacks. Results include specific findings with severity levels and remediation guidance tailored to Feathersjs's architecture.
What Feathersjs-specific configurations help prevent DDoS attacks?
Key Feathersjs configurations include Socket.io connection limits, service-level rate limiting hooks, and authentication strategy hardening. Set maxHttpBufferSize and connection timeouts in Socket.io configuration. Implement rate limiting hooks using rate-limiter-flexible or similar libraries, applying them to all service methods. Configure authentication strategies with exponential backoff and proof-of-work requirements. Use connection pooling with proper limits for database services. Add timeout middleware to service methods to prevent hanging requests. Enable structured logging to track request patterns and identify anomalies. Consider implementing a reverse proxy with DDoS protection features in front of your Feathersjs application.