Skip to content

Instantly share code, notes, and snippets.

@lexfrei
Created March 5, 2026 22:07
Show Gist options
  • Select an option

  • Save lexfrei/c69dd83ddb2935edf47e05d15ba3021a to your computer and use it in GitHub Desktop.

Select an option

Save lexfrei/c69dd83ddb2935edf47e05d15ba3021a to your computer and use it in GitHub Desktop.
OpenNebula VNC proxy chain through FireEdge + Guacamole — architecture analysis

OpenNebula VNC Proxy Chain: FireEdge + Guacamole Architecture

Components

  1. Browser — HTML5 client (Guacamole.js)
  2. FireEdge (Node.js) — frontend server, also WebSocket proxy
  3. guacd (opennebula-guacd) — native Guacamole proxy daemon, port 4822
  4. SSH tunnel — created by FireEdge when needed
  5. Hypervisor — QEMU/KVM VNC on port from GRAPHICS/PORT (usually 5900+)

Full Chain

Browser (Guacamole.js)
    │
    │  WebSocket (wss://)
    ▼
FireEdge (:2616)
    │
    │  1. GET /api/vm/:id/guacamole/vnc
    │     → createTokenServerAdmin()
    │     → XML-RPC to oned → get VM info
    │     → extract HOSTNAME and GRAPHICS/PORT
    │     → encrypt connection settings (AES-256-CBC)
    │     → return token to client
    │
    │  2. WebSocket /guacamole
    │     → decrypt token
    │     → if no direct access to hypervisor:
    │        → SSH tunnel (localhost:random_port → hypervisor:vnc_port)
    │     → pass settings to guacd
    │
    │  Guacamole protocol (TCP)
    ▼
guacd (:4822)
    │
    │  VNC protocol (TCP)
    │  (directly to hypervisor OR through SSH tunnel)
    ▼
Hypervisor (HOSTNAME:GRAPHICS_PORT)
    │
    │  QEMU VNC
    ▼
VM console

Key Details

VM Host/Port Discovery

Source: src/fireedge/src/server/routes/api/vm/functions.js

  • hostname = VM.HISTORY_RECORDS.HISTORY[-1].HOSTNAME (last hypervisor where VM is running)
  • port = VM.TEMPLATE.GRAPHICS.PORT (defaults to 5900)
  • password = VM.TEMPLATE.GRAPHICS.PASSWD

SSH Tunnel (when no direct access)

Source: src/fireedge/src/server/utils/sshTunnel.js

  • Finds an available port in range 5900–6100 on the FireEdge host
  • Creates SSH local port forwarding: ssh -L localPort:localhost:vncPort hypervisor
  • guacd connects to localhost:localPort instead of hypervisor:vncPort
  • SSH process PID is stored for cleanup when the session closes

Federation (multi-zone)

Source: src/fireedge/src/server/routes/websockets/guacamoleProxy.js

  • Proxies WebSocket requests between zones
  • Determines target zone from URL parameter
  • If zone has its own FireEdge URL — proxies there
  • If not — constructs URL from zone's RPC endpoint

Encryption

Source: src/fireedge/src/server/routes/websockets/guacamole.js

  • Connection settings encrypted with AES-256-CBC using key from /var/lib/one/.one/fireedge_key
  • Token is passed to the client, then decrypted by guacd handler on WebSocket connection

Important Note on HOSTNAME

When a VM starts on a hypervisor, GRAPHICS/PORT is assigned by QEMU, and HOSTNAME is the hypervisor address from VM history. guacd needs network access to the hypervisor (directly or through the SSH tunnel that FireEdge creates automatically). If localhost or 127.0.0.1 is returned as hostname — guacd will try to connect to itself, which breaks VNC.

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment