7.1 KiB
Remote Desktop
Holesail Browser supports VNC and RDP connections in the browser, tunneled over Holesail. VNC uses the noVNC RFB client; RDP uses node-rdpjs-2. Both are accessed from the dashboard's Remote Desktop tab.
VNC vs RDP
| Feature | VNC | RDP |
|---|---|---|
| Protocol | RFB (VNC) | RDP (Microsoft) |
| Browser client | noVNC (WebSocket → RFB) | node-rdpjs-2 (JSON bridge) |
| Performance | Good for most use cases | Moderate (JSON serialization overhead) |
| Compatibility | Any VNC server | Windows Remote Desktop, FreeRDP |
| Default port | 5900 | 3389 |
Architecture
VNC
Dashboard (noVNC / canvas)
│ WebSocket ws://127.0.0.1:23000+ (binary frames)
▼
rdp-manager.js (transparent byte pipe)
│ TCP
▼
127.0.0.1:22000+ (Holesail client tunnel)
│ P2P / Noise protocol
▼
Remote VNC server (port 5900)
For VNC, the native host is a transparent pipe — it does not interpret the RFB protocol. noVNC handles all VNC protocol logic in the browser.
RDP
Dashboard (canvas renderer)
│ WebSocket ws://127.0.0.1:23000+ (JSON frames)
▼
rdp-manager.js (node-rdpjs-2 RDP client)
│ TCP
▼
127.0.0.1:22000+ (Holesail client tunnel)
│ P2P / Noise protocol
▼
Remote RDP server (port 3389)
For RDP, node-rdpjs-2 handles the RDP protocol in the native host. Bitmap updates are serialized to JSON and sent to the browser, which renders them on a canvas. Mouse and keyboard input is sent as JSON from the browser to the native host.
Usage
Saving a connection
- Open the dashboard → Remote Desktop
- Click Add Connection
- Enter:
- Label — a name for this connection
- Type — VNC or RDP
- hs:// key — the Holesail key for the remote peer
- Port — remote port (default: 5900 for VNC, 3389 for RDP)
- Width / Height — initial display resolution
- Username — (RDP only) login username
- Password — optional; saved as base64 in
state.jsonand used automatically on reconnect
- Click Save
Connecting
- Click Connect next to a saved connection
- A viewer window opens in the dashboard
- The native host starts a Holesail tunnel to the remote peer and begins the session
Disconnecting
Click Disconnect or close the viewer. The tunnel and WebSocket server are cleaned up.
Native host commands
startRdpSession
Start a new VNC or RDP session.
Request payload:
{
"connectionId": "rdp-abc123",
"hsUrl": "hs://abc123...",
"type": "vnc",
"port": 5900,
"width": 1280,
"height": 720,
"username": "",
"passwordB64": "cGFzc3dvcmQ="
}
passwordB64 is optional. When present it is a base64-encoded UTF-8 password string used for RDP authentication.
Response payload:
{
"ok": true,
"sessionId": "rdp-session-1",
"wsPort": 23000,
"tunnelPort": 22000
}
stopRdpSession
Stop a running session.
Request payload:
{ "sessionId": "rdp-session-1" }
Response payload:
{ "ok": true }
getRdpSessions
List active sessions.
Response payload:
{
"ok": true,
"sessions": [
{ "sessionId": "rdp-session-1", "connectionId": "rdp-abc123", "type": "vnc", "wsPort": 23000 }
]
}
setRdpConnections
Save RDP/VNC connection definitions to state.json.
Request payload:
{
"connections": [
{
"id": "rdp-abc123",
"label": "Work PC",
"hsUrl": "hs://abc...",
"type": "vnc",
"port": 5900,
"width": 1280,
"height": 720,
"username": "",
"passwordB64": "cGFzc3dvcmQ="
}
]
}
passwordB64 is optional. When present it is a base64-encoded UTF-8 password string (btoa(unescape(encodeURIComponent(password)))). It is persisted in state.json and used automatically when starting a session.
WebSocket protocol
VNC
The dashboard connects to ws://127.0.0.1:<wsPort>. All frames are binary — raw RFB bytes passed transparently between noVNC and the VNC server. The native host does not interpret the protocol.
RDP
Native host → browser (connection established):
{ "type": "connected", "width": 1280, "height": 720 }
Native host → browser (bitmap updates):
{
"type": "bitmap",
"destLeft": 100,
"destTop": 50,
"destRight": 300,
"destBottom": 150,
"width": 200,
"height": 100,
"bitsPerPixel": 32,
"isCompress": false,
"data": "<base64-encoded bitmap>"
}
Native host → browser (session events):
{ "type": "close" }
{ "type": "error", "message": "Authentication failed" }
Browser → native host (mouse input):
{ "type": "mouseMove", "x": 150, "y": 75 }
{ "type": "mouseButton", "x": 150, "y": 75, "button": 1, "isDown": true }
{ "type": "mouseButton", "x": 150, "y": 75, "button": 1, "isDown": false }
Browser → native host (keyboard input):
{ "type": "keyEvent", "code": 65, "isDown": true }
{ "type": "keyEvent", "code": 65, "isDown": false }
{ "type": "keyUnicode", "code": 65, "isDown": true }
Note:
keyEventsends a scancode viasendKeyEventScancode;keyUnicodesends a Unicode code point viasendKeyEventUnicode. UsekeyEventfor special keys (arrows, function keys, modifiers) andkeyUnicodefor printable characters.
Port allocation
| Range | Usage |
|---|---|
| 22000+ | Holesail client tunnel (one per session) |
| 23000+ | WebSocket server (one per session) |
Saved connections
RDP/VNC connections are stored in state.json under rdpConnections:
{
"rdpConnections": [
{
"id": "rdp-abc123",
"label": "Work PC",
"hsUrl": "hs://abc123...",
"type": "vnc",
"port": 5900,
"width": 1280,
"height": 720,
"username": "",
"passwordB64": "cGFzc3dvcmQ="
}
]
}
passwordB64 is omitted when no password was saved. Connections are restored on startup. Active sessions are not persisted — they must be reconnected after a native host restart.
Requirements
VNC
- A VNC server on the remote machine (e.g. TigerVNC, RealVNC, macOS Screen Sharing)
- The VNC server must be accessible via a Holesail
hs://key
RDP
- Windows Remote Desktop enabled on the remote machine, or a compatible RDP server (e.g. xrdp on Linux)
- The RDP server must be accessible via a Holesail
hs://key
Troubleshooting
Connection times out
- The remote peer may be offline or the
hs://key may be wrong - Check
~/.holesail-browser/holesail-browser.logfor tunnel errors
VNC: black screen or no updates
- Verify the VNC server is running and listening on the expected port
- Try disconnecting and reconnecting
RDP: authentication fails
- Verify the username and password on the remote machine
- Ensure the remote machine has Remote Desktop enabled and the user has permission to connect
RDP: slow or choppy display
RDP performance depends on the latency of the Holesail tunnel and the speed of JSON serialization. For better performance, use VNC if the remote machine supports it.