Add SSH-only emergency access fallback
This commit is contained in:
1 parent
e7b6739d85
commit
af6abf54ae
4 files changed
+166
No files matched your search
@@ -75,6 +75,7 @@ Option „Bewegung reduzieren“ erhalten automatisch eine unbewegte Variante.
|
|||||||
- [Installation und Abnahme](docs/INSTALLATION.md)
|
- [Installation und Abnahme](docs/INSTALLATION.md)
|
||||||
- [WireGuard-Heimseite](docs/WIREGUARD_HOME_PEER.md)
|
- [WireGuard-Heimseite](docs/WIREGUARD_HOME_PEER.md)
|
||||||
- [Checkliste für den unbeaufsichtigten Standort](docs/REMOTE_SITE_CHECKLIST.md)
|
- [Checkliste für den unbeaufsichtigten Standort](docs/REMOTE_SITE_CHECKLIST.md)
|
||||||
|
- [Temporärer Notfallzugriff über SSH](docs/EMERGENCY_UNI_ACCESS.md)
|
||||||
- [Betrieb und Profilwechsel](docs/OPERATIONS.md)
|
- [Betrieb und Profilwechsel](docs/OPERATIONS.md)
|
||||||
- [Sicherheitsmodell](docs/SECURITY.md)
|
- [Sicherheitsmodell](docs/SECURITY.md)
|
||||||
- [Disaster Recovery](docs/DISASTER_RECOVERY.md)
|
- [Disaster Recovery](docs/DISASTER_RECOVERY.md)
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# Notfallzugriff aus dem Universitätsnetz
|
||||||
|
|
||||||
|
## Zweck
|
||||||
|
|
||||||
|
Der normale Zugang zu Open WebUI und den MCP-Endpunkten erfolgt ausschließlich
|
||||||
|
über WireGuard. Falls vorübergehend ein administrativer Zugriff über die
|
||||||
|
Standortverbindung erforderlich ist, werden die KI-Ports **nicht** im
|
||||||
|
Universitätsnetz veröffentlicht. Stattdessen stellt ein kurzlebiger Proxy sie
|
||||||
|
nur auf Athenas Loopback-Adresse bereit; ein authentifizierter SSH-Tunnel bringt
|
||||||
|
sie verschlüsselt zum eigenen Rechner.
|
||||||
|
|
||||||
|
Dieser Weg eignet sich beispielsweise zur Diagnose eines gestörten VPN-Tunnels.
|
||||||
|
Er verändert das Fail-Closed-Egress nicht: Ist die Fritzbox nicht erreichbar,
|
||||||
|
funktionieren lokaler Chat und Administration, aber MCP-Zugriffe auf Heimnetz
|
||||||
|
und Internet bleiben absichtlich blockiert.
|
||||||
|
|
||||||
|
## 1. Auf Athena aktivieren
|
||||||
|
|
||||||
|
Per SSH auf Athena anmelden und als root ausführen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mike-ai-emergency-access start
|
||||||
|
mike-ai-emergency-access status
|
||||||
|
```
|
||||||
|
|
||||||
|
Die Ausgabe darf ausschließlich Bindings mit `127.0.0.1` zeigen. Verwendet
|
||||||
|
werden:
|
||||||
|
|
||||||
|
| Lokaler Port auf Athena | Ziel |
|
||||||
|
|---:|---|
|
||||||
|
| 18080 | Open WebUI |
|
||||||
|
| 18090 | Web-MCP |
|
||||||
|
| 18091 | Home-Assistant-MCP |
|
||||||
|
| 18092 | ARR-MCP |
|
||||||
|
| 18093 | Unraid-MCP (read-only) |
|
||||||
|
|
||||||
|
Fehlende optionale MCP-Container werden übersprungen. Die Proxy-Container
|
||||||
|
verwenden kein neues Image, keine Secrets und keine zusätzlichen Rechte. Sie
|
||||||
|
besitzen keine Restart-Policy und verschwinden spätestens beim Hostneustart.
|
||||||
|
|
||||||
|
## 2. SSH-Tunnel auf dem eigenen Rechner öffnen
|
||||||
|
|
||||||
|
`<UNI-IP-ODER-DNS>` durch die aktuelle Standortadresse von Athena ersetzen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh -N \
|
||||||
|
-L 18080:127.0.0.1:18080 \
|
||||||
|
-L 18090:127.0.0.1:18090 \
|
||||||
|
-L 18091:127.0.0.1:18091 \
|
||||||
|
-L 18092:127.0.0.1:18092 \
|
||||||
|
-L 18093:127.0.0.1:18093 \
|
||||||
|
-i ~/.ssh/athena_key root@<UNI-IP-ODER-DNS>
|
||||||
|
```
|
||||||
|
|
||||||
|
Das Terminal bleibt während der Nutzung geöffnet. Danach ist Open WebUI unter
|
||||||
|
`http://127.0.0.1:18080` erreichbar. Die MCP-URLs lauten entsprechend
|
||||||
|
`http://127.0.0.1:18090/mcp` bis `http://127.0.0.1:18093/mcp`.
|
||||||
|
|
||||||
|
## 3. Sofort wieder schließen
|
||||||
|
|
||||||
|
Den SSH-Tunnel mit `Ctrl+C` beenden und auf Athena ausführen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mike-ai-emergency-access stop
|
||||||
|
mike-ai-emergency-access status
|
||||||
|
```
|
||||||
|
|
||||||
|
Zusätzlich prüfen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ss -lnt | grep -E ':(18080|18090|18091|18092|18093) '
|
||||||
|
```
|
||||||
|
|
||||||
|
Nach `stop` darf dieser Befehl nichts mehr ausgeben. Port 8080 und 8081 bleiben
|
||||||
|
während des gesamten Vorgangs an der physischen Standortadresse geschlossen.
|
||||||
|
|
||||||
|
## Was ausdrücklich nicht gemacht wird
|
||||||
|
|
||||||
|
- kein Binding auf `0.0.0.0`
|
||||||
|
- keine direkte Freigabe von 8080/8081 im Universitätsnetz
|
||||||
|
- keine Änderung der Fail-Closed-Routingregeln
|
||||||
|
- kein Fallback der MCPs auf das Universitäts-Internet
|
||||||
|
- keine dauerhafte Notfallfreigabe und kein automatischer Neustart der Proxys
|
||||||
@@ -342,6 +342,8 @@ install_routing_guard() {
|
|||||||
/usr/local/sbin/mike-ai-container-vpn-guard
|
/usr/local/sbin/mike-ai-container-vpn-guard
|
||||||
install -m 0644 "$ROOT_DIR/platform/host/mike-ai-container-vpn-guard.service" \
|
install -m 0644 "$ROOT_DIR/platform/host/mike-ai-container-vpn-guard.service" \
|
||||||
/etc/systemd/system/mike-ai-container-vpn-guard.service
|
/etc/systemd/system/mike-ai-container-vpn-guard.service
|
||||||
|
install -m 0755 "$ROOT_DIR/platform/host/mike-ai-emergency-access" \
|
||||||
|
/usr/local/sbin/mike-ai-emergency-access
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable mike-ai-container-vpn-guard.service
|
systemctl enable mike-ai-container-vpn-guard.service
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
IMAGE=mike-ai/wireguard-gateway:local
|
||||||
|
|
||||||
|
proxy_names=(
|
||||||
|
mike-ai-emergency-openwebui
|
||||||
|
mike-ai-emergency-mcp-web
|
||||||
|
mike-ai-emergency-mcp-homeassistant
|
||||||
|
mike-ai-emergency-mcp-arr
|
||||||
|
mike-ai-emergency-mcp-unraid
|
||||||
|
)
|
||||||
|
|
||||||
|
remove_proxies() {
|
||||||
|
docker rm -f "${proxy_names[@]}" >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
|
||||||
|
start_proxy() {
|
||||||
|
local name=$1 network=$2 host_port=$3 target=$4
|
||||||
|
docker container inspect "$target" >/dev/null 2>&1 || {
|
||||||
|
printf 'Übersprungen (Ziel fehlt): %s\n' "$target" >&2
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
docker start "$target" >/dev/null 2>&1 || true
|
||||||
|
[ "$(docker inspect -f '{{.State.Running}}' "$target" 2>/dev/null || true)" = true ] || {
|
||||||
|
printf 'Übersprungen (Ziel startet nicht): %s\n' "$target" >&2
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
docker run --detach --rm --pull never \
|
||||||
|
--name "$name" \
|
||||||
|
--network mike-ai_frontend \
|
||||||
|
--publish "127.0.0.1:${host_port}:${host_port}" \
|
||||||
|
--read-only --cap-drop ALL --pids-limit 64 --memory 64m \
|
||||||
|
--security-opt no-new-privileges:true \
|
||||||
|
--entrypoint socat "$IMAGE" \
|
||||||
|
"TCP-LISTEN:${host_port},bind=0.0.0.0,reuseaddr,fork" \
|
||||||
|
"TCP:${target}:8000" >/dev/null
|
||||||
|
# Docker deliberately discards published ports on an internal-only network.
|
||||||
|
# The proxy therefore publishes through frontend and receives the tools
|
||||||
|
# network as a second, non-egress attachment for target discovery.
|
||||||
|
docker network connect "$network" "$name"
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
start)
|
||||||
|
remove_proxies
|
||||||
|
docker image inspect "$IMAGE" >/dev/null
|
||||||
|
|
||||||
|
docker start mike-ai-router mike-ai-open-webui >/dev/null 2>&1 || true
|
||||||
|
docker run --detach --rm --pull never \
|
||||||
|
--name mike-ai-emergency-openwebui \
|
||||||
|
--network mike-ai_frontend \
|
||||||
|
--publish 127.0.0.1:18080:18080 \
|
||||||
|
--read-only --cap-drop ALL --pids-limit 64 --memory 64m \
|
||||||
|
--security-opt no-new-privileges:true \
|
||||||
|
--entrypoint socat "$IMAGE" \
|
||||||
|
TCP-LISTEN:18080,bind=0.0.0.0,reuseaddr,fork \
|
||||||
|
TCP:mike-ai-open-webui:8080 >/dev/null
|
||||||
|
|
||||||
|
start_proxy mike-ai-emergency-mcp-web mike-ai-tools 18090 mike-ai-mcp-web
|
||||||
|
start_proxy mike-ai-emergency-mcp-homeassistant mike-ai-tools 18091 mike-ai-mcp-homeassistant
|
||||||
|
start_proxy mike-ai-emergency-mcp-arr mike-ai-tools 18092 mike-ai-mcp-arr
|
||||||
|
start_proxy mike-ai-emergency-mcp-unraid mike-ai-tools 18093 mike-ai-mcp-unraid-official
|
||||||
|
|
||||||
|
echo 'Notfall-Proxys laufen ausschließlich auf 127.0.0.1.'
|
||||||
|
echo 'Jetzt vom Client einen SSH-Tunnel auf die Ports 18080 und 18090-18093 öffnen.'
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
remove_proxies
|
||||||
|
echo 'Notfall-Proxys entfernt.'
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
docker ps --filter 'name=mike-ai-emergency-' \
|
||||||
|
--format 'table {{.Names}}\t{{.Ports}}\t{{.Status}}'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Aufruf: $0 start|stop|status" >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Reference in new issue
Block a user