- Browser — HTML5 client (Guacamole.js)
- FireEdge (Node.js) — frontend server, also WebSocket proxy
- guacd (opennebula-guacd) — native Guacamole proxy daemon, port 4822
- SSH tunnel — created by FireEdge when needed
- Hypervisor — QEMU/KVM VNC on port from
GRAPHICS/PORT(usually 5900+)
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
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 to5900)password=VM.TEMPLATE.GRAPHICS.PASSWD
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:localPortinstead ofhypervisor:vncPort - SSH process PID is stored for cleanup when the session closes
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
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
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.