Skip to content

System Architecture ​

Purpose of the platform ​

The Cyber Range gives BSIT Network & Cybersecurity students on-demand, isolated, hands-on labs in the browser, scores their progress automatically, and gives instructors and admins the tools to monitor, review and operate it. It runs on a single Oracle Cloud (OCI) Ampere virtual machine.

High-level architecture ​

Major components ​

ComponentWhat it doesRuns whereListens onSource
PortalAll web pages; edge middleware for login and role redirects; server-side BFF routes that proxy to the API; DVWA reverse proxy that also detects Scenario 2 attacksHost, systemd user unit cyberrange-portal10.115.77.1:3000cyberrange/portal/
Provisioning APILab lifecycle (create, status, destroy), scoring, progress, reviews, instructor and admin endpoints, background reaper and score pollerHost, user unit cyberrange-provision-api10.115.77.1:5000cyberrange/src/provisioning/
Terminal bridgeWebSocket server that authenticates the user and streams an lxc exec shell (inside tmux) to xterm.jsHost, user unit cyberrange-ssh-bridge10.115.77.1:8765cyberrange/bridge-src/bridge.py
SQLite databaseLabs, scores, reviews, audit log, lab sessions, alert snapshots, evidence image metadataHost file ~/cyberrange-data/pod_mgmt.db (default path)n/acyberrange/src/provisioning/db.py, schema/
LXD + OVNCreates and deletes containers and per-lab networksHost (snap)Unix socketcyberrange/src/provisioning/provision.py, pod_net.py
Gateway nginxSingle public origin: routes portal, Keycloak and terminal trafficguacamole LXD container10.115.77.12:80cyberrange/deploy/guacamole/nginx-ampere.conf
KeycloakIdentity provider: accounts, passwords, realm roles, OIDC tokens, introspection, admin REST APIguacamole container, system unit127.0.0.1:8083 under /authcyberrange/deploy/keycloak/keycloak.service
Wazuh managerSIEM: receives agent events from the lab targets, writes alerts.jsonwazuh-manager container on mon-net10.0.40.10:1514/1515; API bound to 127.0.0.1:55000 inside the container (harden_wazuh_api.sh), proxied to host loopbackmanual/02-gateway-and-wazuh.md, deploy/host/harden_wazuh_api.sh
Lab containerskali (attacker box), meta (vulnerable server), dvwa (vulnerable web app)One set per lab on pod-<id>-net, behind the lab's egress ACL.10, .20, .30cyberrange/src/provisioning/provision.py, pod_net.py
cloudflaredOutbound tunnel publishing the gateway on the public hostnameHost, system unitoutbound onlycyberrange/deploy/systemd/cloudflared.service
Release pullerEvery 5 minutes, applies a new GitHub release ampere-live with health checks, a Wazuh certificate check and rollbackHost, user timern/acyberrange/deploy/host/pull_release.sh
Booking page backendRecords test-session bookings in a Google Sheet and emails confirmations and organizer notices; it does not create Cyber Range accounts (domain owners create them in Admin → Users)Google Apps Script, outside the hostn/acyberrange/booking/Code.gs, docs/BOOKING-ACCOUNT-PROVISIONING.md

Technology stack ​

LayerTechnologies
FrontendNext.js 15.5 (App Router), React 19, TypeScript 5, Tailwind CSS 3, NextAuth 4, xterm.js 6, react-markdown with rehype-sanitize, zustand
BackendPython 3, FastAPI, Pydantic, uvicorn, pylxd, requests, Pillow
TerminalPython websockets 12, lxc exec, tmux
IdentityKeycloak (realm cyber-range, client portal)
DataSQLite (WAL mode), Keycloak's own database (see Database)
InfrastructureOCI Ampere A1, Ubuntu 24.04, LXD (snap), OVN, nginx, Cloudflare Tunnel, systemd
Security monitoringWazuh 4.7.5 manager and agents
DeliveryGitHub Actions (release build, pull-request type check), GitHub Releases, host-side pull script

How the components communicate ​

FromToProtocolAuthenticationSource
BrowserCloudflareHTTPSnone at this layermanual/appendix-network-map.md
cloudflaredGateway nginxHTTP over the private bridgetunnel token (host side)cyberrange/deploy/systemd/cloudflared.service
BrowserPortal pages and /api/*HTTP via nginxNextAuth session cookiecyberrange/portal/src/middleware.ts, lib/apiProxy.ts
BrowserKeycloak /auth/...HTTP via nginxKeycloak login formcyberrange/portal/src/lib/auth.ts
Portal serverKeycloak token endpointHTTPconfidential client ID and secretcyberrange/portal/src/lib/auth.ts
Portal serverProvisioning APIHTTP to 10.115.77.1:5000Authorization: Bearer user access tokencyberrange/portal/src/lib/apiProxy.ts
Portal server (DVWA proxy)API /internal/browser-scoreHTTPX-Browser-Score-Secret shared secretcyberrange/portal/src/app/lab/dvwa/[[...path]]/route.ts
API and bridgeKeycloak introspection endpointHTTPAPI's client credentialscyberrange/src/provisioning/auth.py
BrowserTerminal bridgeWebSocket via nginxaccess token in the token query parametercyberrange/portal/src/components/terminal/XtermView.tsx
BridgeProvisioning APIHTTPuser's bearer token (ownership check)cyberrange/bridge-src/bridge.py
APILXDpylxd over the local Unix socket, plus lxc CLIhost user in the lxd groupcyberrange/src/provisioning/provision.py, pod_net.py
APIWazuh managerLXD file API (read alerts.json); HTTPS to localhost:55000 for agent lookup, status and cleanup, verified against the pinned certificate or the internal CA; lxc exec to install the return route to each lab subnetLXD control plane; Wazuh API users WAZUH_SCORING_USER (read-only) and WAZUH_PROVISION_USER (agent read and delete)cyberrange/src/provisioning/alerts_reader.py, wazuh_client.py, pod_net.py
Lab agentsWazuh managerWazuh agent protocol, TCP 1514/1515, the only traffic the lab's egress ACL lets out of the labagent keys after passwordless enrollmentmanual/06-scoring.md, pod_net.py

Where to go next ​

Sources

manual/appendix-network-map.md, manual/02-gateway-and-wazuh.md, manual/06-scoring.md, cyberrange/deploy/systemd/*.service, cyberrange/deploy/host/harden_wazuh_api.sh, cyberrange/src/provisioning/pod_net.py, cyberrange/booking/Code.gs, docs/BOOKING-ACCOUNT-PROVISIONING.md, .github/workflows/*.yml, cyberrange/deploy/guacamole/nginx-ampere.conf, cyberrange/src/provisioning/provision_api_fastapi.py, cyberrange/src/provisioning/config.py, cyberrange/portal/package.json, cyberrange/bridge-src/requirements.txt.

Cyber Range capstone documentation (Capstone 2 · Group 2 · A4102). Documents main at commit 6971373.