1096 lines
39 KiB
Markdown
1096 lines
39 KiB
Markdown
# mGuard VPN Endpoint Server
|
|
|
|
VPN-Management-System für Phoenix Contact mGuard Router mit Web-Oberfläche.
|
|
|
|
## Übersicht
|
|
|
|
Dieses System ermöglicht die zentrale Verwaltung von mGuard VPN-Gateways und den sicheren Fernzugriff auf Endpunkte (SPS, HMI, etc.) hinter diesen Gateways.
|
|
|
|
### Komponenten
|
|
|
|
| Komponente | Beschreibung |
|
|
|------------|--------------|
|
|
| **Server + Web-UI** | Docker-basiert mit FastAPI, MariaDB, OpenVPN und Web-Dashboard |
|
|
| **Desktop Client** | PyQt6 GUI-Anwendung für Techniker (Windows/Linux) |
|
|
| **Provisioning Tool** | CLI-Tool für Gateway-Provisionierung |
|
|
|
|
### Unterstützte Router
|
|
|
|
| Router | Firmware | Provisionierung |
|
|
|--------|----------|-----------------|
|
|
| FL MGUARD 2000/4000 | 10.5.x | REST API |
|
|
| FL MGUARD RS4000 | 8.9 | SSH / ATV-Datei |
|
|
| FL MGUARD 1000 | 1.x | REST API |
|
|
|
|
---
|
|
|
|
## Architektur
|
|
|
|
```
|
|
┌────────────────────────────────────────────────────────────────────────────┐
|
|
│ DOCKER COMPOSE STACK │
|
|
│ │
|
|
│ ┌──────────────────────┐ ┌───────────────────────┐ │
|
|
│ │ FastAPI Server │ │ MariaDB │ │
|
|
│ │ :8000 │ │ :3306 │ │
|
|
│ │ ├── REST API │ │ │ │
|
|
│ │ ├── Web UI (HTMX) │ │ ├── CAs │ │
|
|
│ │ └── PKI-Verwaltung │ │ ├── VPN Servers │ │
|
|
│ └──────────┬───────────┘ │ ├── VPN Profiles │ │
|
|
│ │ │ ├── Gateways │ │
|
|
│ └──────────────┴──┴── Users │ │
|
|
└─────────────────────────────────────────────────────────────────────────────┘
|
|
│
|
|
Interne API (localhost)
|
|
│
|
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
│ OpenVPN Container (Host-Netzwerk) │
|
|
│ ┌───────────────────────────────────────────────────────────────────────┐ │
|
|
│ │ supervisord │ │
|
|
│ │ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │ │
|
|
│ │ │ openvpn-1 │ │ openvpn-2 │ │ openvpn-N │ │ │
|
|
│ │ │ UDP:1194 │ │ TCP:443 │ │ UDP:1195 │ │ │
|
|
│ │ │ (Produktion) │ │ (Firewall) │ │ (Backup) │ │ │
|
|
│ │ └────────────────┘ └────────────────┘ └────────────────┘ │ │
|
|
│ └───────────────────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ Polling alle 30s: Neue Server automatisch starten/stoppen │
|
|
└─────────────────────────────────────────────────────────────────────────────┘
|
|
│
|
|
Host-Ports direkt (kein Docker NAT)
|
|
│
|
|
┌─────────────┴─────────────┐
|
|
▼ ▼
|
|
┌───────────────────┐ ┌─────────────────┐
|
|
│ mGuard Gateway │ │ Web Browser │
|
|
│ (beim Kunden) │ │ (Admin) │
|
|
└───────────────────┘ └─────────────────┘
|
|
```
|
|
|
|
### Multi-Server Architektur
|
|
|
|
Der OpenVPN-Container verwaltet **automatisch mehrere VPN-Server-Instanzen**:
|
|
|
|
- Läuft im **Host-Netzwerk-Modus** für direkte Port-Bindung
|
|
- Verwendet **supervisord** für Prozess-Management
|
|
- **Pollt alle 30 Sekunden** die API für neue/geänderte Server
|
|
- **Keine docker-compose.yml Änderungen** nötig beim Hinzufügen neuer VPN-Server!
|
|
|
|
```
|
|
Datenbank OpenVPN Container
|
|
┌─────────────────────┐ ┌─────────────────────┐
|
|
│ VPN-Server │ │ supervisord │
|
|
│ ├── ID: 1 (aktiv) │ ──Poll──▶ │ ├── openvpn-1 │
|
|
│ ├── ID: 2 (aktiv) │ │ ├── openvpn-2 │
|
|
│ └── ID: 3 (inaktiv)│ │ └── (kein 3) │
|
|
└─────────────────────┘ └─────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Verbindungsweg: Client → Server → Gateway → Endpunkt
|
|
|
|
Diese Sektion erklärt den vollständigen Datenweg, wenn ein Techniker (Service-PC) auf ein Gerät (z.B. SPS, HMI) hinter einem Gateway zugreift.
|
|
|
|
### Übersicht
|
|
|
|
```
|
|
Techniker-Netz Internet Kunden-Netz
|
|
192.168.178.0/24 192.168.0.0/24
|
|
|
|
┌─────────────────┐ ┌──────────────────────────────┐ ┌─────────────────┐ ┌─────────────┐
|
|
│ Service-PC │ │ VPN-Server │ │ Gateway │ │ Endpunkt │
|
|
│ (Techniker) │ │ (Docker Host) │ │ (mGuard) │ │ (SPS) │
|
|
│ │ │ │ │ │ │ │
|
|
│ LAN: 192.168. │ │ ┌────────────────────────┐ │ │ VPN: 10.8.0.100 │ │ 192.168.0.3 │
|
|
│ 178.100 │ │ │ OpenVPN Server │ │ │ │ │ Port 11740 │
|
|
│ GW: 192.168. │◄────►│ │ VPN-Netz: 10.8.0.0/24 │ │◄────►│ LAN: 192.168. │◄────►│ (CoDeSys) │
|
|
│ 178.1 │ │ │ Public: 85.16.65.177 │ │ │ 0.100 │ │ │
|
|
│ │ │ └────────────────────────┘ │ │ │ │ │
|
|
│ VPN: 10.8.0.50 │ │ │ │ │ │ │
|
|
└─────────────────┘ └──────────────────────────────┘ └─────────────────┘ └─────────────┘
|
|
│ │ │ │
|
|
│ VPN-Tunnel │ VPN-Tunnel │ Lokales Netz │
|
|
│ (verschlüsselt) │ (verschlüsselt) │ 192.168.0.0/24 │
|
|
└──────────────────────────────┴───────────────────────────────┴───────────────────────┘
|
|
```
|
|
|
|
### Netzwerk-Adressen im Beispiel
|
|
|
|
| Komponente | Interface | IP-Adresse | Beschreibung |
|
|
|------------|-----------|------------|--------------|
|
|
| **Service-PC** | eth0/wlan0 | 192.168.178.100/24 | Lokales Netz des Technikers |
|
|
| **Service-PC** | (Gateway) | 192.168.178.1 | Fritz!Box/Router ins Internet |
|
|
| **Service-PC** | tun0 | 10.8.0.50 | VPN-IP (vom Server zugewiesen) |
|
|
| **VPN-Server** | eth0 | 85.16.65.177 | Öffentliche IP |
|
|
| **VPN-Server** | tun0 | 10.8.0.1 | VPN-Gateway |
|
|
| **Gateway** | tun0 | 10.8.0.100 | VPN-IP des Gateways |
|
|
| **Gateway** | eth0 | 192.168.0.100/24 | LAN-Interface beim Kunden |
|
|
| **Endpunkt (SPS)** | eth0 | 192.168.0.3 | CoDeSys-SPS im Kunden-LAN |
|
|
|
|
### Schritt-für-Schritt Verbindungsablauf
|
|
|
|
#### 1. Techniker meldet sich im Desktop-Client an
|
|
|
|
```
|
|
Service-PC VPN-Server (API)
|
|
│ │
|
|
│ POST /api/auth/login │
|
|
│ {username, password} │
|
|
│ ─────────────────────────────────────► │
|
|
│ │
|
|
│ JWT Token │
|
|
│ ◄───────────────────────────────────── │
|
|
```
|
|
|
|
#### 2. Techniker wählt Gateway und Endpunkt
|
|
|
|
```
|
|
Service-PC VPN-Server (API)
|
|
│ │
|
|
│ GET /api/gateways │
|
|
│ ─────────────────────────────────────► │
|
|
│ │
|
|
│ Liste der zugewiesenen Gateways │
|
|
│ + Online-Status │
|
|
│ ◄───────────────────────────────────── │
|
|
│ │
|
|
│ POST /api/connections/connect │
|
|
│ {gateway_id, endpoint_id} │
|
|
│ ─────────────────────────────────────► │
|
|
│ │
|
|
│ VPN-Konfiguration (.ovpn Inhalt) │
|
|
│ + Ziel-IP und Port │
|
|
│ ◄───────────────────────────────────── │
|
|
```
|
|
|
|
#### 3. VPN-Tunnel wird aufgebaut
|
|
|
|
```
|
|
Service-PC OpenVPN-Server Gateway (mGuard)
|
|
│ │ │
|
|
│ UDP/TCP Handshake │ │
|
|
│ ────────────────────────────►│ │
|
|
│ │ │
|
|
│ TLS-Authentifizierung │ │
|
|
│ (Client-Zertifikat) │ │
|
|
│ ◄───────────────────────────►│ │
|
|
│ │ │
|
|
│ VPN-IP zugewiesen: │ │
|
|
│ 10.8.0.50 │ │
|
|
│ ◄────────────────────────── │ │
|
|
│ │ │
|
|
│ Tunnel aktiv │ Tunnel aktiv │
|
|
│ ════════════════════════════ │ ═══════════════════════ │
|
|
│ │ 10.8.0.100 │
|
|
```
|
|
|
|
#### 4. Routing zum Endpunkt
|
|
|
|
```
|
|
Service-PC (10.8.0.50) OpenVPN-Server Gateway (10.8.0.100) SPS (192.168.0.3)
|
|
│ │ │ │
|
|
│ Paket an 192.168.0.3:11740 │ │ │
|
|
│ ══════════════════════════════►│ │ │
|
|
│ (durch VPN-Tunnel) │ │ │
|
|
│ │ │ │
|
|
│ │ Routing-Entscheidung: │ │
|
|
│ │ 192.168.0.0/24→10.8.0.100 │ │
|
|
│ │ (via iroute im CCD) │ │
|
|
│ │ ══════════════════════════►│ │
|
|
│ │ (durch VPN-Tunnel) │ │
|
|
│ │ │ │
|
|
│ │ │ IP-Forwarding + NAT │
|
|
│ │ │ ────────────────────────►│
|
|
│ │ │ (eth0: 192.168.0.100) │
|
|
│ │ │ │
|
|
│ │ │ Antwort │
|
|
│ │ │ ◄────────────────────────│
|
|
│ │ │ │
|
|
│ │ ◄══════════════════════════│ │
|
|
│ ◄══════════════════════════════│ │ │
|
|
│ │ │ │
|
|
```
|
|
|
|
### Routing-Konfiguration im Detail
|
|
|
|
#### Server-Seite (OpenVPN-Server)
|
|
|
|
Der VPN-Server muss wissen, welche Subnetze über welchen Client (Gateway) erreichbar sind:
|
|
|
|
**server.conf (automatisch generiert):**
|
|
```
|
|
# VPN-Netzwerk für alle Clients
|
|
server 10.8.0.0 255.255.255.0
|
|
|
|
# Route für Kunden-Subnetz 192.168.0.0/24 → Gateway
|
|
route 192.168.0.0 255.255.255.0 # Kernel-Route
|
|
|
|
# Client-Config-Directory für iroute-Direktiven
|
|
client-config-dir /etc/openvpn/ccd
|
|
```
|
|
|
|
**CCD-Datei für Gateway (z.B. `/etc/openvpn/ccd/gw-kunde-abc-1`):**
|
|
```
|
|
# Traffic für Kunden-Subnetz 192.168.0.0/24 geht durch diesen Client
|
|
iroute 192.168.0.0 255.255.255.0
|
|
```
|
|
|
|
> **Wichtig:** `route` sagt dem Kernel wohin, `iroute` sagt OpenVPN wohin.
|
|
> Beide sind erforderlich damit das Routing funktioniert!
|
|
|
|
#### Gateway-Seite (mGuard/Linux)
|
|
|
|
Das Gateway muss als Router fungieren und Traffic weiterleiten:
|
|
|
|
```bash
|
|
# IP-Forwarding aktivieren
|
|
echo 1 > /proc/sys/net/ipv4/ip_forward
|
|
|
|
# NAT/Masquerading für VPN-Traffic ins Kunden-LAN (192.168.0.0/24)
|
|
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
|
|
|
|
# Forwarding erlauben: VPN (tun0) ↔ Kunden-LAN (eth0)
|
|
iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT
|
|
iptables -A FORWARD -i eth0 -o tun0 -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
```
|
|
|
|
**Wichtig:** Das Gateway hat zwei Interfaces:
|
|
- `tun0` (10.8.0.100) - VPN-Tunnel zum Server
|
|
- `eth0` (192.168.0.100) - Kunden-LAN mit der SPS
|
|
|
|
### Split Tunneling (Client-Seite)
|
|
|
|
Der Desktop-Client verwendet **Split Tunneling**, damit:
|
|
- VPN-Traffic (Gateways, Endpunkte) durch den Tunnel geht
|
|
- Internet-Traffic **nicht** durch den Tunnel geht
|
|
|
|
**Client-Konfiguration (.ovpn):**
|
|
```
|
|
# Redirect-Gateway vom Server ignorieren
|
|
pull-filter ignore "redirect-gateway"
|
|
|
|
# Nur VPN-Netzwerk routen
|
|
route 10.8.0.0 255.255.255.0
|
|
|
|
# Nur Kunden-Subnetze routen (automatisch hinzugefügt basierend auf Gateway-Zugriff)
|
|
route 192.168.0.0 255.255.255.0 # Kunde mit SPS
|
|
```
|
|
|
|
**Resultat auf dem Service-PC:**
|
|
```
|
|
┌──────────────────────┐
|
|
│ Service-PC │
|
|
│ LAN: 192.168.178.100 │
|
|
│ VPN: 10.8.0.50 │
|
|
└──────────┬───────────┘
|
|
│
|
|
┌──────────────┴──────────────┐
|
|
│ │
|
|
Ziel: 10.8.0.x Ziel: 8.8.8.8
|
|
Ziel: 192.168.0.x (Internet)
|
|
│ │
|
|
▼ ▼
|
|
┌───────────────┐ ┌───────────────┐
|
|
│ VPN-Tunnel │ │ Fritz!Box │
|
|
│ (tun0) │ │ 192.168.178.1 │
|
|
└───────────────┘ └───────────────┘
|
|
```
|
|
|
|
**Routing-Tabelle auf dem Service-PC (nach VPN-Verbindung):**
|
|
```
|
|
$ ip route
|
|
default via 192.168.178.1 dev eth0 # Internet → Fritz!Box
|
|
10.8.0.0/24 via 10.8.0.1 dev tun0 # VPN-Netz → Tunnel
|
|
192.168.0.0/24 via 10.8.0.1 dev tun0 # Kunden-Netz → Tunnel
|
|
192.168.178.0/24 dev eth0 src 192.168.178.100 # Lokales Netz
|
|
```
|
|
|
|
### Beispiel: Kompletter Verbindungsweg
|
|
|
|
**Szenario:** Techniker will auf CoDeSys (Port 11740) auf einer SPS zugreifen.
|
|
|
|
| Komponente | Lokale IP | VPN-IP | Rolle |
|
|
|------------|-----------|--------|-------|
|
|
| Service-PC | 192.168.178.100 | 10.8.0.50 | Techniker-Laptop mit Desktop-Client |
|
|
| Fritz!Box | 192.168.178.1 | - | Internet-Gateway des Technikers |
|
|
| VPN-Server | 85.16.65.177:1199 | 10.8.0.1 | Docker-Host mit OpenVPN |
|
|
| Gateway | 192.168.0.100 | 10.8.0.100 | mGuard/Linux beim Kunden |
|
|
| SPS (Endpunkt) | 192.168.0.3:11740 | - | CoDeSys-SPS im Kunden-LAN |
|
|
|
|
**Paketweg (Hinrichtung):**
|
|
|
|
```
|
|
1. Techniker öffnet CoDeSys, verbindet zu 192.168.0.3:11740
|
|
|
|
2. Service-PC prüft Routing-Tabelle:
|
|
192.168.0.0/24 → tun0 (VPN-Tunnel)
|
|
✓ Ziel 192.168.0.3 matcht → geht durch Tunnel
|
|
|
|
3. Paket wird verschlüsselt und durch VPN-Tunnel gesendet:
|
|
Inner: Src: 10.8.0.50 Dst: 192.168.0.3:11740
|
|
Outer: Src: 192.168.178.100 Dst: 85.16.65.177:1199 (UDP)
|
|
|
|
4. Paket geht über Fritz!Box (192.168.178.1) ins Internet
|
|
|
|
5. VPN-Server (85.16.65.177) empfängt, entschlüsselt, prüft Routing:
|
|
- route 192.168.0.0/24 → existiert (Kernel weiß Bescheid)
|
|
- iroute 192.168.0.0/24 → OpenVPN weiß: geht an Client "gw-xxx"
|
|
|
|
6. Server verschlüsselt und leitet an Gateway weiter (durch dessen Tunnel):
|
|
Src: 10.8.0.50 Dst: 192.168.0.3
|
|
|
|
7. Gateway (10.8.0.100) empfängt auf tun0, leitet weiter:
|
|
- IP-Forwarding aktiv
|
|
- NAT/Masquerade: Src-IP wird zu 192.168.0.100 (Gateway's LAN-IP)
|
|
- Paket geht raus auf eth0 (192.168.0.100) ins Kunden-LAN
|
|
|
|
8. SPS (192.168.0.3) empfängt Anfrage von 192.168.0.100, antwortet
|
|
|
|
9. Rückweg:
|
|
- SPS antwortet an 192.168.0.100 (Gateway)
|
|
- Gateway's NAT übersetzt zurück zu 10.8.0.50
|
|
- Paket geht durch VPN-Tunnel zurück zum Server
|
|
- Server leitet an Service-PC weiter
|
|
- CoDeSys empfängt Antwort
|
|
```
|
|
|
|
**Zusammenfassung der IP-Adressen im Paket:**
|
|
|
|
```
|
|
Service-PC VPN-Server Gateway SPS
|
|
192.168.178.100 85.16.65.177 192.168.0.100 192.168.0.3
|
|
│ │ │ │
|
|
│ Outer: 192.168.178.100 │ │ │
|
|
│ → 85.16.65.177 │ │ │
|
|
│ Inner: 10.8.0.50 │ │ │
|
|
│ → 192.168.0.3 │ │ │
|
|
│═════════════════════════│ │ │
|
|
│ (verschlüsselt) │ Inner: 10.8.0.50 │ │
|
|
│ │ → 192.168.0.3 │ │
|
|
│ │════════════════════════│ │
|
|
│ │ (verschlüsselt) │ NAT: 192.168.0.100 │
|
|
│ │ │ → 192.168.0.3 │
|
|
│ │ │───────────────────────│
|
|
│ │ │ (unverschlüsselt) │
|
|
```
|
|
|
|
### Firewall-Regeln (automatisch)
|
|
|
|
Der VPN-Server kann dynamisch Firewall-Regeln erstellen, um Zugriffe zu kontrollieren:
|
|
|
|
```bash
|
|
# Wenn Techniker sich verbindet und Endpunkt anfordert:
|
|
iptables -A MGUARD_VPN -s 10.8.0.50 -d 192.168.0.3 -p tcp --dport 11740 -j ACCEPT
|
|
iptables -A MGUARD_VPN -s 192.168.0.3 -d 10.8.0.50 -p tcp --sport 11740 -j ACCEPT
|
|
|
|
# Wenn Techniker trennt:
|
|
iptables -D MGUARD_VPN ... (Regeln entfernen)
|
|
```
|
|
|
|
### Zusammenfassung der Netzwerk-Komponenten
|
|
|
|
| Schicht | Komponente | Funktion |
|
|
|---------|------------|----------|
|
|
| **Client** | Desktop-Client | Login, Gateway-Auswahl, OpenVPN starten |
|
|
| **Client** | OpenVPN (Client) | VPN-Tunnel aufbauen, Split-Tunneling |
|
|
| **Server** | OpenVPN (Server) | Tunnel-Endpunkt, Routing zwischen Clients |
|
|
| **Server** | CCD-Dateien | iroute-Direktiven für Gateway-Subnetze |
|
|
| **Gateway** | OpenVPN (Client) | Permanenter VPN-Tunnel zum Server |
|
|
| **Gateway** | IP-Forwarding | Pakete zwischen tun0 und eth0 weiterleiten |
|
|
| **Gateway** | NAT/Masquerade | Source-IP umschreiben für Rückweg |
|
|
| **Endpunkt** | Zielgerät | SPS, HMI, oder anderes Gerät im Kunden-LAN |
|
|
|
|
---
|
|
|
|
### PKI-Verwaltung über Web-UI
|
|
|
|
Die gesamte PKI (Zertifizierungsstellen, Zertifikate, VPN-Server) wird über die Web-Oberfläche verwaltet:
|
|
|
|
| Bereich | Beschreibung |
|
|
|---------|--------------
|
|
| **Zertifizierungsstellen (CA)** | Eigene CA erstellen oder importieren |
|
|
| **VPN-Server** | Mehrere Server mit unterschiedlichen Ports/Protokollen |
|
|
| **VPN-Profile** | Pro Gateway mehrere Profile für Failover/Migration |
|
|
|
|
---
|
|
|
|
## Schnellstart
|
|
|
|
### Voraussetzungen
|
|
|
|
- Docker & Docker Compose
|
|
- Mindestens 2 GB RAM für die Container
|
|
- Port 8000 (Web/API) und gewünschte VPN-Ports frei
|
|
|
|
### 1. Installation
|
|
|
|
```bash
|
|
# Repository klonen oder Dateien kopieren
|
|
cd endpoint-server-openvpn
|
|
|
|
# Konfiguration erstellen
|
|
cp .env.example .env
|
|
|
|
# .env bearbeiten und Passwörter anpassen!
|
|
nano .env
|
|
```
|
|
|
|
### 2. Container starten
|
|
|
|
```bash
|
|
# Container bauen und starten
|
|
docker-compose up -d
|
|
|
|
# Logs prüfen
|
|
docker-compose logs -f
|
|
```
|
|
|
|
### 3. Ersteinrichtung (Web-UI)
|
|
|
|
Nach dem Start unter **http://localhost:8000/** einloggen.
|
|
|
|
Standard-Login:
|
|
- **Benutzername:** `admin`
|
|
- **Passwort:** `changeme` (in .env ändern!)
|
|
|
|
#### Schritt 1: CA erstellen
|
|
|
|
1. Navigation: **VPN → Zertifizierungsstellen**
|
|
2. **Neue CA erstellen** klicken
|
|
3. Formular ausfüllen:
|
|
- Name: z.B. "Produktion CA"
|
|
- Organisation, Land, Stadt
|
|
- Schlüsselgröße: 4096 (empfohlen) oder 2048
|
|
- Gültigkeit: 3650 Tage (10 Jahre)
|
|
4. **Erstellen** - DH-Parameter werden im Hintergrund generiert
|
|
|
|
#### Schritt 2: VPN-Server erstellen
|
|
|
|
1. Navigation: **VPN → VPN-Server**
|
|
2. **Neuer VPN-Server** klicken
|
|
3. Formular ausfüllen:
|
|
- Name: z.B. "Produktion UDP"
|
|
- CA auswählen (aus Schritt 1)
|
|
- Hostname: Öffentliche IP oder Domain
|
|
- Port: 1194
|
|
- Protokoll: UDP (empfohlen) oder TCP
|
|
4. **Erstellen** - Server-Zertifikat wird automatisch generiert
|
|
|
|
#### Schritt 3: Automatischer Start
|
|
|
|
Der OpenVPN-Container erkennt neue Server automatisch (Polling alle 30s):
|
|
|
|
```bash
|
|
# Logs prüfen - Server sollte automatisch starten
|
|
docker-compose logs -f openvpn
|
|
|
|
# Ausgabe sollte zeigen:
|
|
# [2024-01-15 10:30:00] New server detected: 1
|
|
# [2024-01-15 10:30:00] Setting up server 1 (Produktion UDP) on port 1194/udp
|
|
# [2024-01-15 10:30:01] Server 1 configured successfully
|
|
```
|
|
|
|
**Kein Container-Neustart nötig!**
|
|
|
|
---
|
|
|
|
## Mehrere VPN-Server betreiben
|
|
|
|
### Automatische Verwaltung
|
|
|
|
Einfach weitere VPN-Server über die Web-UI erstellen:
|
|
|
|
| Server | Port | Protokoll | Verwendung |
|
|
|--------|------|-----------|------------|
|
|
| Produktion UDP | 1194 | UDP | Standard, schnell |
|
|
| Produktion TCP | 443 | TCP | Firewall-Bypass |
|
|
| Backup | 1195 | UDP | Fallback-Server |
|
|
|
|
Der Container startet diese automatisch - **keine Konfigurationsänderungen nötig!**
|
|
|
|
### Firewall-Regeln
|
|
|
|
Da der Container im Host-Netzwerk läuft, müssen die VPN-Ports auf dem Host freigegeben sein:
|
|
|
|
```bash
|
|
# Beispiel für iptables
|
|
sudo iptables -A INPUT -p udp --dport 1194 -j ACCEPT
|
|
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
|
|
sudo iptables -A INPUT -p udp --dport 1195 -j ACCEPT
|
|
|
|
# Oder via ufw
|
|
sudo ufw allow 1194/udp
|
|
sudo ufw allow 443/tcp
|
|
sudo ufw allow 1195/udp
|
|
```
|
|
|
|
---
|
|
|
|
## Gateway einrichten
|
|
|
|
### 1. Gateway anlegen
|
|
|
|
1. Navigation: **Gateways → Neues Gateway**
|
|
2. Formular ausfüllen:
|
|
- Name: z.B. "Kunde ABC - Türsteuerung Halle 1"
|
|
- Router-Typ: FL MGUARD 2000
|
|
- Standort: Halle 1, Raum 102
|
|
|
|
### 2. VPN-Profil erstellen
|
|
|
|
1. Gateway öffnen → **VPN-Profile** Tab
|
|
2. **Neues Profil** klicken
|
|
3. Formular:
|
|
- Name: z.B. "Produktion"
|
|
- VPN-Server: Server auswählen
|
|
- Priorität: 1 (primär)
|
|
4. **Erstellen** - Client-Zertifikat wird generiert
|
|
|
|
### 3. Provisioning-Download
|
|
|
|
1. VPN-Profil öffnen
|
|
2. **Konfiguration herunterladen** klicken
|
|
3. `.ovpn` Datei auf mGuard Router übertragen
|
|
|
|
### Failover mit mehreren Profilen
|
|
|
|
Für Ausfallsicherheit mehrere Profile mit unterschiedlichen Prioritäten:
|
|
|
|
| Profil | VPN-Server | Priorität | Verwendung |
|
|
|--------|------------|-----------|------------|
|
|
| Produktion | Server 1 (UDP) | 1 | Primärer Server |
|
|
| Fallback | Server 2 (TCP) | 2 | Bei Ausfall von Server 1 |
|
|
|
|
---
|
|
|
|
## Endpunkte definieren
|
|
|
|
Endpunkte sind Geräte hinter dem Gateway (SPS, HMI, etc.):
|
|
|
|
1. Gateway öffnen → **Endpunkte** Tab
|
|
2. **Endpunkt hinzufügen**
|
|
3. Ausfüllen:
|
|
- Name: HMI Türsteuerung
|
|
- IP-Adresse: 10.0.0.3
|
|
- Port: 11740
|
|
- Protokoll: TCP
|
|
- Anwendung: CoDeSys
|
|
|
|
---
|
|
|
|
## Web-Oberfläche
|
|
|
|
### Navigation
|
|
|
|
| Bereich | Beschreibung |
|
|
|---------|--------------
|
|
| **Dashboard** | Gateway-Status, aktive Verbindungen, Statistiken |
|
|
| **Gateways** | Gateway-Verwaltung, Endpunkte, VPN-Profile |
|
|
| **VPN → VPN-Server** | VPN-Instanzen verwalten, Status, Clients |
|
|
| **VPN → Zertifizierungsstellen** | CA erstellen/importieren, Zertifikate |
|
|
| **Benutzer** | Techniker anlegen, Rollen zuweisen |
|
|
| **Verbindungen** | Live-Anzeige aktiver Verbindungen, Historie |
|
|
|
|
---
|
|
|
|
## Benutzer & Berechtigungen
|
|
|
|
### Rollen
|
|
|
|
| Rolle | Rechte |
|
|
|-------|--------|
|
|
| **super_admin** | Alle Mandanten, alle Gateways, CAs, VPN-Server |
|
|
| **admin** | Eigener Mandant: Gateways, Benutzer, Endpunkte |
|
|
| **technician** | Nur zugewiesene Gateways sehen und verbinden |
|
|
| **viewer** | Nur lesen, keine Verbindungen |
|
|
|
|
---
|
|
|
|
## Wartung & Betrieb
|
|
|
|
### Logs ansehen
|
|
|
|
```bash
|
|
# Alle Logs
|
|
docker-compose logs -f
|
|
|
|
# Nur API-Server
|
|
docker-compose logs -f api
|
|
|
|
# Nur OpenVPN (alle Server)
|
|
docker-compose logs -f openvpn
|
|
|
|
# Einzelner VPN-Server im Container
|
|
docker exec mguard-openvpn cat /var/log/openvpn/server-1.log
|
|
```
|
|
|
|
### Server-Status prüfen
|
|
|
|
```bash
|
|
# Alle laufenden OpenVPN-Prozesse
|
|
docker exec mguard-openvpn supervisorctl status
|
|
|
|
# Ausgabe:
|
|
# openvpn-1 RUNNING pid 123, uptime 0:05:30
|
|
# openvpn-2 RUNNING pid 456, uptime 0:05:28
|
|
```
|
|
|
|
### Einzelnen Server neustarten
|
|
|
|
```bash
|
|
# Via supervisorctl
|
|
docker exec mguard-openvpn supervisorctl restart openvpn-1
|
|
```
|
|
|
|
### Backup
|
|
|
|
```bash
|
|
# Datenbank-Backup (enthält CAs, Zertifikate, Konfiguration)
|
|
docker-compose exec db mysqldump -u root -p mguard_vpn > backup.sql
|
|
|
|
# Volumes auflisten
|
|
docker volume ls | grep mguard
|
|
```
|
|
|
|
**Wichtig:** Die PKI (CAs, Zertifikate, Private Keys) ist in der Datenbank gespeichert. Ein Datenbank-Backup sichert alles.
|
|
|
|
### Update
|
|
|
|
```bash
|
|
# Container stoppen
|
|
docker-compose down
|
|
|
|
# Neue Version pullen/kopieren
|
|
git pull
|
|
|
|
# Neu bauen und starten
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
---
|
|
|
|
## Fehlerbehebung
|
|
|
|
### OpenVPN startet nicht
|
|
|
|
```bash
|
|
# Logs prüfen
|
|
docker-compose logs openvpn
|
|
```
|
|
|
|
Mögliche Ursachen:
|
|
- **"API not ready"**: API-Container noch nicht gestartet
|
|
- **"No active VPN servers found"**: VPN-Server in Web-UI erstellen
|
|
- **"Failed to fetch server config"**: Server nicht bereit (CA/Zertifikat fehlt)
|
|
|
|
### Neuer VPN-Server wird nicht gestartet
|
|
|
|
1. Prüfe ob Server in Web-UI als "Bereit" markiert ist
|
|
2. Warte 30 Sekunden (Polling-Intervall)
|
|
3. Prüfe Logs: `docker-compose logs -f openvpn`
|
|
|
|
### Port bereits belegt
|
|
|
|
```bash
|
|
# Prüfen welcher Prozess den Port nutzt
|
|
sudo netstat -tlnp | grep 1194
|
|
sudo lsof -i :1194
|
|
|
|
# Falls nötig: Prozess beenden oder anderen Port in Web-UI wählen
|
|
```
|
|
|
|
### VPN-Server zeigt "Ausstehend"
|
|
|
|
DH-Parameter werden noch generiert. Status in der VPN-Server-Übersicht prüfen.
|
|
|
|
```bash
|
|
# CA-Status in Datenbank prüfen
|
|
docker-compose exec db mysql -u mguard -p -e \
|
|
"SELECT name, status FROM mguard_vpn.certificate_authorities"
|
|
```
|
|
|
|
### Gateway verbindet nicht
|
|
|
|
1. VPN-Profil für Gateway erstellt?
|
|
2. Provisioning-Datei heruntergeladen und importiert?
|
|
3. Firewall-Ports offen?
|
|
4. VPN-Server Status prüfen: **VPN → VPN-Server → Details**
|
|
|
|
---
|
|
|
|
## Verzeichnisstruktur
|
|
|
|
```
|
|
endpoint-server-openvpn/
|
|
├── docker-compose.yml # Container-Orchestrierung
|
|
├── .env.example # Konfigurationsvorlage
|
|
├── README.md # Diese Datei
|
|
│
|
|
├── server/ # FastAPI Backend + Web-UI
|
|
│ ├── Dockerfile
|
|
│ ├── requirements.txt
|
|
│ └── app/
|
|
│ ├── main.py # Einstiegspunkt
|
|
│ ├── api/ # REST API Routes
|
|
│ │ └── internal.py # Interne API für OpenVPN
|
|
│ ├── web/ # Web-UI Routes
|
|
│ │ ├── ca.py # CA-Verwaltung
|
|
│ │ ├── vpn_servers.py # VPN-Server
|
|
│ │ └── vpn_profiles.py # VPN-Profile
|
|
│ ├── templates/ # Jinja2 HTML-Templates
|
|
│ ├── models/ # Datenbank-Modelle
|
|
│ │ ├── certificate_authority.py
|
|
│ │ ├── vpn_server.py
|
|
│ │ └── vpn_profile.py
|
|
│ └── services/ # Business-Logik
|
|
│ ├── certificate_service.py
|
|
│ ├── vpn_server_service.py
|
|
│ └── vpn_profile_service.py
|
|
│
|
|
├── openvpn/ # OpenVPN Multi-Server Container
|
|
│ ├── Dockerfile
|
|
│ ├── entrypoint.sh # Multi-Server Management Script
|
|
│ └── supervisord.conf # Prozess-Manager Konfiguration
|
|
│
|
|
├── client/ # PyQt Desktop-Client
|
|
│ └── ...
|
|
│
|
|
└── provisioning-tool/ # CLI Provisioning
|
|
└── ...
|
|
```
|
|
|
|
---
|
|
|
|
## Sicherheit
|
|
|
|
- **TLS 1.2+** für VPN-Verbindungen
|
|
- **AES-256-GCM** Verschlüsselung (konfigurierbar)
|
|
- **JWT-Token** für API-Authentifizierung
|
|
- **Session-Cookies** für Web-UI
|
|
- **bcrypt** Password-Hashing
|
|
- **Multi-Tenant** Datenisolation
|
|
- **CRL** für Zertifikatswiderruf
|
|
|
|
### Produktiv-Empfehlungen
|
|
|
|
1. `.env` Passwörter ändern!
|
|
2. HTTPS-Reverse-Proxy (nginx/traefik) vorschalten
|
|
3. Firewall: Nur VPN-Ports und HTTPS nach außen
|
|
4. Regelmäßige Datenbank-Backups
|
|
5. Schlüsselgröße 4096-bit für CAs
|
|
|
|
### Host-Netzwerk Hinweis
|
|
|
|
Der OpenVPN-Container läuft im Host-Netzwerk-Modus. Das bedeutet:
|
|
- Direkte Port-Bindung (kein Docker NAT)
|
|
- Weniger Netzwerk-Overhead
|
|
- Container kann auf localhost:8000 zugreifen
|
|
- Firewall-Regeln auf Host-Ebene erforderlich
|
|
|
|
---
|
|
|
|
## REST API
|
|
|
|
Die API ist dokumentiert unter: **http://localhost:8000/api/docs**
|
|
|
|
### Wichtige Endpoints
|
|
|
|
| Methode | Endpoint | Beschreibung |
|
|
|---------|----------|--------------|
|
|
| POST | `/api/auth/login` | Login |
|
|
| GET | `/api/gateways` | Gateway-Liste |
|
|
| GET | `/api/gateways/{id}/profiles` | VPN-Profile eines Gateways |
|
|
| GET | `/api/gateways/{id}/profiles/{pid}/provision` | Provisioning-Download |
|
|
|
|
### Interne API (für OpenVPN-Container)
|
|
|
|
| Endpoint | Beschreibung |
|
|
|----------|--------------|
|
|
| `/api/internal/health` | Health Check |
|
|
| `/api/internal/vpn-servers/active` | Liste aller aktiven Server |
|
|
| `/api/internal/vpn-servers/{id}/config` | Server-Konfiguration |
|
|
| `/api/internal/vpn-servers/{id}/ca` | CA-Zertifikat |
|
|
| `/api/internal/vpn-servers/{id}/cert` | Server-Zertifikat |
|
|
| `/api/internal/vpn-servers/{id}/key` | Server Private Key |
|
|
| `/api/internal/vpn-servers/{id}/dh` | DH-Parameter |
|
|
| `/api/internal/vpn-servers/{id}/crl` | Revocation List |
|
|
| `/api/internal/vpn-servers/{id}/started` | Server-Start melden |
|
|
| `/api/internal/vpn-servers/{id}/stopped` | Server-Stop melden |
|
|
|
|
---
|
|
|
|
## Umgebungsvariablen
|
|
|
|
### OpenVPN Container
|
|
|
|
| Variable | Standard | Beschreibung |
|
|
|----------|----------|--------------|
|
|
| `API_URL` | `http://127.0.0.1:8000/api/internal` | API-Endpunkt |
|
|
| `API_TIMEOUT` | `120` | Timeout beim Warten auf API (Sekunden) |
|
|
| `API_RETRY_INTERVAL` | `5` | Wiederholungsintervall (Sekunden) |
|
|
| `POLL_INTERVAL` | `30` | Polling-Intervall für neue Server (Sekunden) |
|
|
|
|
---
|
|
|
|
## Container neu bauen
|
|
|
|
```bash
|
|
# Stoppen
|
|
docker-compose down
|
|
|
|
# Komplett neu bauen
|
|
docker-compose build --no-cache
|
|
|
|
# Starten
|
|
docker-compose up -d
|
|
```
|
|
|
|
---
|
|
|
|
## Desktop Client (Techniker-Anwendung)
|
|
|
|
Der Desktop Client ist eine PyQt6-Anwendung für Techniker, um sich zu VPN-Gateways zu verbinden.
|
|
|
|
### Voraussetzungen
|
|
|
|
- **Python 3.10+**
|
|
- **OpenVPN** (muss installiert sein)
|
|
- Zugang zum mGuard VPN Server
|
|
|
|
---
|
|
|
|
### Installation
|
|
|
|
#### Linux (Debian/Ubuntu)
|
|
|
|
```bash
|
|
# System-Abhängigkeiten installieren
|
|
sudo apt update
|
|
sudo apt install python3 python3-pip python3-venv openvpn
|
|
|
|
# In das Client-Verzeichnis wechseln
|
|
cd client/
|
|
|
|
# Virtuelle Umgebung erstellen (empfohlen)
|
|
python3 -m venv venv
|
|
source venv/bin/activate
|
|
|
|
# Abhängigkeiten installieren
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
#### Linux (Fedora/RHEL)
|
|
|
|
```bash
|
|
# System-Abhängigkeiten installieren
|
|
sudo dnf install python3 python3-pip openvpn
|
|
|
|
# In das Client-Verzeichnis wechseln
|
|
cd client/
|
|
|
|
# Virtuelle Umgebung erstellen (empfohlen)
|
|
python3 -m venv venv
|
|
source venv/bin/activate
|
|
|
|
# Abhängigkeiten installieren
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
#### Linux (Arch)
|
|
|
|
```bash
|
|
# System-Abhängigkeiten installieren
|
|
sudo pacman -S python python-pip openvpn
|
|
|
|
# In das Client-Verzeichnis wechseln
|
|
cd client/
|
|
|
|
# Virtuelle Umgebung erstellen (empfohlen)
|
|
python -m venv venv
|
|
source venv/bin/activate
|
|
|
|
# Abhängigkeiten installieren
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
#### Windows
|
|
|
|
1. **Python installieren:**
|
|
- Download von https://www.python.org/downloads/
|
|
- Bei Installation "Add Python to PATH" aktivieren
|
|
|
|
2. **OpenVPN installieren:**
|
|
- Download von https://openvpn.net/community-downloads/
|
|
- Standard-Installation in `C:\Program Files\OpenVPN`
|
|
|
|
3. **Client installieren:**
|
|
```powershell
|
|
# PowerShell oder CMD
|
|
cd client
|
|
|
|
# Virtuelle Umgebung erstellen (empfohlen)
|
|
python -m venv venv
|
|
venv\Scripts\activate
|
|
|
|
# Abhängigkeiten installieren
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
#### macOS
|
|
|
|
```bash
|
|
# Homebrew installieren (falls nicht vorhanden)
|
|
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
|
|
# Python und OpenVPN installieren
|
|
brew install python openvpn
|
|
|
|
# In das Client-Verzeichnis wechseln
|
|
cd client/
|
|
|
|
# Virtuelle Umgebung erstellen (empfohlen)
|
|
python3 -m venv venv
|
|
source venv/bin/activate
|
|
|
|
# Abhängigkeiten installieren
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
---
|
|
|
|
### Client starten
|
|
|
|
#### Linux / macOS
|
|
|
|
```bash
|
|
# In das Client-Verzeichnis wechseln
|
|
cd client/
|
|
|
|
# Virtuelle Umgebung aktivieren (falls verwendet)
|
|
source venv/bin/activate
|
|
|
|
# Client starten
|
|
python main.py
|
|
```
|
|
|
|
**Hinweis:** Für VPN-Verbindungen sind Root-Rechte erforderlich:
|
|
|
|
```bash
|
|
# Mit sudo starten (für VPN-Verbindungen)
|
|
sudo venv/bin/python main.py
|
|
```
|
|
|
|
#### Windows
|
|
|
|
```powershell
|
|
# In das Client-Verzeichnis wechseln
|
|
cd client
|
|
|
|
# Virtuelle Umgebung aktivieren (falls verwendet)
|
|
venv\Scripts\activate
|
|
|
|
# Client starten
|
|
python main.py
|
|
```
|
|
|
|
**Hinweis:** Als Administrator ausführen für VPN-Verbindungen.
|
|
|
|
---
|
|
|
|
### Erste Schritte im Client
|
|
|
|
1. **Server konfigurieren:**
|
|
- Beim ersten Start Server-URL eingeben (z.B. `https://vpn.meinefirma.de:8000`)
|
|
|
|
2. **Anmelden:**
|
|
- Mit Techniker-Zugangsdaten einloggen
|
|
|
|
3. **Gateway wählen:**
|
|
- Liste der zugewiesenen Gateways wird angezeigt
|
|
- Online-Status wird angezeigt (grün = erreichbar)
|
|
|
|
4. **Verbinden:**
|
|
- Gateway auswählen und "Verbinden" klicken
|
|
- VPN-Verbindung wird automatisch hergestellt
|
|
|
|
5. **Endpunkte nutzen:**
|
|
- Nach Verbindung sind die Endpunkte (SPS, HMI, etc.) erreichbar
|
|
- IP-Adressen und Ports werden angezeigt
|
|
|
|
---
|
|
|
|
### Konfiguration
|
|
|
|
Der Client speichert Einstellungen in:
|
|
|
|
| OS | Pfad |
|
|
|----|------|
|
|
| Linux/macOS | `~/.mguard-vpn/settings.json` |
|
|
| Windows | `C:\Users\<User>\.mguard-vpn\settings.json` |
|
|
|
|
OpenVPN-Konfigurationen werden gespeichert in:
|
|
|
|
| OS | Pfad |
|
|
|----|------|
|
|
| Linux/macOS | `~/.openvpn/` |
|
|
| Windows | `C:\Users\<User>\OpenVPN\config\` |
|
|
|
|
---
|
|
|
|
### Fehlerbehebung Client
|
|
|
|
#### "OpenVPN nicht gefunden"
|
|
|
|
**Linux:**
|
|
```bash
|
|
# OpenVPN Pfad prüfen
|
|
which openvpn
|
|
# Sollte /usr/sbin/openvpn ausgeben
|
|
|
|
# Falls woanders installiert, symlink erstellen
|
|
sudo ln -s /pfad/zu/openvpn /usr/sbin/openvpn
|
|
```
|
|
|
|
**Windows:**
|
|
- Prüfen ob OpenVPN in `C:\Program Files\OpenVPN\bin\` installiert ist
|
|
- Falls anderer Pfad: `client/config.py` anpassen
|
|
|
|
**macOS:**
|
|
```bash
|
|
# OpenVPN Pfad prüfen
|
|
which openvpn
|
|
# Meist /opt/homebrew/bin/openvpn oder /usr/local/bin/openvpn
|
|
|
|
# Symlink erstellen falls nötig
|
|
sudo ln -s $(which openvpn) /usr/sbin/openvpn
|
|
```
|
|
|
|
#### "Permission denied" bei VPN-Verbindung
|
|
|
|
VPN-Verbindungen erfordern erhöhte Rechte:
|
|
|
|
```bash
|
|
# Linux/macOS: Mit sudo starten
|
|
sudo python main.py
|
|
|
|
# Windows: Als Administrator ausführen
|
|
# Rechtsklick → "Als Administrator ausführen"
|
|
```
|
|
|
|
#### PyQt6 Fehler auf Linux
|
|
|
|
```bash
|
|
# Fehlende Qt-Bibliotheken installieren
|
|
sudo apt install libxcb-xinerama0 libxkbcommon-x11-0
|
|
|
|
# Oder für Wayland
|
|
sudo apt install qtwayland5
|
|
```
|
|
|
|
---
|
|
|
|
## Lizenz
|
|
|
|
Proprietär - Nur für internen Gebrauch.
|