WebSocket Server
The RTFMv2 Console includes a powerful WebSocket server that enables remote command execution, real-time collaboration, and file transfer capabilities. This allows multiple clients to connect, join sessions, and execute commands remotely.
Overview
RTFMv2 provides two separate WebSocket servers for different use cases:
1. Main WebSocket Server (WSS - Secure)
- Protocol: WSS (WebSocket Secure with TLS)
- Default Port: 5001
- Authentication: License-based challenge-response
- Purpose: Secure remote client connections
- Features: Full command execution, file transfer, session management
2. Node-RED WebSocket Server (WS - Unsecured)
- Protocol: WS (Unencrypted WebSocket)
- Default Port: 5000
- Authentication: None (internal use)
- Purpose: Node-RED visual workflow integration
- Features: Command execution from Node-RED flows
- Availability: Commercial edition only
This page focuses on the Main WebSocket Server (WSS).
Starting the WebSocket Server
From Interactive Console
>> server --start
WebSocket server started on wss://0.0.0.0:5001
Start on Custom Port:
>> server --start --port 8080
WebSocket server started on wss://0.0.0.0:8080
Stopping the Server
>> server --stop
WebSocket server stopped
Checking Active Connections
>> list --connections
Active WebSocket Connections:
- User: alice, Session: pentest-123, IP: 192.168.1.50, Connected: 2024-11-14 10:30:00 UTC
- User: bob, Session: pentest-123, IP: 192.168.1.51, Connected: 2024-11-14 10:32:15 UTC

