Files
Borealis-Github-Replica/Docs/vpn-and-remote-access.md

16 KiB

VPN and Remote Access

Back to Docs Index | Index (HTML)

Purpose

Document Borealis remote access features: WireGuard reverse VPN tunnels, remote PowerShell, and VNC via noVNC.

WireGuard Reverse VPN (High Level)

  • Outbound-only: agents initiate tunnels to the Engine; no inbound listeners on devices.
  • Transport: WireGuard UDP 30000.
  • One persistent tunnel per agent, established at agent boot and shared across operators.
  • Host-only routing: each agent gets a /32; no client-to-client routes.
  • Keepalive: PersistentKeepalive = 30 seconds on the agent.
  • No idle teardown while the agent service is running.
  • Per-device allowlist: ports are restricted per device and enforced by Engine firewall rules.

Remote PowerShell

  • Uses the WireGuard tunnel and a TCP shell server on the agent.
  • UI establishes sessions via /api/shell/establish and disconnects via /api/shell/disconnect.
  • Engine bridges UI Socket.IO events to the agent TCP shell.
  • Shell port default: 47002 (configurable).

VNC via noVNC

  • Engine issues one-time VNC session tokens via /api/vnc/establish.
  • WebUI connects to ws(s)://<engine_host>:4823/vnc.
  • VNC allowed only if the device allowlist includes 5900.
  • Agent runs UltraVNC as a Windows service; Borealis opens the VNC firewall rule on demand and closes it via /api/vnc/disconnect.

Reverse Proxy Configuration

Traefik dynamic config (replace service URL with the actual Borealis Engine URL):

http:
  routers:
    borealis:
      entryPoints:
        - websecure
      tls:
        certResolver: letsencrypt
      service: borealis
      rule: "Host(`borealis.example.com`) && PathPrefix(`/`)"
      middlewares:
        - cors-headers

  middlewares:
    cors-headers:
      headers:
        accessControlAllowOriginList:
          - "*"
        accessControlAllowMethods:
          - GET
          - POST
          - OPTIONS
        accessControlAllowHeaders:
          - Content-Type
          - Upgrade
          - Connection
        accessControlMaxAge: 100
        addVaryHeader: true

  services:
    borealis:
      loadBalancer:
        servers:
          - url: "http://127.0.0.1:5000"
        passHostHeader: true

API Endpoints

  • POST /api/tunnel/connect (Token Authenticated) - ensure WireGuard tunnel material for an agent.
  • GET /api/tunnel/status (Token Authenticated) - tunnel status by agent.
  • GET /api/tunnel/active (Token Authenticated) - list active tunnels.
  • POST /api/agent/vpn/ensure (Device Authenticated) - agent-side persistent tunnel bootstrap.
  • GET /api/device/vpn_config/<agent_id> (Token Authenticated) - read allowed ports.
  • PUT /api/device/vpn_config/<agent_id> (Token Authenticated) - update allowed ports.
  • POST /api/vnc/establish (Token Authenticated) - establish VNC session token.
  • POST /api/vnc/disconnect (Token Authenticated) - disconnect VNC session (closes firewall).
  • POST /api/shell/establish (Token Authenticated) - establish remote shell session.
  • POST /api/shell/disconnect (Token Authenticated) - disconnect remote shell session.

Codex Agent (Detailed)

Core Engine files

  • Tunnel service: Data/Engine/services/VPN/vpn_tunnel_service.py.
  • WireGuard server manager: Data/Engine/services/VPN/wireguard_server.py.
  • Tunnel API: Data/Engine/services/API/devices/tunnel.py.
  • Shell bridge: Data/Engine/services/WebSocket/vpn_shell.py.
  • VNC session API: Data/Engine/services/API/devices/vnc.py.
  • VNC proxy: Data/Engine/services/RemoteDesktop/vnc_proxy.py.

Core Agent files

  • WireGuard client role: Data/Agent/Roles/role_WireGuardTunnel.py.
  • Remote PowerShell role: Data/Agent/Roles/role_RemotePowershell.py.
  • VNC role: Data/Agent/Roles/role_VNC.py.

Config paths

  • Engine WireGuard config: Engine/WireGuard/borealis-wg.conf.
  • Agent WireGuard config: Agent/Borealis/Settings/WireGuard/Borealis.conf.
  • Engine WireGuard keys: Engine/Certificates/VPN_Server/.
  • Agent WireGuard keys: Agent/Borealis/Certificates/VPN_Client/.

