diff --git a/docs/website/docs.html b/docs/website/docs.html
index 798b45e..fd1d31c 100644
--- a/docs/website/docs.html
+++ b/docs/website/docs.html
@@ -101,6 +101,7 @@
+
@@ -141,6 +142,7 @@
Configuration — Config Editor with two-phase safe apply, batch configuration across devices, bulk CLI commands, reusable templates, Simple Config (Linksys/Ubiquiti-style UI), and git-backed config backup with diff viewer.
Monitoring — Interactive network topology (ReactFlow + Dagre), real-time metrics via SSE/NATS, configurable alert rules, notification channels (email, webhook, Slack), audit trail, KMS transparency dashboard, and PDF reports.
Security — 1Password-style zero-knowledge architecture with SRP-6a auth, 2SKD key derivation, Secret Key with Emergency Kit, OpenBao KMS for per-tenant envelope encryption, Internal CA with SFTP cert deployment, WireGuard VPN, and AES-256-GCM credential encryption.
+ Remote Access — One-click WinBox tunnel launch via NATS request-reply, browser-based SSH terminal (xterm.js over WebSocket), per-device session management with idle timeouts, and full audit logging of remote sessions.
Administration — Full multi-tenancy with PostgreSQL RLS, user management with RBAC, API keys (mktp_ prefix), firmware management, maintenance windows, and setup wizard.
UX — Command palette (Cmd+K), Vim-style keyboard shortcuts, dark/light mode, Framer Motion page transitions, and shimmer skeleton loaders.
@@ -452,6 +454,7 @@ open http://localhost
reports | PDF report generation (Jinja2 + WeasyPrint) |
api_keys | API key management (mktp_ prefix) |
maintenance_windows | Scheduled maintenance with alert suppression |
+ remote_access | WinBox tunnel and SSH terminal session management |
vpn | WireGuard VPN management |
certificates | Internal CA and device TLS certificates |
transparency | KMS access event dashboard |
@@ -468,6 +471,8 @@ open http://localhost
Circuit breaker: Backs off from unreachable devices to avoid wasting poll cycles
Credential decryption: OpenBao Transit with LRU cache (1024 entries, 5min TTL) to minimize KMS calls
Output: Publishes poll results to NATS JetStream; the API’s NATS subscribers process and persist them
+ Remote access: Tunnel manager allocates TCP ports (49000–49004) for WinBox sessions; SSH relay server bridges WebSocket connections to RouterOS SSH via PTY
+ NATS responder: Listens on tunnel.open.* / tunnel.close.* for API-initiated WinBox tunnel requests
Database access: Uses poller_user role which bypasses RLS (needs cross-tenant device access)
Memory limit: 256 MB
@@ -503,7 +508,8 @@ open http://localhost
- Image:
nats:2-alpine
- Role: Message bus between the Go poller and the Python API
- - Streams: DEVICE_EVENTS (poll results, status changes), ALERT_EVENTS (SSE delivery), OPERATION_EVENTS (SSE delivery)
+ - Streams: DEVICE_EVENTS (poll results, status changes), ALERT_EVENTS (SSE delivery), OPERATION_EVENTS (SSE delivery), AUDIT_EVENTS (session lifecycle)
+ - Request-reply:
tunnel.open.* and tunnel.close.* subjects for WinBox tunnel management between API and poller
- Durable consumers: Ensure no message loss during API restarts
- Memory limit: 128 MB
@@ -555,6 +561,8 @@ open http://localhost
| NATS Monitor | 8222 | 8222 | HTTP |
| OpenBao | 8200 | 8200 | HTTP |
| WireGuard | 51820 | 51820 | UDP |
+ | WinBox Tunnels | 49000–49004 | 49000–49004 | TCP |
+ | SSH Relay (WebSocket) | 2222 | 2222 | TCP |
@@ -821,6 +829,14 @@ open http://localhost
+ Remote Access Buttons
+ The device detail page includes WinBox and SSH buttons for one-click remote access:
+
+ - WinBox — Opens a WinBox tunnel via NATS request-reply. The poller allocates a local TCP port and proxies traffic to the device’s WinBox port. A
winbox:// URI is returned to launch the WinBox application.
+ - SSH — Opens an in-browser SSH terminal powered by xterm.js. The connection is bridged through a WebSocket to the poller’s SSH relay, which creates a PTY session on the target device.
+
+ Both session types have configurable idle timeouts (WinBox: 5 min, SSH: 15 min) and are fully audit-logged.
+
Simple Config
Simple Config provides a consumer-router-style interface modeled after Linksys and Ubiquiti UIs. It is designed for operators who prefer guided configuration over raw RouterOS paths.
Seven category tabs:
@@ -853,6 +869,70 @@ open http://localhost
Safe Apply is strongly recommended for firewall rules and routing changes on remote devices.
+
+
+ Remote Access
+ TOD provides browser-based remote access to RouterOS devices without exposing management ports to the internet. Two access methods are available from the device detail page.
+
+ WinBox Tunnels
+ Click the WinBox button on any device to open a temporary TCP tunnel:
+
+ - The API sends a NATS request to the poller on
tunnel.open.{device_id}.
+ - The poller allocates a port from the pool (49000–49004) and opens a bidirectional TCP proxy to the device’s WinBox port (8291).
+ - The API returns a
winbox:// URI that launches your local WinBox application.
+ - The tunnel closes automatically after 5 minutes of idle time, or when explicitly closed.
+
+
+ SSH Terminal
+ Click the SSH button to open an in-browser terminal:
+
+ - The API generates a single-use session token stored in Redis (60-second TTL).
+ - The frontend connects to the poller’s WebSocket endpoint with the token.
+ - The poller’s SSH relay authenticates the token, establishes an SSH connection to the device, and bridges the WebSocket to a PTY session.
+ - The terminal renders in the browser using xterm.js with full color and resize support.
+ - Sessions close after 15 minutes of idle time.
+
+
+ Architecture
+ Browser API NATS Poller RouterOS
+ | | | | |
+ +--WinBox btn->| | | |
+ | +--req tunnel.open----------->| |
+ | | | +--TCP proxy--->|
+ | |<--{port, uri}---------------+ |
+ |<--winbox://->+ | | |
+ | | | | |
+ +--SSH btn---->| | | |
+ | +--token to Redis | |
+ |<--ws url-----+ | | |
+ +--WebSocket-------------------------------------->| |
+ | | | +--SSH session->|
+ |<-------- bidirectional PTY bridge -------->|<------------>|
+
+ Session Management
+
+
+ | Feature | WinBox Tunnel | SSH Terminal |
+
+
+ | Idle timeout | 5 minutes | 15 minutes |
+ | Port range | 49000–49004 | N/A (WebSocket) |
+ | Auth method | NATS request-reply | Single-use Redis token (60s TTL) |
+ | Audit logged | Yes (open/close) | Yes (open/close with duration) |
+ | RBAC | Operator+ | Operator+ |
+
+
+
+ Security
+
+ - WinBox tunnels are only accessible from the poller’s host (bound to
0.0.0.0 within the container network).
+ - SSH session tokens are single-use, expire in 60 seconds, and are validated + deleted atomically in Redis.
+ - All session open/close events are written to the immutable audit trail.
+ - SSH session end events are published to NATS JetStream for durable processing.
+ - Rate limited: 5 tunnel/session requests per minute per IP.
+
+
+
Monitoring & Alerts
@@ -1134,6 +1214,7 @@ open http://localhost
| Reports | /api/reports/* | PDF report generation (Jinja2 + WeasyPrint) |
| API Keys | /api/api-keys/* | API key CRUD |
| Maintenance Windows | /api/maintenance-windows/* | Scheduled maintenance window management |
+ | Remote Access | /api/tenants/{id}/devices/{id}/remote-access/* | WinBox tunnel and SSH terminal session management |
| VPN | /api/vpn/* | WireGuard VPN tunnel management |
| Certificates | /api/certificates/* | Internal CA and device certificate management |
| Transparency | /api/transparency/* | KMS access event dashboard |
diff --git a/docs/website/index.html b/docs/website/index.html
index 1c350b8..cde2894 100644
--- a/docs/website/index.html
+++ b/docs/website/index.html
@@ -51,7 +51,8 @@
"Two-phase configuration push with panic-revert",
"Multi-tenant PostgreSQL Row-Level Security",
"Internal Certificate Authority",
- "Firmware management and audit trail"
+ "Firmware management and audit trail",
+ "Browser-based WinBox tunnels and SSH terminal"
],
"softwareRequirements": "Docker, PostgreSQL 17, Redis, NATS"
}
@@ -177,6 +178,7 @@
Manage firmware upgrades
Discover and visualize network topology
Maintain secure backups of router configurations
+ Launch WinBox sessions and SSH terminals directly from the browser
Everything in one place.