WebSocket and Real-time Connection Analysis: Monitor Live Data Flows
A practical Fusebox guide to websocket and real-time connection analysis.
WebSocket and Real-time Connection Analysis: Monitor Live Data Flows
Published: January 2024
Reading time: 9 minutes
Real-time connections power modern web experiencesβchat, notifications, live updates, collaborative editing. But they also introduce security risks and performance challenges. Here's how to analyze WebSocket connections, monitor real-time data flows, and identify vulnerabilities.
Why Real-time Analysis Matters
The Hidden Data Highway
- Persistent connections - Bypass traditional request/response security
- Binary protocols - Harder to inspect than HTTP
- Authentication gaps - Often implemented incorrectly
- Data leakage - Sensitive info in real-time streams
- Performance impact - Keep-alive overhead and reconnection storms
Real-World Incidents
Slack (2016): WebSocket token exposure allowed account takeover
Zoom (2020): WebSocket vulnerabilities enabled meeting hijacking
Discord (2021): Real-time connection leak exposed user presence
Trading Apps (2023): WebSocket injection manipulated prices
Chat Services: Regular data leaks through unencrypted WebSockets
Quick WebSocket Detection
1. Active Connection Monitor
// Monitor all WebSocket connections on the page
(function monitorWebSockets() {
console.log('π WebSocket Connection Monitor\n');
const connections = new Map();
let connectionId = 0;
// Override WebSocket constructor
const OriginalWebSocket = window.WebSocket;
window.WebSocket = function(url, protocols) {
console.log(`\nπ New WebSocket connection #${++connectionId}`);
console.log(` URL: ${url}`);
if (protocols) console.log(` Protocols: ${protocols}`);
// Create real WebSocket
const ws = new OriginalWebSocket(url, protocols);
const id = connectionId;
const startTime = Date.now();
// Store connection info
const connInfo = {
id: id,
url: url,
protocols: protocols,
state: 'CONNECTING',
messagesSent: 0,
messagesReceived: 0,
bytesSent: 0,
bytesReceived: 0,
startTime: startTime,
errors: []
};
connections.set(id, connInfo);
// Monitor events
ws.addEventListener('open', function(event) {
connInfo.state = 'OPEN';
connInfo.openTime = Date.now();
console.log(`β
Connection #${id} opened (${connInfo.openTime - startTime}ms)`);
// Check for security
const wsUrl = new URL(url);
if (wsUrl.protocol === 'ws:' && window.location.protocol === 'https:') {
console.log(` β οΈ WARNING: Insecure WebSocket on HTTPS page!`);
connInfo.errors.push('Insecure WebSocket');
}
});
ws.addEventListener('message', function(event) {
connInfo.messagesReceived++;
const dataSize = event.data.length || event.data.size || 0;
connInfo.bytesReceived += dataSize;
// Analyze message content
let messageType = 'unknown';
let sensitiveData = false;
if (typeof event.data === 'string') {
messageType = 'text';
// Check for sensitive data patterns
const sensitivePatterns = [
/password/i,
/token/i,
/session/i,
/credit.?card/i,
/ssn/i,
/api.?key/i
];
sensitiveData = sensitivePatterns.some(pattern => pattern.test(event.data));
// Try to parse JSON
try {
const parsed = JSON.parse(event.data);
messageType = parsed.type || parsed.event || 'json';
} catch (e) {
// Not JSON
}
} else if (event.data instanceof Blob) {
messageType = 'binary';
}
console.log(`π¨ Message #${connInfo.messagesReceived} on connection #${id}`);
console.log(` Type: ${messageType}, Size: ${dataSize} bytes`);
if (sensitiveData) {
console.log(` β οΈ SENSITIVE DATA DETECTED!`);
connInfo.errors.push('Sensitive data in message');
}
});
ws.addEventListener('error', function(event) {
connInfo.state = 'ERROR';
connInfo.errors.push('Connection error');
console.log(`β Error on connection #${id}`);
});
ws.addEventListener('close', function(event) {
connInfo.state = 'CLOSED';
connInfo.closeTime = Date.now();
connInfo.duration = connInfo.closeTime - startTime;
console.log(`π΄ Connection #${id} closed`);
console.log(` Code: ${event.code}, Reason: ${event.reason || 'none'}`);
console.log(` Duration: ${(connInfo.duration / 1000).toFixed(1)}s`);
console.log(` Messages: ${connInfo.messagesSent} sent, ${connInfo.messagesReceived} received`);
});
// Override send to monitor outgoing
const originalSend = ws.send;
ws.send = function(data) {
connInfo.messagesSent++;
connInfo.bytesSent += data.length || data.size || 0;
console.log(`π€ Sending message #${connInfo.messagesSent} on connection #${id}`);
return originalSend.apply(this, arguments);
};
return ws;
};
// Restore prototype
window.WebSocket.prototype = OriginalWebSocket.prototype;
// Status report
setInterval(() => {
if (connections.size > 0) {
console.log('\nπ WebSocket Status Report');
console.log('β'.repeat(40));
connections.forEach((conn, id) => {
if (conn.state === 'OPEN') {
const duration = ((Date.now() - conn.startTime) / 1000).toFixed(1);
const rate = conn.messagesReceived > 0 ?
(conn.messagesReceived / duration).toFixed(1) : 0;
console.log(`Connection #${id}: ${conn.state}`);
console.log(` Duration: ${duration}s`);
console.log(` Messages: ${conn.messagesReceived} (${rate} msg/s)`);
console.log(` Data received: ${(conn.bytesReceived / 1024).toFixed(1)}KB`);
if (conn.errors.length > 0) {
console.log(` β οΈ Issues: ${conn.errors.join(', ')}`);
}
}
});
}
}, 10000);
console.log('WebSocket monitoring active...');
})();
2. Socket.io Detection and Analysis
// Detect and analyze Socket.io connections
function analyzeSocketIO() {
console.log('\nπ Socket.io Analysis\n');
if (!window.io) {
console.log('β Socket.io not detected');
return;
}
console.log('β
Socket.io detected!');
// Find all socket instances
const sockets = [];
// Common Socket.io instance locations
const possibleSockets = [
window.socket,
window.io.socket,
window.app?.socket,
window.socketIO
];
possibleSockets.forEach(socket => {
if (socket && socket.emit && socket.on) {
sockets.push(socket);
}
});
if (sockets.length === 0 && window.io) {
// Try to find by monitoring new connections
const originalIo = window.io;
window.io = function(...args) {
const socket = originalIo.apply(this, args);
console.log('π New Socket.io connection created');
analyzeSocket(socket);
return socket;
};
window.io.prototype = originalIo.prototype;
}
// Analyze found sockets
sockets.forEach((socket, index) => {
console.log(`\nπ‘ Socket instance #${index + 1}`);
analyzeSocket(socket);
});
function analyzeSocket(socket) {
console.log(` Connected: ${socket.connected}`);
console.log(` ID: ${socket.id || 'not assigned'}`);
// Monitor events
const events = new Map();
// Override emit to track outgoing
const originalEmit = socket.emit;
socket.emit = function(event, ...args) {
if (!events.has(event)) {
events.set(event, { sent: 0, received: 0 });
}
events.get(event).sent++;
console.log(`π€ Emit: ${event}`);
if (args.length > 0 && typeof args[0] !== 'function') {
console.log(` Data: ${JSON.stringify(args[0]).substring(0, 100)}...`);
}
return originalEmit.apply(this, arguments);
};
// Override on to track incoming
const originalOn = socket.on;
socket.on = function(event, handler) {
if (!events.has(event)) {
events.set(event, { sent: 0, received: 0 });
}
const wrappedHandler = function(...args) {
events.get(event).received++;
console.log(`π¨ Received: ${event}`);
if (args.length > 0) {
console.log(` Data: ${JSON.stringify(args[0]).substring(0, 100)}...`);
}
return handler.apply(this, args);
};
console.log(`π Listening for: ${event}`);
return originalOn.call(this, event, wrappedHandler);
};
// Common Socket.io events to monitor
const commonEvents = [
'connect',
'disconnect',
'error',
'reconnect',
'message'
];
commonEvents.forEach(event => {
socket.on(event, (data) => {
console.log(`π― ${event} event:`, data);
});
});
// Security analysis
console.log('\nπ Security Analysis:');
// Check transport
if (socket.io) {
console.log(` Transport: ${socket.io.engine?.transport?.name || 'unknown'}`);
if (window.location.protocol === 'https:' &&
socket.io.uri && socket.io.uri.startsWith('ws://')) {
console.log(' β οΈ WARNING: Insecure WebSocket on HTTPS!');
}
}
// Check authentication
if (socket.auth || socket.io?.opts?.auth) {
console.log(' β
Authentication configured');
} else {
console.log(' β οΈ No authentication found');
}
// List all event listeners
setTimeout(() => {
console.log('\nπ Event Summary:');
events.forEach((stats, event) => {
console.log(` ${event}: ${stats.sent} sent, ${stats.received} received`);
});
}, 5000);
}
}
analyzeSocketIO();
3. Server-Sent Events (SSE) Monitor
// Monitor Server-Sent Events connections
function monitorSSE() {
console.log('\nπ‘ Server-Sent Events Monitor\n');
const connections = [];
// Override EventSource
const OriginalEventSource = window.EventSource;
window.EventSource = function(url, config) {
console.log(`π New SSE connection: ${url}`);
const es = new OriginalEventSource(url, config);
const connInfo = {
url: url,
config: config,
state: 'CONNECTING',
events: new Map(),
startTime: Date.now(),
reconnects: 0
};
connections.push(connInfo);
// Monitor connection state
es.addEventListener('open', () => {
connInfo.state = 'OPEN';
console.log(`β
SSE connected: ${url}`);
// Security check
const sseUrl = new URL(url, window.location.origin);
if (sseUrl.protocol === 'http:' && window.location.protocol === 'https:') {
console.log(' β οΈ WARNING: Insecure SSE on HTTPS page!');
}
});
es.addEventListener('error', (e) => {
connInfo.state = 'ERROR';
connInfo.reconnects++;
console.log(`β SSE error on ${url} (reconnect #${connInfo.reconnects})`);
});
// Override addEventListener to monitor all events
const originalAddEventListener = es.addEventListener;
es.addEventListener = function(type, listener, options) {
if (type !== 'open' && type !== 'error') {
if (!connInfo.events.has(type)) {
connInfo.events.set(type, 0);
}
// Wrap listener to count events
const wrappedListener = function(event) {
connInfo.events.get(type)++;
console.log(`π¨ SSE Event: ${type}`);
console.log(` Data: ${event.data?.substring(0, 100)}...`);
// Check for sensitive data
if (event.data) {
const sensitive = /password|token|key|secret/i.test(event.data);
if (sensitive) {
console.log(' β οΈ SENSITIVE DATA DETECTED!');
}
}
return listener.apply(this, arguments);
};
console.log(`π SSE listening for: ${type}`);
return originalAddEventListener.call(this, type, wrappedListener, options);
}
return originalAddEventListener.apply(this, arguments);
};
return es;
};
// Check for existing EventSource instances
console.log('Checking for existing SSE connections...');
// Common patterns
const patterns = [
window.eventSource,
window.sse,
window.source
];
patterns.forEach(source => {
if (source && source.readyState !== undefined) {
console.log('Found existing SSE connection');
connections.push({
url: source.url || 'unknown',
state: ['CONNECTING', 'OPEN', 'CLOSED'][source.readyState],
existing: true
});
}
});
// Status report
setInterval(() => {
if (connections.length > 0) {
console.log('\nπ SSE Status Report');
connections.forEach((conn, index) => {
console.log(`\nConnection #${index + 1}: ${conn.url}`);
console.log(` State: ${conn.state}`);
console.log(` Reconnects: ${conn.reconnects}`);
if (conn.events.size > 0) {
console.log(' Events received:');
conn.events.forEach((count, event) => {
console.log(` ${event}: ${count}`);
});
}
});
}
}, 10000);
console.log('SSE monitoring active...');
}
monitorSSE();
Real-time Security Analysis
1. Connection Security Scanner
// Analyze security of real-time connections
async function scanRealtimeSecurity() {
console.log('\nπ Real-time Connection Security Scan\n');
const issues = [];
// 1. Check for insecure WebSockets
console.log('1οΈβ£ Checking WebSocket security...');
// Look for ws:// on https:// pages
if (window.location.protocol === 'https:') {
const scripts = Array.from(document.scripts);
const scriptContent = scripts.map(s => s.innerHTML).join(' ');
if (scriptContent.includes('ws://') && !scriptContent.includes('wss://')) {
issues.push({
severity: 'HIGH',
issue: 'Insecure WebSocket on HTTPS page',
impact: 'Man-in-the-middle attacks possible',
fix: 'Use wss:// instead of ws://'
});
}
}
// 2. Check for authentication
console.log('2οΈβ£ Checking authentication...');
// Monitor for auth tokens in URLs
const OriginalWebSocket = window.WebSocket;
window.WebSocket = function(url, protocols) {
const urlObj = new URL(url);
// Check for tokens in URL
if (urlObj.searchParams.has('token') ||
urlObj.searchParams.has('auth') ||
urlObj.searchParams.has('key')) {
issues.push({
severity: 'HIGH',
issue: 'Authentication token in WebSocket URL',
impact: 'Tokens visible in logs and referrer headers',
fix: 'Send auth tokens in connection headers or first message'
});
}
return new OriginalWebSocket(url, protocols);
};
window.WebSocket.prototype = OriginalWebSocket.prototype;
// 3. Check for origin validation
console.log('3οΈβ£ Testing origin validation...');
try {
// Test WebSocket with different origin
const testWs = new WebSocket(
window.location.origin.replace('http', 'ws') + '/test',
[]
);
testWs.onerror = () => {
console.log(' β
Origin validation appears to be working');
};
testWs.onopen = () => {
issues.push({
severity: 'MEDIUM',
issue: 'WebSocket accepts connections from any origin',
impact: 'Cross-site WebSocket hijacking possible',
fix: 'Validate Origin header on server'
});
testWs.close();
};
setTimeout(() => testWs.close(), 1000);
} catch (e) {
// Connection failed - good
}
// 4. Check for rate limiting
console.log('4οΈβ£ Testing rate limiting...');
let rapidMessages = 0;
const testRateLimit = () => {
const ws = new WebSocket(
window.location.origin.replace('http', 'ws') + '/test'
);
ws.onopen = () => {
// Send many messages rapidly
for (let i = 0; i < 100; i++) {
try {
ws.send(JSON.stringify({ test: i }));
rapidMessages++;
} catch (e) {
break;
}
}
ws.close();
};
ws.onerror = () => {};
};
// Don't actually spam the server
console.log(' β οΈ Rate limit test skipped (would spam server)');
// 5. Check for message validation
console.log('5οΈβ£ Checking message validation...');
// Look for JSON parsing without try/catch
const hasUnsafeJSONParsing = Array.from(document.scripts)
.some(script => {
const content = script.innerHTML;
return content.includes('JSON.parse(') &&
!content.includes('try') &&
content.includes('message');
});
if (hasUnsafeJSONParsing) {
issues.push({
severity: 'MEDIUM',
issue: 'Unsafe JSON parsing in message handlers',
impact: 'Malformed messages can crash application',
fix: 'Wrap JSON.parse in try/catch blocks'
});
}
// Report findings
console.log('\nπ Security Scan Results:');
if (issues.length === 0) {
console.log('β
No major security issues found');
} else {
console.log(`β Found ${issues.length} security issues:\n`);
issues.sort((a, b) => {
const severity = { HIGH: 3, MEDIUM: 2, LOW: 1 };
return severity[b.severity] - severity[a.severity];
}).forEach((issue, index) => {
console.log(`${index + 1}. ${issue.severity}: ${issue.issue}`);
console.log(` Impact: ${issue.impact}`);
console.log(` Fix: ${issue.fix}\n`);
});
}
// Best practices
console.log('π‘ Real-time Security Best Practices:');
console.log('1. Always use wss:// on HTTPS sites');
console.log('2. Implement proper authentication');
console.log('3. Validate message origin and format');
console.log('4. Rate limit connections and messages');
console.log('5. Implement heartbeat/timeout mechanisms');
console.log('6. Log and monitor anomalous behavior');
return issues;
}
scanRealtimeSecurity();
2. Message Pattern Analyzer
// Analyze patterns in real-time messages
class MessagePatternAnalyzer {
constructor() {
this.patterns = new Map();
this.anomalies = [];
this.startTime = Date.now();
}
analyzeMessage(type, data, connection) {
// Get or create pattern entry
if (!this.patterns.has(type)) {
this.patterns.set(type, {
count: 0,
sizes: [],
intervals: [],
lastTime: Date.now(),
samples: []
});
}
const pattern = this.patterns.get(type);
const now = Date.now();
// Update statistics
pattern.count++;
pattern.intervals.push(now - pattern.lastTime);
pattern.lastTime = now;
// Analyze data
let dataSize = 0;
let dataStructure = null;
if (typeof data === 'string') {
dataSize = data.length;
// Try to parse structure
try {
const parsed = JSON.parse(data);
dataStructure = this.getStructure(parsed);
} catch (e) {
dataStructure = 'string';
}
} else if (data instanceof ArrayBuffer) {
dataSize = data.byteLength;
dataStructure = 'binary';
}
pattern.sizes.push(dataSize);
// Store sample (first 5)
if (pattern.samples.length < 5) {
pattern.samples.push({
data: data.substring ? data.substring(0, 100) : '[binary]',
structure: dataStructure,
timestamp: now
});
}
// Detect anomalies
this.detectAnomalies(type, pattern, dataSize);
}
getStructure(obj) {
if (Array.isArray(obj)) {
return 'array';
}
if (obj === null) {
return 'null';
}
if (typeof obj === 'object') {
const keys = Object.keys(obj).sort();
return `object:${keys.join(',')}`;
}
return typeof obj;
}
detectAnomalies(type, pattern, currentSize) {
// Size anomaly
if (pattern.sizes.length > 10) {
const avgSize = pattern.sizes.reduce((a, b) => a + b) / pattern.sizes.length;
if (currentSize > avgSize * 5) {
this.anomalies.push({
type: 'size',
message: `Unusually large ${type} message: ${currentSize} bytes (avg: ${avgSize.toFixed(0)})`
});
}
}
// Frequency anomaly
if (pattern.intervals.length > 10) {
const avgInterval = pattern.intervals.reduce((a, b) => a + b) / pattern.intervals.length;
const lastInterval = pattern.intervals[pattern.intervals.length - 1];
if (lastInterval < avgInterval / 10) {
this.anomalies.push({
type: 'frequency',
message: `Rapid ${type} messages: ${lastInterval}ms interval (avg: ${avgInterval.toFixed(0)}ms)`
});
}
}
}
report() {
console.log('\nπ Message Pattern Analysis Report');
console.log('β'.repeat(50));
const duration = (Date.now() - this.startTime) / 1000;
console.log(`Analysis duration: ${duration.toFixed(1)}s\n`);
// Pattern summary
this.patterns.forEach((pattern, type) => {
console.log(`π¨ Message Type: ${type}`);
console.log(` Count: ${pattern.count}`);
console.log(` Rate: ${(pattern.count / duration).toFixed(1)} msg/s`);
if (pattern.sizes.length > 0) {
const avgSize = pattern.sizes.reduce((a, b) => a + b) / pattern.sizes.length;
const maxSize = Math.max(...pattern.sizes);
console.log(` Avg size: ${avgSize.toFixed(0)} bytes`);
console.log(` Max size: ${maxSize} bytes`);
}
if (pattern.samples.length > 0) {
console.log(' Sample structures:');
const structures = [...new Set(pattern.samples.map(s => s.structure))];
structures.forEach(s => console.log(` - ${s}`));
}
console.log('');
});
// Anomalies
if (this.anomalies.length > 0) {
console.log('β οΈ Anomalies Detected:');
this.anomalies.forEach(anomaly => {
console.log(` - ${anomaly.message}`);
});
}
// Security recommendations based on patterns
console.log('\nπ Security Recommendations:');
let hasLargeMessages = false;
let hasHighFrequency = false;
this.patterns.forEach(pattern => {
const avgSize = pattern.sizes.reduce((a, b) => a + b, 0) / pattern.sizes.length;
if (avgSize > 10000) hasLargeMessages = true;
const rate = pattern.count / duration;
if (rate > 10) hasHighFrequency = true;
});
if (hasLargeMessages) {
console.log('1. Implement message size limits');
console.log('2. Consider compression for large payloads');
}
if (hasHighFrequency) {
console.log('3. Implement rate limiting per connection');
console.log('4. Consider message batching');
}
console.log('5. Validate all message formats');
console.log('6. Implement connection timeouts');
}
}
// Initialize analyzer
const messageAnalyzer = new MessagePatternAnalyzer();
// Hook into WebSocket to analyze
const OriginalWebSocket = window.WebSocket;
window.WebSocket = function(url, protocols) {
const ws = new OriginalWebSocket(url, protocols);
ws.addEventListener('message', (event) => {
messageAnalyzer.analyzeMessage('incoming', event.data, url);
});
const originalSend = ws.send;
ws.send = function(data) {
messageAnalyzer.analyzeMessage('outgoing', data, url);
return originalSend.apply(this, arguments);
};
return ws;
};
// Report after 30 seconds
setTimeout(() => messageAnalyzer.report(), 30000);
console.log('Message pattern analysis started (30s collection)...');
Complete Real-time Audit
Comprehensive Connection Assessment
// Run complete real-time connection audit
async function completeRealtimeAudit() {
console.log('π COMPLETE REAL-TIME CONNECTION AUDIT');
console.log('β'.repeat(50));
console.log(`URL: ${window.location.href}`);
console.log(`Date: ${new Date().toLocaleDateString()}\n`);
const audit = {
connections: {
websocket: 0,
socketio: false,
sse: 0,
longPolling: false
},
security: {
score: 100,
issues: []
},
performance: {
messageRate: 0,
bandwidth: 0,
reconnections: 0
},
recommendations: []
};
// Phase 1: Connection Detection
console.log('π‘ PHASE 1: CONNECTION DETECTION');
console.log('β'.repeat(40));
// Check for WebSocket
if (window.WebSocket) {
console.log('β
WebSocket API available');
// Monitor for 5 seconds
let wsConnections = 0;
const OriginalWS = window.WebSocket;
window.WebSocket = function(url) {
wsConnections++;
audit.connections.websocket++;
console.log(` π WebSocket connection: ${url}`);
// Security check
if (url.startsWith('ws://') && window.location.protocol === 'https:') {
audit.security.issues.push('Insecure WebSocket on HTTPS');
audit.security.score -= 20;
}
return new OriginalWS(url);
};
window.WebSocket.prototype = OriginalWS.prototype;
}
// Check for Socket.io
if (window.io) {
audit.connections.socketio = true;
console.log('β
Socket.io detected');
}
// Check for EventSource (SSE)
if (window.EventSource) {
console.log('β
Server-Sent Events available');
}
// Check for long polling (XHR/fetch patterns)
let pollCount = 0;
const checkLongPolling = () => {
const xhrOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url) {
if (method === 'GET' && url.includes('poll')) {
pollCount++;
if (pollCount > 3) {
audit.connections.longPolling = true;
}
}
return xhrOpen.apply(this, arguments);
};
};
checkLongPolling();
// Phase 2: Security Analysis
console.log('\nπ PHASE 2: SECURITY ANALYSIS');
console.log('β'.repeat(40));
// Check protocols
if (window.location.protocol === 'https:') {
console.log('β
Page served over HTTPS');
} else {
console.log('β Page not using HTTPS');
audit.security.issues.push('Not using HTTPS');
audit.security.score -= 30;
}
// Check for auth tokens in URLs
const scripts = Array.from(document.scripts);
const hasTokensInUrls = scripts.some(s =>
s.innerHTML.includes('?token=') ||
s.innerHTML.includes('&auth=')
);
if (hasTokensInUrls) {
console.log('β οΈ Possible auth tokens in URLs');
audit.security.issues.push('Auth tokens in URLs');
audit.security.score -= 15;
}
// Phase 3: Performance Analysis
console.log('\nβ‘ PHASE 3: PERFORMANCE ANALYSIS');
console.log('β'.repeat(40));
// Monitor for 5 seconds
const startMonitoring = Date.now();
let messageCount = 0;
let totalBytes = 0;
// Override WebSocket to count messages
if (window.WebSocket) {
const OriginalWS = window.WebSocket;
window.WebSocket = function(url) {
const ws = new OriginalWS(url);
ws.addEventListener('message', (e) => {
messageCount++;
totalBytes += e.data.length || e.data.size || 0;
});
const originalSend = ws.send;
ws.send = function(data) {
messageCount++;
totalBytes += data.length || data.size || 0;
return originalSend.apply(this, arguments);
};
return ws;
};
window.WebSocket.prototype = OriginalWS.prototype;
}
// Wait and calculate
setTimeout(() => {
const duration = (Date.now() - startMonitoring) / 1000;
audit.performance.messageRate = (messageCount / duration).toFixed(1);
audit.performance.bandwidth = (totalBytes / duration / 1024).toFixed(1); // KB/s
console.log(`Message rate: ${audit.performance.messageRate} msg/s`);
console.log(`Bandwidth: ${audit.performance.bandwidth} KB/s`);
// Phase 4: Best Practices
console.log('\nβ
PHASE 4: BEST PRACTICES CHECK');
console.log('β'.repeat(40));
const practices = {
'Secure protocol (wss://)': audit.connections.websocket === 0 ||
!audit.security.issues.includes('Insecure WebSocket on HTTPS'),
'Authentication implemented': !audit.security.issues.includes('Auth tokens in URLs'),
'Compression enabled': true, // Would need server access to verify
'Heartbeat/ping implemented': messageCount > 0 // Rough check
};
Object.entries(practices).forEach(([practice, implemented]) => {
console.log(`${implemented ? 'β
' : 'β'} ${practice}`);
if (!implemented) {
audit.security.score -= 5;
}
});
// Final Score
audit.security.score = Math.max(0, audit.security.score);
console.log('\nπ AUDIT SUMMARY');
console.log('β'.repeat(50));
console.log(`Security Score: ${audit.security.score}/100`);
console.log(`Active connections: ${audit.connections.websocket + (audit.connections.socketio ? 1 : 0)}`);
console.log(`Message rate: ${audit.performance.messageRate} msg/s`);
console.log(`Issues found: ${audit.security.issues.length}`);
// Risk level
let risk = 'LOW';
if (audit.security.score < 50) risk = 'HIGH';
else if (audit.security.score < 70) risk = 'MEDIUM';
console.log(`Risk Level: ${risk}`);
// Recommendations
console.log('\nπ‘ RECOMMENDATIONS:');
if (audit.security.issues.includes('Insecure WebSocket on HTTPS')) {
console.log('1. Use wss:// for all WebSocket connections');
}
if (audit.security.issues.includes('Auth tokens in URLs')) {
console.log('2. Move auth tokens to headers or message payload');
}
if (audit.performance.messageRate > 50) {
console.log('3. Implement message batching to reduce overhead');
}
if (!audit.connections.websocket && !audit.connections.socketio) {
console.log('4. Consider WebSocket for real-time features');
}
console.log('5. Implement connection state recovery');
console.log('6. Add message compression for large payloads');
console.log('7. Monitor for connection stability');
}, 5000);
console.log('\nCollecting data for 5 seconds...');
return audit;
}
// Run the complete audit
completeRealtimeAudit();
The Bottom Line
Real-time connections are powerful but risky:
- Every connection is persistent - Traditional security doesn't apply
- Messages bypass normal controls - No CORS, different auth model
- Performance compounds quickly - Message storms crash servers
- Debugging is harder - Async, bidirectional, binary protocols
- Security often an afterthought - Focus on functionality over protection
Monitor every connection. Validate every message. Secure every transport. Real-time means real risk.
Monitor real-time connections instantly: Fusebox tracks WebSocket, Socket.io, and SSE connections, analyzes message patterns, and detects security issues while you browse. Secure your real-time data flows. $29 one-time purchase.