Service names (Windows)

  • Engine listener service: WireGuardTunnel$borealis-wg.
  • Agent tunnel service: WireGuardTunnel$Borealis.
  • Adapter name in Control Panel: Borealis.
  • Display names:
    • Borealis - WireGuard - Engine
    • Borealis - WireGuard - Agent

Event flow (WireGuard tunnel)

  1. Agent calls /api/agent/vpn/ensure at boot (and periodically) to establish the persistent tunnel.
  2. Engine creates or reuses the tunnel session and emits vpn_tunnel_start.
  3. Agent verifies the token signature and starts the WireGuard client with PersistentKeepalive = 30.
  4. Engine applies firewall allowlist rules for the agent /32.
  5. UI sessions (shell/VNC) reuse the existing tunnel without teardown.

Event flow (Remote PowerShell)

  1. UI opens a shell and emits vpn_shell_open.
  2. Engine checks tunnel status and agent socket readiness.
  3. Engine opens a TCP connection to agent shell on port 47002.
  4. UI sends vpn_shell_send; Engine forwards to agent over TCP.
  5. Agent returns stdout frames; Engine emits vpn_shell_output.

Allowed ports and ACL rules

  • Default allowlist (Windows): 5985, 5986, 5900, 3478, 47002.
  • Per-device overrides are stored in device_vpn_config.
  • Engine creates outbound firewall rules for each allowed port and protocol.

Persistent tunnel behavior

  • WireGuard sessions stay online while the agent service is running.
  • There are no tunnel-disconnect endpoints; only role-level disconnects (shell/VNC) exist.
  • The tunnel and per-device firewall rules remain in place while the agent runs.
  • Keepalive is handled by WireGuard (PersistentKeepalive = 30 seconds).
  • The agent periodically calls /api/agent/vpn/ensure to heal the tunnel if it drops.

Logs to inspect

  • Engine tunnel log: Engine/Logs/VPN_Tunnel/tunnel.log.
  • Engine shell log: Engine/Logs/VPN_Tunnel/remote_shell.log.
  • Agent tunnel log: Agent/Logs/VPN_Tunnel/tunnel.log.
  • Agent shell log: Agent/Logs/VPN_Tunnel/remote_shell.log.

Troubleshooting checklist

  • Confirm WireGuard service is running (Engine and Agent).
  • Confirm the agent successfully calls /api/agent/vpn/ensure after boot.
  • Confirm /api/tunnel/status returns status=up and agent_socket=true.
  • Verify Agent/Borealis/Settings/WireGuard/Borealis.conf during an active session.
  • Test TCP shell reachability: Test-NetConnection <agent_vpn_ip> -Port 47002.

Known limitations

  • Legacy WebSocket tunnels are retired; only WireGuard is supported.
  • VNC requires UltraVNC running on the agent and port 5900 allowed in VPN config.

Reverse VPN Tunnels (WireGuard) - Full Reference

1) High-level model

  • Outbound-only: agents establish WireGuard tunnels to the Engine; no inbound access on devices.
  • Transport: WireGuard/UDP on port 30000.
  • Sessions: one persistent VPN tunnel per agent; multiple operators share it.
  • Routing: host-only /32 per agent; AllowedIPs restricted to the agent /32 and engine /32; no client-to-client.
  • Keepalive: PersistentKeepalive = 30 seconds; tunnels stay up while agents run.
  • Keys: WireGuard server keys under Engine/Certificates/VPN_Server; client keys under Agent/Borealis/Certificates/VPN_Client.

2) Engine components

  • Orchestrator: Data/Engine/services/VPN/vpn_tunnel_service.py
    • Allocates per-agent /32, issues short-lived orchestration tokens, enforces single-session.
    • Keeps the WireGuard listener online, applies firewall rules, and avoids idle teardown in persistent mode.
    • Emits Socket.IO events: vpn_tunnel_start, vpn_tunnel_stop, vpn_tunnel_activity.
  • WireGuard manager: Data/Engine/services/VPN/wireguard_server.py
    • Generates server keys, renders config, manages wireguard.exe tunnel service, applies ACL rules.
  • PowerShell bridge: Data/Engine/services/WebSocket/vpn_shell.py
    • Proxies UI shell input/output to the agent's TCP shell server over WireGuard.
  • Logging: Engine/Logs/VPN_Tunnel/tunnel.log plus Device Activity entries; shell I/O is in Engine/Logs/VPN_Tunnel/remote_shell.log.

