- Agent: WS-Client mit Reconnect, Command-Handler (exec, tunnel_open/close/data)
- Backend: WS-Hub, Tunnel-Manager mit dynamischen Proxy-Ports (10000-20000)
- API: /agents/{id}/exec, /tunnel, /tunnels, /proxy/{tunnel_id}
- Binary WebSocket Messages fuer effiziente Tunnel-Daten
- gorilla/websocket (pure Go, kein CGO)
- README aktualisiert
381 lines
9.4 KiB
Markdown
381 lines
9.4 KiB
Markdown
# OPNsense RMM System
|
|
|
|
Remote Monitoring & Management System fuer OPNsense Firewalls mit WebSocket-basierter Kommunikation und TCP-Tunnel-Funktionalitaet.
|
|
|
|
## Ueberblick
|
|
|
|
Dieses System besteht aus zwei Komponenten:
|
|
|
|
- **Backend** (Go) - REST API Server mit WebSocket Hub, TLS und SQLite-Datenbank, laeuft auf einem Linux-Server
|
|
- **Agent** (Go) - Laeuft auf OPNsense/FreeBSD, sammelt Systemdaten, haelt WebSocket-Verbindung zum Backend und ermoeglicht Remote-Commands/Tunneling
|
|
|
|
## Architektur
|
|
|
|
```
|
|
┌──────────────────────┐ WebSocket + HTTPS (TLS) ┌──────────────────────┐
|
|
│ OPNsense FW │ ◄─────────────────────────────► │ RMM Backend │
|
|
│ (FreeBSD) │ wss://backend:8443/api/v1/ │ (Linux) │
|
|
│ │ agent/ws │ │
|
|
│ rmm-agent │ │ REST API │
|
|
│ - Hardware/CPU/RAM │ POST /agent/register │ WebSocket Hub │
|
|
│ - Disk/Network │ POST /agent/heartbeat │ Tunnel Manager │
|
|
│ - Services/Certs │ │ SQLite DB │
|
|
│ - WebSocket Client │ Commands: │ :8443 │
|
|
│ - Tunnel Manager │ • exec (Befehl ausfuehren) │ │
|
|
│ │ • tunnel_open/close │ 192.168.85.13 │
|
|
│ 192.168.85.33 │ • tunnel_data (TCP-Proxy) │ │
|
|
└──────────────────────┘ └──────────────────────┘
|
|
|
|
TCP-Tunnel Flow:
|
|
Browser/Client ──► Backend Proxy ──► WebSocket ──► Agent ──► OPNsense Service
|
|
(Port 10000-20000) (Binary) (Local) (z.B. :443, :22)
|
|
```
|
|
|
|
## Neue Funktionen (WebSocket/Tunnel)
|
|
|
|
### 1. Bidirektionale Kommunikation
|
|
- **WebSocket-Verbindung**: Agent baut nach Registrierung eine persistente WebSocket-Verbindung zum Backend auf
|
|
- **Automatisches Reconnect**: Bei Verbindungsabbruch mit exponential backoff
|
|
- **Ping/Pong Keepalive**: Verbindung wird automatisch überwacht
|
|
- **Command-Response-Pattern**: Backend kann Commands an Agents senden und Responses erhalten
|
|
|
|
### 2. Remote Command Execution
|
|
- **exec Command**: Backend kann Befehle auf der OPNsense ausführen lassen
|
|
- **Timeout-Support**: Configurable timeouts für Command-Execution
|
|
- **stdout/stderr Output**: Vollständige Ausgabe wird zurückgeliefert
|
|
|
|
### 3. TCP-Tunneling über WebSocket
|
|
- **tunnel_open**: Agent öffnet TCP-Verbindung zu lokalem Service (z.B. OPNsense WebUI :443)
|
|
- **Dynamische Proxy-Ports**: Backend allokiert automatisch freie Ports (10000-20000)
|
|
- **Binary WebSocket Messages**: Effiziente Datenübertragung ohne Base64-Overhead
|
|
- **Multi-Tunnel Support**: Mehrere gleichzeitige Tunnel pro Agent möglich
|
|
|
|
### 4. HTTP-Proxy durch Tunnel
|
|
- **Reverse Proxy**: `GET /api/v1/agents/{id}/proxy/{tunnel_id}/*` leitet HTTP-Traffic durch Tunnel
|
|
- **Transparent**: Browser kann direkt auf OPNsense WebUI zugreifen über Backend-URL
|
|
|
|
## Voraussetzungen
|
|
|
|
- Go 1.22+
|
|
- make
|
|
- OpenSSL (fuer manuelle Zertifikat-Generierung)
|
|
- SSH-Zugang zu den Zielservern
|
|
- gorilla/websocket Library (automatisch über go mod)
|
|
|
|
## Build
|
|
|
|
```bash
|
|
# Beide Komponenten bauen
|
|
make all
|
|
|
|
# Nur Backend (linux/amd64)
|
|
make backend
|
|
|
|
# Nur Agent (freebsd/amd64)
|
|
make agent
|
|
|
|
# Dependencies aktualisieren
|
|
cd agent && go mod tidy
|
|
cd backend && go mod tidy
|
|
|
|
# TLS-Zertifikate generieren (optional, Backend generiert automatisch)
|
|
make certs
|
|
```
|
|
|
|
Die Binaries landen in `build/`.
|
|
|
|
## Konfiguration
|
|
|
|
### Backend (`backend/config.yaml`)
|
|
|
|
```yaml
|
|
listen_addr: ":8443"
|
|
tls_cert: "certs/server.crt"
|
|
tls_key: "certs/server.key"
|
|
db_path: "rmm.db"
|
|
api_keys:
|
|
- "01532e5a7c9e70bf2757df77a2f5b9b9"
|
|
```
|
|
|
|
**Neue WebSocket-Features:**
|
|
- WebSocket-Hub läuft automatisch
|
|
- Tunnel-Manager verwaltet aktive Tunnel
|
|
- Port-Range 10000-20000 für dynamische Proxy-Ports
|
|
|
|
### Agent (`agent/config.yaml`)
|
|
|
|
```yaml
|
|
backend_url: "https://192.168.85.13:8443"
|
|
api_key: "01532e5a7c9e70bf2757df77a2f5b9b9"
|
|
interval_seconds: 60
|
|
agent_name: "opnsense-fw01"
|
|
insecure: true
|
|
```
|
|
|
|
**WebSocket wird automatisch gestartet:**
|
|
- WebSocket URL: `wss://192.168.85.13:8443/api/v1/agent/ws?agent_id=XXX&api_key=XXX`
|
|
- Reconnect mit Backoff bei Verbindungsabbruch
|
|
- Ping/Pong Keepalive alle 30s
|
|
|
|
## Deployment
|
|
|
|
### Backend (192.168.85.13)
|
|
|
|
```bash
|
|
make deploy-backend
|
|
```
|
|
|
|
Dies startet:
|
|
1. REST API Server auf :8443
|
|
2. WebSocket Hub für Agent-Verbindungen
|
|
3. Tunnel Manager für TCP-Proxies
|
|
4. SQLite-Datenbank für persistente Daten
|
|
|
|
### Agent (192.168.85.33 / OPNsense)
|
|
|
|
```bash
|
|
make deploy-agent
|
|
```
|
|
|
|
Dies startet:
|
|
1. HTTP Heartbeat-Loop (weiterhin alle 60s)
|
|
2. WebSocket-Client mit automatischem Reconnect
|
|
3. Command-Handler für eingehende Befehle
|
|
4. Tunnel-Manager für TCP-Verbindungen
|
|
|
|
## API-Dokumentation
|
|
|
|
### WebSocket Commands (Backend → Agent)
|
|
|
|
#### exec - Befehl ausführen
|
|
```json
|
|
{
|
|
"type": "command",
|
|
"id": "cmd-123",
|
|
"command": "exec",
|
|
"params": {
|
|
"command": "ps aux | head -10",
|
|
"timeout": 30
|
|
}
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"type": "response",
|
|
"id": "cmd-123",
|
|
"status": "ok",
|
|
"data": {
|
|
"output": "PID COMMAND\n1 kernel\n..."
|
|
}
|
|
}
|
|
```
|
|
|
|
#### tunnel_open - TCP-Tunnel öffnen
|
|
```json
|
|
{
|
|
"type": "command",
|
|
"id": "cmd-124",
|
|
"command": "tunnel_open",
|
|
"params": {
|
|
"target_host": "127.0.0.1",
|
|
"target_port": 443
|
|
}
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"type": "response",
|
|
"id": "cmd-124",
|
|
"status": "ok",
|
|
"data": {
|
|
"tunnel_id": "a1b2c3d4e5f6789a"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### tunnel_close - TCP-Tunnel schließen
|
|
```json
|
|
{
|
|
"type": "command",
|
|
"id": "cmd-125",
|
|
"command": "tunnel_close",
|
|
"params": {
|
|
"tunnel_id": "a1b2c3d4e5f6789a"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Neue REST API Endpoints
|
|
|
|
#### POST /api/v1/agents/{id}/exec
|
|
Befehl auf Agent ausführen.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"command": "uptime",
|
|
"timeout": 30
|
|
}
|
|
```
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"message": "Command gesendet",
|
|
"command_id": "cmd-123"
|
|
}
|
|
```
|
|
|
|
#### POST /api/v1/agents/{id}/tunnel
|
|
TCP-Tunnel zu Agent öffnen.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"target_host": "127.0.0.1",
|
|
"target_port": 443
|
|
}
|
|
```
|
|
|
|
**Response (201):**
|
|
```json
|
|
{
|
|
"tunnel_id": "a1b2c3d4e5f6789a",
|
|
"proxy_port": 12345,
|
|
"target_host": "127.0.0.1",
|
|
"target_port": 443,
|
|
"created_at": "2024-01-28T12:30:00Z"
|
|
}
|
|
```
|
|
|
|
#### DELETE /api/v1/agents/{id}/tunnel/{tunnel_id}
|
|
Tunnel schließen.
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"message": "Tunnel geschlossen"
|
|
}
|
|
```
|
|
|
|
#### GET /api/v1/agents/{id}/tunnels
|
|
Aktive Tunnel auflisten.
|
|
|
|
**Response (200):**
|
|
```json
|
|
[
|
|
{
|
|
"tunnel_id": "a1b2c3d4e5f6789a",
|
|
"proxy_port": 12345,
|
|
"target_host": "127.0.0.1",
|
|
"target_port": 443,
|
|
"active": true,
|
|
"created_at": "2024-01-28T12:30:00Z"
|
|
}
|
|
]
|
|
```
|
|
|
|
#### GET /api/v1/agents/{id}/proxy/{tunnel_id}/*
|
|
HTTP-Reverse-Proxy durch Tunnel.
|
|
|
|
**Beispiel:**
|
|
```
|
|
GET /api/v1/agents/abc123/proxy/tunnel789/
|
|
→ Leitet weiter an OPNsense WebUI (127.0.0.1:443) über Tunnel
|
|
```
|
|
|
|
#### GET /api/v1/hub/status
|
|
WebSocket Hub Status.
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"status": "running",
|
|
"connected_agents": ["abc123", "def456"],
|
|
"stats": {
|
|
"connected_agents": 2,
|
|
"active_tunnels": 3
|
|
},
|
|
"timestamp": "2024-01-28T12:30:00Z"
|
|
}
|
|
```
|
|
|
|
### WebSocket Endpoint
|
|
|
|
#### GET /api/v1/agent/ws
|
|
WebSocket-Upgrade für Agents.
|
|
|
|
**Query Parameters:**
|
|
- `agent_id`: Agent-ID (aus Registrierung)
|
|
- `api_key`: API-Key für Authentifizierung
|
|
|
|
**Usage:**
|
|
```
|
|
wss://192.168.85.13:8443/api/v1/agent/ws?agent_id=abc123&api_key=xxx
|
|
```
|
|
|
|
## Tunnel-Datenformat
|
|
|
|
### Binary WebSocket Messages
|
|
TCP-Tunnel-Daten werden als Binary Messages übertragen:
|
|
|
|
**Format:** `[tunnel_id_length:1][tunnel_id][data]`
|
|
|
|
- Byte 0: Länge der Tunnel-ID (max 255)
|
|
- Bytes 1-N: Tunnel-ID als UTF-8 String
|
|
- Bytes N+1-Ende: TCP-Payload-Daten
|
|
|
|
### Beispiel-Usage
|
|
|
|
1. **Tunnel öffnen:**
|
|
```bash
|
|
curl -X POST http://backend:8443/api/v1/agents/abc123/tunnel \
|
|
-H "X-API-Key: xxx" \
|
|
-d '{"target_host":"127.0.0.1","target_port":443}'
|
|
```
|
|
|
|
2. **Über Tunnel auf OPNsense WebUI zugreifen:**
|
|
```
|
|
# Backend allokiert Port 12345 für Tunnel
|
|
# Browser kann jetzt zugreifen über:
|
|
https://192.168.85.13:12345/
|
|
```
|
|
|
|
3. **Oder über HTTP-Proxy:**
|
|
```
|
|
https://192.168.85.13:8443/api/v1/agents/abc123/proxy/tunnel789/
|
|
```
|
|
|
|
## Technische Details
|
|
|
|
### CGO-frei
|
|
- Beide Komponenten kompilieren mit `CGO_ENABLED=0`
|
|
- Agent läuft auf FreeBSD/amd64 (OPNsense)
|
|
- Backend läuft auf Linux/amd64
|
|
- gorilla/websocket ist pure Go, kein CGO erforderlich
|
|
|
|
### Sicherheit
|
|
- TLS-verschlüsselte WebSocket-Verbindungen (WSS)
|
|
- API-Key-Authentifizierung für alle Endpoints
|
|
- Agent validiert Commands vor Ausführung
|
|
- Tunnel sind isoliert per Agent/Tunnel-ID
|
|
|
|
### Performance
|
|
- Binary WebSocket Messages für Tunnel-Daten (kein Base64-Overhead)
|
|
- Connection-Pooling für gleichzeitige Tunnel
|
|
- Effiziente Port-Allokation für Proxies
|
|
- Heartbeat läuft weiterhin parallel (für Monitoring auch ohne WS)
|
|
|
|
### Monitoring
|
|
- Agent funktioniert auch ohne WebSocket (nur Heartbeat)
|
|
- WebSocket-Verbindungsstatus wird überwacht
|
|
- Inactive Tunnel werden automatisch bereinigt
|
|
- Hub-Status zeigt Connected Agents und aktive Tunnel
|
|
|
|
## Lizenz
|
|
|
|
Intern. |