Server Configuration
Automatic TLS Certificate Generation
The WebSocket server automatically generates and manages TLS certificates:
Certificate Details:
- Location: ./certs/server.pfx
- Type: Self-signed X509 certificate
- Algorithm: ECDSA P-256
- Validity: 1 year
- Auto-Renewal: 30 days before expiration
- Password: Derived from license signature using HKDF-SHA256
Subject Alternative Names (SANs):
- localhost
- Machine hostname
- 127.0.0.1
- ::1 (IPv6 loopback)
Security: - TLS 1.2 and TLS 1.3 enabled - Enhanced Key Usage: Server Authentication - Password derived cryptographically from license
Server Settings
| Setting | Value |
|---|---|
| Default Port | 5001 |
| Protocol | WSS (WebSocket Secure) |
| Bind Address | 0.0.0.0 (all interfaces) |
| Max Message Size | 1 MB (1,000,000 bytes) |
| File Transfer Message Size | Unlimited (chunked) |
| Library | Fleck WebSocket Server |
Authentication
The WebSocket server uses a secure challenge-response authentication mechanism based on your RTFMv2 license.
Authentication Flow
1. Client connects to wss://server:5001
↓
2. Server sends challenge:
{
"type": "challenge",
"nonce": "randomBase64String=="
}
↓
3. Client derives authentication key from license:
key = HKDF-SHA256(
ikm: license.Signature,
salt: SHA256(Customer),
info: "rtfm-auth-ws-v1",
length: 32 bytes
)
↓
4. Client computes proof:
proof = HMAC-SHA256(key, nonce)
↓
5. Client sends authentication:
{
"type": "auth",
"license": {
"Customer": "CompanyName",
"ExpiresUtc": "2025-12-31T23:59:59Z",
"Signature": "base64Signature=="
},
"nonce": "sameNonceFromChallenge",
"proof": "computedHMAC==",
"userId": "username"
}
↓
6. Server validates:
- Nonce matches
- License not expired
- HMAC proof is correct
↓
7. Server responds:
{
"type": "auth-ok",
"userId": "username"
}
✓ Client is now authenticated
Security Features
- One-Time Nonce: Prevents replay attacks
- License Validation: Ensures valid RTFMv2 license
- HMAC-SHA256: Cryptographic proof of possession
- HKDF Key Derivation: Secure key generation from license
- Constant-Time Comparison: Prevents timing attacks
- Rate Limiting: 5 bad message types → disconnect
Connection Management
Session Rooms
Clients can join session rooms to collaborate and share command output.
Join a Session:
{
"type": "join",
"sessionId": "pentest-123"
}
Join Default Shared Session:
{
"type": "join",
"sessionId": "Shared"
}
Leave a Session:
{
"type": "leave"
}
Connection State
The server tracks the following for each connection:
- WebSocket connection object
- Authentication status (true/false)
- User ID
- Session ID
- Connection timestamp
- Client IP address
- Bad message counter (rate limiting)
Multiple Clients
- Multiple clients can join the same session
- Commands executed by one client are broadcast to all clients in the session
- Results are shared in real-time
- Each client maintains independent authentication
Message Types and Protocol
Message Format
All messages are JSON with the following structure:
{
"type": "messageType",
"payload": { ... },
"sessionId": "optional-session-id",
"from": "optional-user-id"
}
Available Message Types
| Type | Direction | Description |
|---|---|---|
challenge |
Server → Client | Authentication challenge with nonce |
auth |
Client → Server | Authentication response with proof |
auth-ok |
Server → Client | Authentication successful |
error |
Server → Client | Error message |
join |
Client → Server | Join session room |
joined |
Server → Client | Successfully joined session |
leave |
Client → Server | Leave current session |
left |
Server → Client | Successfully left session |
query |
Client ↔ Server | Execute command or receive result |
result |
Client → Server | Broadcast result to session |
heartbeat |
Client → Server | Keep-alive ping |
file-upload-init |
Server → Client | Initialize file transfer |
file-upload-chunk |
Server → Client | File data chunk |
file-upload-complete |
Server → Client | File transfer complete |
file-download-request |
Client → Server | Request file download |
file-transfer-error |
Server ↔ Client | File transfer error |
file-transfer-progress |
Server → Client | Transfer progress update |
Command Execution
Executing Commands Remotely
Send a Command:
{
"type": "query",
"sessionId": "pentest-123",
"from": "alice",
"payload": {
"cmd": "list --session"
}
}
Server Response (Broadcast to All Session Members):
{
"type": "query",
"sessionId": "pentest-123",
"from": "alice",
"payload": "\nSession: pentest-123\nHost: 192.168.1.0/24\n..."
}
Shell Mode Integration
The WebSocket server integrates with the console's shell mode, maintaining shell state per session:
Example: Running Shell Commands
{
"type": "query",
"sessionId": "pentest-123",
"from": "alice",
"payload": {
"cmd": "shell --cmd 'ls -la' --session-id 'pentest-123'"
}
}
Shell State Persistence:
- Working directory is tracked per session ID
- cd commands persist across multiple WebSocket commands
- Each session maintains independent shell state
Command Examples
List Available Commands:
{
"type": "query",
"payload": { "cmd": "help" }
}
Run Custom Shell Command:
{
"type": "query",
"payload": { "cmd": "run --custom 'nmap -sV 192.168.1.1'" }
}
Execute Template Attack:
{
"type": "query",
"payload": { "cmd": "template nikto --ip 192.168.1.100" }
}
Get Host Information:
{
"type": "query",
"payload": { "cmd": "hostinfo --host 192.168.1.50" }
}
File Transfer
The WebSocket server supports robust file transfer with chunking, hashing, and error recovery.
File Transfer Features
- Chunked Transfer: Files split into 256 KB chunks
- SHA-256 Validation: Entire file and each chunk validated
- Progress Tracking: Real-time progress updates
- Error Recovery: Detailed error reporting
- Large File Support: No practical size limit
- Atomic Operations: Temporary staging with atomic move on completion
Downloading Files from Server
1. Request File:
{
"type": "query",
"payload": { "cmd": "file --copy passwords.txt" }
}
2. Server Sends Initialization:
{
"type": "file-upload-init",
"payload": {
"fileName": "passwords.txt",
"fileSize": 524288,
"totalChunks": 2,
"sha256Hash": "abcd1234...base64hash",
"sessionId": "pentest-123",
"transferId": "unique-guid-12345"
}
}
3. Server Sends Chunks:
{
"type": "file-upload-chunk",
"payload": {
"fileName": "passwords.txt",
"transferId": "unique-guid-12345",
"chunkIndex": 0,
"chunkData": "base64EncodedData...",
"chunkHash": "sha256OfThisChunk...",
"sessionId": "pentest-123"
}
}
4. Server Sends Completion:
{
"type": "file-upload-complete",
"payload": {
"fileName": "passwords.txt",
"transferId": "unique-guid-12345",
"success": true,
"finalHash": "abcd1234...base64hash",
"message": "File sent successfully"
}
}
5. Client Validates:
- Reassemble chunks in order
- Compute SHA-256 of complete file
- Compare with finalHash
- Save to disk if valid
File Transfer Configuration
| Setting | Value |
|---|---|
| Chunk Size | 256 KB (262,144 bytes) |
| Timeout | 30 seconds per chunk |
| Hash Algorithm | SHA-256 |
| Encoding | Base64 |
| Storage | .transfers/ directory (staging) |
| Validation | File hash + per-chunk hash |
File Path Resolution
The server resolves file paths in this order:
- Absolute path: If path is absolute, use as-is
- Relative to LootDir: Check in session's loot directory
- Relative to working directory: Check in current shell working directory
Error Handling
File Transfer Error Message:
{
"type": "file-transfer-error",
"payload": {
"fileName": "passwords.txt",
"transferId": "unique-guid-12345",
"errorMessage": "File not found",
"errorCode": "FILE_NOT_FOUND"
}
}
Common Error Codes:
- FILE_NOT_FOUND: Requested file doesn't exist
- CHUNK_HASH_MISMATCH: Chunk integrity check failed
- FINAL_HASH_MISMATCH: Complete file hash doesn't match
- TIMEOUT: Chunk transfer timed out
- PERMISSION_DENIED: Insufficient permissions
Desktop Client Integration
The RTFMv2 desktop client includes a built-in WebSocket client interface.
Connecting from Desktop Client
- Open the desktop client
- Navigate to Remote Consoles window
- Enter WebSocket URL:
wss://localhost:5001 - Click Connect
- Authentication happens automatically using your license
- Join a session to start collaborating