3) API endpoints

  • POST /api/tunnel/connect -> issues or reuses session material (tunnel_id, token, virtual_ip, endpoint, allowed_ports).
  • GET /api/tunnel/status -> returns up/down status for an agent.
  • GET /api/tunnel/active -> lists active VPN tunnel sessions (tunnel_id, agent_id, virtual_ip, last_activity, etc.).
  • POST /api/agent/vpn/ensure -> device-authenticated tunnel bootstrap for persistent mode.
  • POST /api/shell/establish -> establish remote shell session.
  • POST /api/shell/disconnect -> disconnect remote shell session.
  • POST /api/vnc/establish -> establish VNC session token.
  • POST /api/vnc/disconnect -> disconnect VNC session (closes firewall).
  • GET /api/device/vpn_config/<agent_id> -> read per-agent allowed ports.
  • PUT /api/device/vpn_config/<agent_id> -> update allowed ports.

4) Agent components

  • Tunnel lifecycle: Data/Agent/Roles/role_WireGuardTunnel.py
    • Validates orchestration tokens, starts WireGuard client service, keeps the tunnel persistent.
  • Shell server: Data/Agent/Roles/role_RemotePowershell.py
  • TCP PowerShell server bound to 0.0.0.0:47002, restricted to VPN subnet (10.255.x.x).
  • Logging: Agent/Logs/VPN_Tunnel/tunnel.log (tunnel lifecycle) and Agent/Logs/VPN_Tunnel/remote_shell.log (shell I/O).

5) Security and auth

  • TLS pinned for Engine API and Socket.IO.
  • Orchestration tokens signed via Engine Ed25519 key; agent verifies signatures and stores the signing key.
  • WireGuard AllowedIPs /32; no LAN routes; client-to-client blocked.
  • Engine firewall rules enforce per-device allowed ports.

6) UI

  • Device details now include an "Advanced Config" tab for per-device allowed ports.
  • PowerShell MVP reuses Data/Engine/web-interface/src/Devices/ReverseTunnel/Powershell.jsx with WireGuard APIs and VPN shell events.

7) Extending to new protocols

  • Add protocol ports to the device allowlist and UI toggles.
  • Reuse the existing VPN tunnel; no new transport/domain lanes required.

8) Legacy removal

  • WebSocket tunnel domains, protocol handlers, and domain limits are removed.
  • No /tunnel Socket.IO namespace or framed protocol messages remain.

9) Change log (not exhaustive)

  • 2025-11-30: Legacy WebSocket tunnel scaffold introduced (lease manager, framing, tokens).
  • 2025-12-06: Legacy PowerShell handler simplified to pipes-only; UI status tweaks.
  • 2025-12-18: Legacy domain lanes added (remote-interactive-shell, remote-management, remote-video) with limits.
  • 2025-12-20: WireGuard reverse VPN migration complete; legacy WebSocket tunnels retired; VPN shell bridge and new APIs.

WireGuard Troubleshooting Handoff (Full)

This section consolidates the troubleshooting context and environment notes for WireGuard tunnel investigations. It is written as reference material only (no standalone prompts).

Environment and scope

  • Workspace: D:\Github\Borealis (local project root for the Engine)
  • Host OS: Windows 10/11 (build 26200). Engine runs on this machine.
  • Remote Agent: mounted read-only at Z:\ (maps to C:\Borealis on the remote device; logs/configs under Z:\Agent...).
  • Agent and Engine launch: via Borealis.ps1, always elevated as admin.
  • Network: Engine on 10.0.0.54; remote agent uses server_url.txt to derive endpoint host.
  • WireGuard version: wireguard.exe 0.5.3, wg.exe 1.0.20210914.
  • PIA (Private Internet Access) is installed and supplies a wintun driver (pia-wintun.sys). Do NOT treat the PIA adapter as the Borealis adapter.

Desired behavior

  • Agent has a dedicated WireGuard adapter named "Borealis".
  • Adapter provisioning is idempotent: if "Borealis" exists, do not recreate it.
  • Configs must live inside the project root:
    • Agent: Agent\Borealis\Settings\WireGuard\Borealis.conf
    • Engine: Engine\WireGuard\borealis-wg.conf
  • Agent ensures the WireGuard tunnel on boot via /api/agent/vpn/ensure, then remote shell/VNC/SSH flow through it.
  • No idle teardown; tunnels and firewall rules stay in place while the agent is running.

