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:

  1. Absolute path: If path is absolute, use as-is
  2. Relative to LootDir: Check in session's loot directory
  3. 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

  1. Open the desktop client
  2. Navigate to Remote Consoles window
  3. Enter WebSocket URL: wss://localhost:5001
  4. Click Connect
  5. Authentication happens automatically using your license
  6. 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
  1. Check port availability:
netstat -an | findstr 5001
  1. Verify firewall allows port 5001
  2. Test with localhost first: wss://localhost:5001
  3. Check certificate is valid (not expired)

Authentication Failures

Problem: Client receives authentication error

Solutions:

  1. Verify license is valid and not expired
  2. Check license signature matches
  3. Ensure nonce is passed correctly
  4. Verify HMAC computation
  5. Check for clock skew between client and server

Certificate Errors

Problem: TLS certificate validation fails

Solutions:

  1. Development: Set trustAllCertsForDev: true in client
  2. Production: Install CA-signed certificate
  3. 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:

  1. Check file permissions on server
  2. Verify sufficient disk space
  3. Check network stability
  4. Review chunk timeout (30 seconds default)
  5. Examine transfer error messages
  6. Check .transfers/ directory for partial files

Performance Issues

Problem: Slow command execution or high latency

Solutions:

  1. Check network latency between client and server
  2. Reduce message size if possible
  3. Use compression for large outputs
  4. Limit number of concurrent connections
  5. Monitor server CPU and memory usage
  6. 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


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