Features in Desktop Client
- Real-time command output from all session members
- File transfer with progress bars
- Connection status indicator
- Multiple concurrent connections
- Session switching

Security Best Practices
1. Network Security
Firewall Rules:
# Allow only specific IPs to connect
iptables -A INPUT -p tcp --dport 5001 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 5001 -j DROP
Production Deployment: - Use reverse proxy (nginx, Apache) for additional security - Implement IP whitelisting - Consider VPN for remote access - Monitor connection logs
2. Certificate Management
Production Certificates: - Replace self-signed certificates with CA-signed certificates - Store certificates securely with restricted permissions - Rotate certificates regularly - Monitor expiration dates
Custom Certificate:
# Place your certificate in:
./certs/server.pfx
# Server will use it instead of generating self-signed
3. License Protection
- Store license files securely
- Restrict file permissions on license files
- Don't commit licenses to version control
- Audit license usage regularly
4. Connection Monitoring
# Regular monitoring
>> list --connections
# Look for:
# - Unexpected users
# - Unknown IP addresses
# - Excessive connections
# - Unusual connection times
5. Session Isolation
- Use unique session IDs per engagement
- Don't use the default "Shared" session for sensitive work
- Regularly clean up old sessions
- Audit session membership
Troubleshooting
Connection Issues
Problem: Client cannot connect to WebSocket server
Solutions: 1. Verify server is running:
>> list --connections
- Check port availability:
netstat -an | findstr 5001
- Verify firewall allows port 5001
- Test with localhost first:
wss://localhost:5001 - Check certificate is valid (not expired)
Authentication Failures
Problem: Client receives authentication error
Solutions:
- Verify license is valid and not expired
- Check license signature matches
- Ensure nonce is passed correctly
- Verify HMAC computation
- Check for clock skew between client and server
Certificate Errors
Problem: TLS certificate validation fails
Solutions:
- Development: Set
trustAllCertsForDev: truein client - Production: Install CA-signed certificate
- Add self-signed certificate to trusted store:
# Windows
certutil -addstore -f "Root" .\certs\server.pfx
# Linux
sudo cp server.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
File Transfer Issues
Problem: File transfer fails or stalls
Solutions:
- Check file permissions on server
- Verify sufficient disk space
- Check network stability
- Review chunk timeout (30 seconds default)
- Examine transfer error messages
- Check
.transfers/directory for partial files
Performance Issues
Problem: Slow command execution or high latency
Solutions:
- Check network latency between client and server
- Reduce message size if possible
- Use compression for large outputs
- Limit number of concurrent connections
- Monitor server CPU and memory usage
- Consider local execution for performance-critical tasks
Advanced Usage
Custom Message Handling
For advanced integrations, you can send custom message types:
// Send custom message
var message = new {
type = "custom",
payload = new {
action = "customAction",
data = "customData"
}
};
await client.SendAsync(JsonSerializer.Serialize(message));
Programmatic Session Management
// Automated session workflow
await client.ConnectAsync();
await client.JoinAsync($"auto-session-{DateTime.UtcNow:yyyyMMdd}");
await client.SendQueryAsync(new { cmd = "new --name AutoTest --host 192.168.1.1 --pass SecurePass" });
await client.SendQueryAsync(new { cmd = "run --custom 'nmap -sV 192.168.1.1'" });
await client.RequestFileAsync("scan-results.xml");
await client.LeaveAsync();
await client.DisconnectAsync();
Integration with CI/CD
# Example: GitLab CI
test:
script:
- RTFMv2.Console.exe server --start --port 5001 &
- sleep 5
- dotnet run --project TestClient -- wss://localhost:5001
- RTFMv2.Console.exe server --stop
Comparison: Main WSS vs Node-RED WS
| Feature | Main WSS Server | Node-RED WS Server |
|---|---|---|
| Port | 5001 (configurable) | 5000 (fixed) |
| Protocol | WSS (encrypted) | WS (unencrypted) |
| Authentication | Challenge-response | None |
| License Required | Yes | Yes (Commercial) |
| File Transfer | Full support | Not supported |
| Session Management | Full support | Basic |
| Use Case | Remote clients | Node-RED integration |
| Client Library | RtfmWsClient | WebSocket nodes |
| Message Format | Structured JSON | Instruction payload |
API Reference Summary
Server Commands
server --start [--port <port>] # Start WebSocket server
server --stop # Stop WebSocket server
list --connections # Show active connections
Message Types Quick Reference
Authentication:
- challenge → auth → auth-ok
Session:
- join → joined
- leave → left
Commands:
- query (send command)
- result (broadcast result)
File Transfer:
- file-upload-init → file-upload-chunk (multiple) → file-upload-complete
- file-download-request
- file-transfer-error
- file-transfer-progress
Maintenance:
- heartbeat
- error
Next Steps
- Learn about Console Commands you can execute remotely
- Explore Node-RED Integration for visual automation
- Review Lua Scripting for extending functionality
- Return to Console Overview
Additional Resources
- Client Library:
RTFMv2.Core.Connection.RtfmWsClient - Server Implementation:
RTFMv2.Console.Server - File Transfer:
RTFMv2.Core.FileTransfer.FileTransferManager - Desktop Client: Remote Consoles window in RTFMv2 desktop application