Recent changes (current repo state)

  • Data/Agent/Roles/role_WireGuardTunnel.py
    • Lazy client init (avoid side effects on import).
    • Service name fix: WireGuard tunnel service is "WireGuardTunnel$Borealis".
    • Endpoint override: if Engine sends localhost, use host from server_url.txt and port from the token.
    • Config path preference: Agent\Borealis\Settings\WireGuard.
    • Service display name set to "Borealis - WireGuard - Agent".
    • Persistent tunnels with PersistentKeepalive = 30.
    • Applies the VPN shell firewall rule using the engine /32 from allowed_ips.
  • Data/Engine/services/VPN/wireguard_server.py
    • Engine config path: Engine\WireGuard\borealis-wg.conf (project root only).
    • Removed invalid "SaveConfig = false" line (WireGuard rejected it).
    • Service display name set to "Borealis - WireGuard - Engine".
    • Ensures the listener service is running after install, and raises if it fails.
  • Borealis.ps1
    • Service name interpolation fixed to include the literal "$" in "WireGuardTunnel$Borealis".

Note: Data/Agent changes only apply after Borealis.ps1 re-stages the agent under Agent.

Current symptoms (2026-01-14 00:05)

  • Tunnel handshakes are healthy; TCP shell connectivity succeeds after adding a firewall rule for TCP/47002 from the engine /32.
  • The firewall rule is now applied/removed by role_WireGuardTunnel.py using the engine /32 in the allowed_ips payload.
  • wireguard.exe /dumplog /tail still fails with "Stdout must be set" when run from PowerShell (use file redirection).

Key paths

  • Agent WireGuard role: Data/Agent/Roles/role_WireGuardTunnel.py
  • Agent VPN shell role: Data/Agent/Roles/role_RemotePowershell.py
  • Engine WireGuard manager: Data/Engine/services/VPN/wireguard_server.py
  • Engine tunnel service: Data/Engine/services/VPN/vpn_tunnel_service.py
  • Agent tunnel logs: Z:\Agent\Logs\VPN_Tunnel\tunnel.log
  • Agent shell logs: Z:\Agent\Logs\VPN_Tunnel\remote_shell.log
  • Engine tunnel logs: Engine\Logs\VPN_Tunnel\tunnel.log
  • Engine shell logs: Engine\Logs\VPN_Tunnel\remote_shell.log
  • Agent WireGuard config: Z:\Agent\Borealis\Settings\WireGuard\Borealis.conf
  • Engine WireGuard config: Engine\WireGuard\borealis-wg.conf

Known WireGuard services and names

  • Engine listener service name: "WireGuardTunnel$borealis-wg"
  • Agent tunnel service name: "WireGuardTunnel$Borealis"
  • Adapter name in Control Panel: "Borealis"
  • Service display names:
    • "Borealis - WireGuard - Engine"
    • "Borealis - WireGuard - Agent"

Suggested verification commands

  • Engine service status:
    • Get-Service -Name "WireGuardTunnel$borealis-wg"
    • sc.exe query "WireGuardTunnel$borealis-wg"
    • netstat -ano -p udp | findstr :30000
  • Engine WireGuard log tail:
    • cmd /c ""C:\Program Files\WireGuard\wireguard.exe" /dumplog /tail > %TEMP%\wg-tail.log"
    • powershell -NoProfile -Command "& 'C:\Program Files\WireGuard\wireguard.exe' /dumplog /tail 2>&1 | Out-File $env:TEMP\wg-tail.log"
  • Agent tunnel state (remote, via Z:\ logs):
    • Z:\Agent\Logs\VPN_Tunnel\tunnel.log
    • Z:\Agent\Logs\VPN_Tunnel\remote_shell.log
    • Z:\Agent\Borealis\Settings\WireGuard\Borealis.conf

Current blockers and next steps

  1. Ensure the agent runtime is re-staged so role_WireGuardTunnel.py applies the shell firewall rule on tunnel start.
  2. During an active session, run Test-NetConnection -ComputerName 10.255.0.2 -Port 47002 on the Engine and confirm it reaches the agent.
  3. Confirm Agent\Borealis\Settings\WireGuard\Borealis.conf includes a [Peer] with endpoint/AllowedIPs while the agent is running.
  4. Capture engine and agent tunnel/shell logs around a failed shell open attempt and re-check WireGuard service state if issues persist.