π Secure, feature-rich WebSocket client-server package for Node.js
- Features
- Installation
- Quick Start
- Configuration
- API Documentation
- Examples
- Security
- Troubleshooting
- Contributing
- License
- π End-to-End Encryption - Diffie-Hellman key exchange + AES-256-GCM with secure key derivation
- π Room/Channel System - Organize clients into rooms for targeted messaging
- π Heartbeat/Ping-Pong - Keep connections alive and detect dead connections
- π Exponential Backoff Reconnection - Smart reconnection strategy that adapts
- ποΈ Message Compression - Reduce bandwidth usage with gzip compression
- π‘οΈ Security - Token authentication, IP whitelist, CORS support, Rate limiting
- β‘ Remote Code Execution - Secure sandboxed code execution with VM2
- π― TypeScript - Fully typed with excellent IntelliSense support
- β 98.1% Test Coverage - Comprehensive test suite with integration tests
- π High Performance - 100 clients connect in ~224ms, broadcast in ~112ms
npm install @onurege3467/workspaces wsNote: ws is a peer dependency and must be installed separately.
import { Server } from '@onurege3467/workspaces'
const server = new Server({
port: 8080,
token: 'your-secret-token',
enableEncryption: true,
enableRooms: true,
enableHeartbeat: true,
enableCompression: true,
allowedOrigins: ['https://example.com'],
enableRateLimit: true
})
server.listen(() => {
console.log('Server running on port 8080')
})
// Broadcast to all clients
server.broadcast({ type: 'announcement', message: 'Welcome!' })
// Broadcast to a specific room
server.to('general').broadcast({ type: 'message', content: 'Hello general!' })import { Client } from '@onurege3467/workspaces'
const client = new Client({
address: 'localhost:8080',
token: 'your-secret-token',
name: 'MyClient',
enableEncryption: true,
enableCompression: true,
reconnectInterval: 5000,
reconnectMaxInterval: 60000,
reconnectBackoffFactor: 2,
enableHeartbeat: true
})
client.on('open', () => {
console.log('Connected!')
client.send('Hello server!')
client.join('general')
})
client.on('message', (message) => {
console.log('Received:', message)
})
client.on('error', (error) => {
console.error('Error:', error.message)
})
client.connect()| Option | Type | Default | Description |
|---|---|---|---|
port |
number |
required | Server port |
token |
string |
required | Authentication token |
enableEncryption |
boolean |
false |
Enable end-to-end encryption |
enableRooms |
boolean |
false |
Enable room/channel system |
enableHeartbeat |
boolean |
false |
Enable heartbeat monitoring |
heartbeatInterval |
number |
30000 |
Heartbeat interval (ms) |
heartbeatTimeout |
number |
5000 |
Heartbeat timeout (ms) |
enableCompression |
boolean |
false |
Enable message compression |
compressionThreshold |
number |
1024 |
Compression threshold (bytes) |
ipWhitelist |
string[] |
[] |
Allowed IP addresses |
allowedOrigins |
string[] |
[] |
CORS allowed origins |
allowCredentials |
boolean |
false |
Allow CORS credentials |
maxConnections |
number |
1000 |
Maximum connections |
enableRateLimit |
boolean |
true |
Enable rate limiting |
rateLimitMaxRequests |
number |
100 |
Max requests per window |
rateLimitWindowMs |
number |
60000 |
Rate limit window (ms) |
enableCodeExecution |
boolean |
false |
DANGER: Enable remote code execution |
codeExecutionTimeout |
number |
5000 |
Code execution timeout (ms) |
codeExecutionMemoryLimit |
number |
134217728 |
Code execution memory limit (bytes) |
| Option | Type | Default | Description |
|---|---|---|---|
address |
string |
required | Server address (host:port) |
token |
string |
required | Authentication token |
enableEncryption |
boolean |
false |
Enable end-to-end encryption |
enableCompression |
boolean |
false |
Enable message compression |
reconnectInterval |
number |
5000 |
Initial reconnection interval (ms) |
reconnectMaxInterval |
number |
60000 |
Max reconnection interval (ms) |
reconnectBackoffFactor |
number |
2 |
Exponential backoff factor |
enableHeartbeat |
boolean |
false |
Enable heartbeat monitoring |
heartbeatInterval |
number |
30000 |
Heartbeat interval (ms) |
heartbeatTimeout |
number |
5000 |
Heartbeat timeout (ms) |
secure |
boolean |
false |
Use WSS instead of WS |
name |
string |
undefined |
Client identifier |
π Full API documentation is available at: ./docs/index.html
Open docs/index.html in your browser for comprehensive API reference with TypeScript types, examples, and detailed descriptions.
new Server(config: ServerConfig)listen(callback?: () => void): void
Start the WebSocket server and begin listening for connections.
server.listen(() => {
console.log('Server started on port 8080');
});broadcast(message: any, sender?: WebSocket): void
Broadcast a message to all connected clients except the sender.
server.broadcast('Hello everyone!');
server.broadcast({ type: 'announcement', content: 'Server restart' });to(roomName: string): RoomManager
Get room manager for targeted broadcasting to a specific room.
server.to('general').broadcast('Message for general room only');close(callback?: () => void): void
Gracefully close the server and all connections.
server.close(() => {
console.log('Server closed');
});getConnectionCount(): number
Get the current number of connected clients.
const count = server.getConnectionCount();
console.log(`Connected clients: ${count}`);getAllRooms(): string[]
Get list of all active room names.
const rooms = server.getAllRooms();
console.log('Active rooms:', rooms);getRoomClients(roomName: string): Set<WebSocket> | undefined
Get all clients in a specific room.
const clients = server.getRoomClients('general');
console.log(`Clients in general room: ${clients?.size}`);new Client(config: ClientConfig)connect(): void
Establish connection to the WebSocket server.
send(message: any): void
Send a message to the server.
client.send('Hello world!');
client.send({ type: 'chat', content: 'Hi!' });
client.send({ sender: 'user1', data: 'Custom message' });join(roomName: string): void
Join a chat room for targeted messaging.
client.join('general');
client.join('support');leave(roomName: string): void
Leave a chat room.
client.leave('general');close(): void
Close the WebSocket connection gracefully.
isConnected(): boolean
Check if the client is currently connected.
getReconnectAttempts(): number
Get the current reconnection attempt count.
open
Connection established.
message
Message received from server.
close
Connection closed.
error
Error occurred.
reconnecting
Attempting to reconnect.
heartbeat
Heartbeat received.
// server.ts
import { Server } from '@onurege3467/workspaces'
const server = new Server({
port: 8080,
token: 'secret'
})
server.listen()
// client.ts
import { Client } from '@onurege3467/workspaces'
const client = new Client({
address: 'localhost:8080',
token: 'secret'
})
client.connect()// server.ts
const server = new Server({
port: 8080,
token: 'secret',
enableEncryption: true
})
// client.ts
const client = new Client({
address: 'localhost:8080',
token: 'secret',
enableEncryption: true
})
client.on('message', (msg) => console.log('Secure:', msg))
client.connect()// server.ts
const server = new Server({
port: 8080,
token: 'secret',
enableRooms: true
})
// Broadcast to specific room
server.to('general').broadcast({ type: 'msg', content: 'Hello general!' })
server.to('support').broadcast({ type: 'msg', content: 'Hello support!' })
// client.ts
client.on('open', () => {
client.join('general')
})
client.send({ type: 'msg', content: 'My message' })// client.ts
const client = new Client({
address: 'localhost:8080',
token: 'secret',
enableHeartbeat: true,
reconnectInterval: 5000,
reconnectMaxInterval: 60000,
reconnectBackoffFactor: 2
})
client.on('reconnecting', () => {
console.log('Attempting to reconnect...');
})
client.on('heartbeat', () => {
console.log('Connection is alive');
})// server.ts
const server = new Server({
port: 8080,
token: 'secret',
enableRateLimit: true,
rateLimitMaxRequests: 50, // 50 requests
rateLimitWindowMs: 60000 // per minute
})
// Check remaining requests for an IP
const remaining = server.getRateLimitRemaining('192.168.1.1');
console.log(`Remaining requests: ${remaining}`);The package uses Diffie-Hellman key exchange for secure key generation and AES-256-GCM for message encryption with PBKDF2 key derivation:
- Client generates public/private key pair using Diffie-Hellman
- Server generates its own key pair
- Both parties exchange public keys
- Shared secret is computed using Diffie-Hellman
- AES-256-GCM key is securely derived from shared secret using PBKDF2 with 100,000 iterations
- All messages are encrypted with this key and include integrity protection
Built-in rate limiting protects against abuse:
- Configurable request limits per IP address
- Sliding window time periods
- Automatic cleanup of old requests
- Returns HTTP 429 when limits exceeded
- Token Authentication: Required for all connections
- IP Whitelisting: Restrict access to specific IP addresses
- CORS Support: Configurable cross-origin policies
- All cryptographic operations include comprehensive input validation
- JSON parsing with proper error handling
- Buffer length validation for encryption keys
# Build the project
npm run build
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Generate API documentation
npm run docsConnection Refused
- Check if server is running on the correct port
- Verify token matches between client and server
- Check IP whitelist if enabled
Encryption Errors
- Ensure both client and server have encryption enabled
- Check network connectivity for key exchange
- Verify compatible Node.js version
Rate Limiting
- Check rate limit configuration
- Monitor server logs for rate limit violations
- Adjust limits based on your use case
Room Messages Not Received
- Ensure rooms are enabled on server
- Verify client has joined the correct room
- Check room name spelling
Enable debug logging:
// Server
const server = new Server({
// ... config
enableDebug: true
})
// Client
const client = new Client({
// ... config
enableDebug: true
})For high-traffic applications:
const server = new Server({
port: 8080,
token: 'secret',
maxConnections: 10000,
enableCompression: true,
compressionThreshold: 512, // Lower threshold
enableRateLimit: true,
rateLimitMaxRequests: 1000,
rateLimitWindowMs: 60000
})π¨ SECURITY WARNING: Remote code execution is EXTREMELY DANGEROUS and should NEVER be enabled in production environments unless you are in a completely trusted environment with proper security measures in place.
- Arbitrary Code Execution: Attackers can run any code on your server
- System Compromise: File system access, network access, privilege escalation
- Data Breach: Sensitive data theft, database manipulation
- Denial of Service: Infinite loops, memory exhaustion, resource abuse
- Backdoors: Malicious code can create persistent access
const server = new Server({
port: 8080,
token: 'secret',
enableCodeExecution: false, // β οΈ KEEP THIS FALSE!
codeExecutionTimeout: 5000, // 5 second timeout
codeExecutionMemoryLimit: 128 * 1024 * 1024 // 128MB limit
});- Only enable in isolated, air-gapped environments
- Use VM2 sandboxing with strict timeouts
- Implement comprehensive input validation
- Block dangerous functions (require, fs, process, etc.)
- Use rate limiting and IP whitelisting
- Monitor execution logs continuously
- Regular security audits
import { VM } from 'vm2';
// β οΈ DANGER: Only for trusted environments!
const server = new Server({
port: 8080,
token: 'secret',
enableCodeExecution: true, // β οΈ NEVER DO THIS IN PRODUCTION!
enableEncryption: true,
enableRateLimit: true
});
// Handle code execution (with security checks)
server.on('connection', (client) => {
client.on('message', async (message) => {
if (message.type === 'execute_code') {
try {
// Security validation
if (message.code.length > 10000) {
throw new Error('Code too large');
}
// Dangerous patterns check
const dangerous = /require|fs\.|process\.|eval\(/;
if (dangerous.test(message.code)) {
throw new Error('Dangerous code pattern detected');
}
// Execute in sandbox
const vm = new VM({
timeout: 5000,
sandbox: {
console: { log: (...args) => console.log('[VM]', ...args) },
Math, Date, JSON, Array, Object
}
});
const result = vm.run(message.code);
client.send({
type: 'execution_result',
success: true,
result: result
});
} catch (error: any) {
client.send({
type: 'execution_error',
success: false,
error: error.message
});
}
}
});
});
// Client (also dangerous if not trusted)
const client = new Client({
address: 'localhost:8080',
token: 'secret',
enableEncryption: true
});
client.send({
type: 'execute_code',
code: `
// Safe example: mathematical computation
const fibonacci = (n) => n <= 1 ? n : fibonacci(n-1) + fibonacci(n-2);
const result = {
fibonacci_10: fibonacci(10),
timestamp: Date.now(),
calculation: Math.pow(2, 8) + Math.PI
};
result;
`
});- Web applications open to internet
- Multi-user systems
- Financial applications
- Healthcare systems
- Government systems
- Any system handling sensitive data
Use only in: Isolated development environments, educational demos, trusted internal networks with proper security controls.
Contributions are welcome! Please feel free to submit a Pull Request.
ISC
Made with β€οΈ by @onurege3467