VNC Gateway (WebSocket → Unix socket) #45

Open
opened 2026-08-25 12:26:31 +00:00 by nicolas.boufideline · 0 comments

Objective

Implement a lightweight, high-performance proxy that bridges WebSocket connections to Unix domain sockets for VNC traffic.


Core Responsibilities

  1. Accept WebSocket connections
  2. Extract vm-id from request path
  3. Map to Unix socket path
  4. Establish bidirectional stream
  5. Handle errors and cleanup

Interface

Listen

0.0.0.0:9000

Endpoint

GET /vnc/<vm-id>

Example

/vnc/vm-123
→ /run/vnc/vm-123.sock


Routing Logic

  • Extract vm-id from URL path
  • Build socket path:

/run/vnc/<vm-id>.sock

  • No external lookup required

Validation

vm-id constraints
  • allowed: [a-zA-Z0-9-_]
  • reject:
    • ..
    • /
    • empty values

Connection Flow

  1. Upgrade HTTP → WebSocket
  2. Resolve socket path
  3. Open Unix socket connection
  4. Start bidirectional copy:

WebSocket ⇄ Unix Socket


Data Handling

  • binary transparent (no transformation)
  • low-latency streaming
  • minimal buffering

Error Handling

Condition Behavior
invalid vm-id HTTP 400
socket not found close WS / 404
permission denied close WS / 403
connection failure close WS

Resource Management

  • close both sides on error
  • detect client disconnect
  • enforce timeouts (idle + max)

Performance Requirements

  • support thousands of concurrent connections
  • non-blocking I/O
  • low memory footprint
  • efficient file descriptor usage

Security

  • strict path sanitization
  • no filesystem traversal
  • run under restricted user
  • limit access to /run/vnc

  • active connections count
  • connection duration
  • error rates
  • per-vm connection stats

Optional Features

  • rate limiting
  • connection caps per VM
  • logging (structured)

Suggested Tech Stack

  • net
  • gorilla/websocket or nhooyr.io/websocket
Alternatives
  • Rust (tokio)
  • Node.js (ws + net)

Minimal Pseudocode (Go-like)

vmID := extractID(request.URL.Path)

if !isValid(vmID) {
    reject()
}

socketPath := "/run/vnc/" + vmID + ".sock"

unixConn := net.Dial("unix", socketPath)

go copy(ws, unixConn)
go copy(unixConn, ws)

Deployment Model

  • 1 instance per host
  • runs alongside VMs
  • exposed on fixed port (e.g. 9000)

Non-Goals

  • no session management
  • no orchestration logic
  • no TLS termination
  • no load balancing

Summary

The gateway is a stateless, deterministic bridge:

  • WebSocket in
  • Unix socket out
  • routing by convention

Simple, fast, and scalable.

## Objective Implement a lightweight, high-performance proxy that bridges WebSocket connections to Unix domain sockets for VNC traffic. --- ## Core Responsibilities 1. Accept WebSocket connections 2. Extract `vm-id` from request path 3. Map to Unix socket path 4. Establish bidirectional stream 5. Handle errors and cleanup --- ## Interface ##### Listen ``` 0.0.0.0:9000 ``` ##### Endpoint ``` GET /vnc/<vm-id> ``` ##### Example ``` /vnc/vm-123 → /run/vnc/vm-123.sock ``` --- ## Routing Logic - Extract `vm-id` from URL path - Build socket path: ``` /run/vnc/<vm-id>.sock ``` - No external lookup required --- ## Validation ##### vm-id constraints - allowed: `[a-zA-Z0-9-_]` - reject: - `..` - `/` - empty values --- ## Connection Flow 1. Upgrade HTTP → WebSocket 2. Resolve socket path 3. Open Unix socket connection 4. Start bidirectional copy: ``` WebSocket ⇄ Unix Socket ``` --- ## Data Handling - binary transparent (no transformation) - low-latency streaming - minimal buffering --- ## Error Handling | Condition | Behavior | |---------------------|----------------------| | invalid vm-id | HTTP 400 | | socket not found | close WS / 404 | | permission denied | close WS / 403 | | connection failure | close WS | --- ## Resource Management - close both sides on error - detect client disconnect - enforce timeouts (idle + max) --- ## Performance Requirements - support thousands of concurrent connections - non-blocking I/O - low memory footprint - efficient file descriptor usage --- ## Security - strict path sanitization - no filesystem traversal - run under restricted user - limit access to `/run/vnc` --- ## Observability (recommended) - active connections count - connection duration - error rates - per-vm connection stats --- ## Optional Features - rate limiting - connection caps per VM - logging (structured) --- ## Suggested Tech Stack ##### Go (recommended) - `net` - `gorilla/websocket` or `nhooyr.io/websocket` ##### Alternatives - Rust (tokio) - Node.js (ws + net) --- ## Minimal Pseudocode (Go-like) ```go vmID := extractID(request.URL.Path) if !isValid(vmID) { reject() } socketPath := "/run/vnc/" + vmID + ".sock" unixConn := net.Dial("unix", socketPath) go copy(ws, unixConn) go copy(unixConn, ws) ``` --- ## Deployment Model * 1 instance per host * runs alongside VMs * exposed on fixed port (e.g. 9000) --- ## Non-Goals * no session management * no orchestration logic * no TLS termination * no load balancing --- ## Summary The gateway is a **stateless, deterministic bridge**: * WebSocket in * Unix socket out * routing by convention Simple, fast, and scalable.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
syonad/two#45
No description provided.