Securing WebSocket connections in production environments requires multi-layered security measures. Here are key security practices:
1. Use WSS (WebSocket Secure)
Enforce encrypted connections:
javascript// Always use wss:// instead of ws:// const ws = new WebSocket('wss://example.com/socket'); // Verify certificate const ws = new WebSocket('wss://example.com/socket', { rejectUnauthorized: true // Reject invalid certificates });
WSS Benefits:
- Encrypted data transmission (TLS/SSL)
- Prevents man-in-the-middle attacks
- Protects sensitive information from eavesdropping
2. Authentication and Authorization
Connection-time Authentication
javascript// Pass authentication token during handshake const ws = new WebSocket(`wss://example.com/socket?token=${authToken}`); // Or send authentication message after connection established ws.onopen = () => { ws.send(JSON.stringify({ type: 'auth', token: authToken })); };
Server-side Verification
javascript// Verify JWT token function validateConnection(token) { try { const decoded = jwt.verify(token, SECRET_KEY); return decoded.userId; } catch (error) { return null; } } // Verify during handshake wss.on('connection', (ws, req) => { const token = req.url.split('token=')[1]; const userId = validateConnection(token); if (!userId) { ws.close(1008, 'Unauthorized'); return; } // Authentication successful, continue processing });
3. Origin Header Validation
Prevent Cross-Site WebSocket Hijacking (CSWSH):
javascriptwss.on('connection', (ws, req) => { const origin = req.headers.origin; const allowedOrigins = ['https://yourdomain.com', 'https://app.yourdomain.com']; if (!allowedOrigins.includes(origin)) { ws.close(1003, 'Unsupported Data'); return; } // Allow connection });
4. Rate Limiting and Throttling
Prevent message flooding and DoS attacks:
javascriptconst rateLimiter = new Map(); function checkRateLimit(userId) { const now = Date.now(); const userLimit = rateLimiter.get(userId); if (!userLimit) { rateLimiter.set(userId, { count: 1, resetTime: now + 60000 }); return true; } if (now > userLimit.resetTime) { rateLimiter.set(userId, { count: 1, resetTime: now + 60000 }); return true; } if (userLimit.count >= 100) { // Max 100 messages per minute return false; } userLimit.count++; return true; } wss.on('connection', (ws, req) => { ws.on('message', (message) => { if (!checkRateLimit(userId)) { ws.send(JSON.stringify({ type: 'error', message: 'Rate limit exceeded' })); return; } // Process message }); });
5. Input Validation and Message Filtering
Validate all incoming messages:
javascriptfunction validateMessage(message) { const data = JSON.parse(message); // Validate message structure if (!data.type || typeof data.type !== 'string') { return false; } // Validate message type const allowedTypes = ['chat', 'ping', 'auth']; if (!allowedTypes.includes(data.type)) { return false; } // Validate data size if (JSON.stringify(data).length > 10240) { // 10KB limit return false; } // Validate content (prevent XSS) if (data.content && /<script|javascript:|onerror=/i.test(data.content)) { return false; } return true; } ws.on('message', (message) => { if (!validateMessage(message)) { ws.close(1007, 'Invalid frame payload data'); return; } // Process valid message });
6. Connection Timeout Management
Set reasonable timeout values:
javascript// Server-side timeout settings const server = http.createServer(); const wss = new WebSocket.Server({ server, clientTracking: true, perMessageDeflate: false }); // Set ping/pong timeout wss.on('connection', (ws) => { ws.isAlive = true; ws.on('pong', () => { ws.isAlive = true; }); }); // Periodically check connection status const interval = setInterval(() => { wss.clients.forEach((ws) => { if (ws.isAlive === false) { return ws.terminate(); } ws.isAlive = false; ws.ping(); }); }, 30000); wss.on('close', () => { clearInterval(interval); });
7. Logging and Monitoring
Log security-related events:
javascriptconst securityLogger = { logConnection: (userId, ip, userAgent) => { console.log(`[SECURITY] Connection from ${ip} - User: ${userId} - UA: ${userAgent}`); }, logUnauthorized: (ip, reason) => { console.warn(`[SECURITY] Unauthorized connection attempt from ${ip} - Reason: ${reason}`); }, logSuspiciousActivity: (userId, activity) => { console.error(`[SECURITY] Suspicious activity from user ${userId}: ${activity}`); } };
8. Network Layer Security
Firewall and Load Balancer Configuration:
- Limit connection source IPs
- Set maximum connection count
- Enable DDoS protection
- Configure Web Application Firewall (WAF)
Security Checklist
- Use WSS encrypted connections
- Implement authentication mechanisms
- Validate Origin headers
- Implement rate limiting
- Validate all input messages
- Set connection timeouts
- Log security events
- Regularly update dependencies
- Conduct security audits and penetration testing