docs: WARP-Egress-Versuch dokumentiert — Cloudflare blockt Consumer-WARP-WG-Clients

Consumer-WARP über natives RouterOS-WG gebaut, verifiziert, zurückgebaut. Befund: Handshake rx=0, Cloudflare blockt inoffizielle WG-Clients (reserved/Client-ID + Abuse-Prevention). Weg: Dedicated Egress.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-26 09:04:18 +02:00
parent 528f133264
commit 3ae6399b93

View File

@@ -1,132 +1,53 @@
# WARP-Egress — nativer Consumer-WARP (WireGuard) auf dem crs326-core # WARP-Egress — nativer Consumer-WARP (WireGuard) auf dem crs326-core
> **Status:** PLAN (noch nicht ausgeführt) · 2026-09-25 · TP-Nummer bei Anlage vergeben (nächste freie, Stand TP46). > **Status:** ❌ **VERWORFEN 2026-09-26** — Cloudflare blockt inoffizielle Consumer-WARP-WireGuard-Clients.
> **Zweck:** ausgehenden **Client**-Verkehr (alle VLANs) über Cloudflare egressen → **geteilte CF-IP** statt > Live gebaut, verifiziert, dann vollständig zurückgebaut. Key + Backup bleiben zur Nachvollziehbarkeit liegen.
> blockierter Heim-IP `90.146.33.177`. **Router-eigene Infra bleibt auf Liwest.**
> **Werkzeuge:** **MikroMCP** (`plan_changes`→`apply_plan`) für den Router-Block · **CF-MCP** zum Verifizieren ·
> `wgcf` nur für den einen Consumer-WARP-Key · `sshpass` nur für die WG-Zeilen, die MikroMCP nicht kann (TP16.1 §4.3).
> **Muster:** TP16.1 (`docs/tp16.1-warp-mesh-native-crs326.md`) — dort natives WG für **Ingress**, hier für **Egress**.
---
## 1. Kontext / Warum ## 1. Kontext / Warum
- Cannaleo-Origin `164.90.191.7` (DigitalOcean, multi-tenant, ~400 Vhosts) blockt die Heim-IP - Cannaleo-Origin `164.90.191.7` (blaueblueten.de, DigitalOcean multi-tenant, ~400 Vhosts) blockt die Heim-IP
`90.146.33.177` hart (leerer `403`, live 2026-09-25). Crawler ist aus, Projekt auf Eis — nur noch privates Surfen/Bestellen. `90.146.33.177` hart (leerer `403`, live 2026-09-25).
- Ziel: CF-Egress für **alle Clients/VLANs** (nur die zwei aktiven Nutzer, keine Einschränkung nötig). - **Scope (User-Vorgabe 2026-09-25):** nicht der ganze Outbound, sondern **genau eine Ziel-IP**
(`164.90.191.7/32` — blaueblueten.de apex + www, beide identisch). Nur **Privatbestellungen**, Traffic
überschaubar gering.
- **Terpenfinder wird NICHT über diesen Weg** in Betrieb genommen (eigene, saubere Lösung — siehe §5).
## 2. Entscheidung & Nicht-Ziele ## 2. Was gebaut wurde (2026-09-26, live)
- **Gewählt:** nativer **Consumer-WARP** als zweites WG-Interface `warpout` auf `crs326-core`. 1. **Consumer-WARP-Key** per `wgcf` registriert (ViRb3 v2.3.0, Wegwerf-Konto via `api.cloudflareclient.com`).
**Clients über WARP, Router-Infra über Liwest** (Policy-Route via **Routing-Regel** → Routing-Tabelle `warpout`). → `mcp/cloudflare/.env` (`CF_WARP_CLIENT_PRIVKEY`, gitignored) + `~/.secrets/wgcf-client/` (account + profil).
- **Verworfen:** WARP-Client als RouterOS-Container (kein `/dev/net/tun`); Mesh-Node als Egress (egressed über 2. Auf `crs326-core` (WG-Zeilen via `sshpass -e`, Rest per MikroMCP/ssh):
die **eigene** Public-IP = die blockierte); cloudflared (reiner Ingress); **Default-Route-Flip** (würde die - `/interface wireguard add name=warpout mtu=1280 private-key=… comment="WARP Egress (privat)"`
WG-Transporte von `wg-hub`/`cf-mesh`/`warpout` mitreißen → fm/dw kaputt, Hairpin). - Peer `warp-cf-pop`: public-key `bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=`,
- **Nicht-Ziel:** Dedicated Egress (paid) — bewusst „vorerst" geteilte CF-IP. endpoint `engage.cloudflareclient.com:2408`, `allowed-address=0.0.0.0/0`, `persistent-keepalive=25s`
- `/ip address add 172.16.0.2/32 interface=warpout`
- `/routing table add name=warpout fib` + `/ip route add 0.0.0.0/0 gateway=warpout routing-table=warpout`
- `/routing rule add dst-address=164.90.191.7/32 action=lookup-only-in-table table=warpout`
- NAT `masquerade out-interface=warpout` + forward `accept out-interface=warpout`
3. **Verifiziert:** Key korrekt (abgeleiteter Public-Key == Router-Public-Key
`HTFM3gj3FyT0EjWkG+2LLmvtxaFz1kH/P1iDwM0HswI=`), Konto „Active" (`wgcf status`).
## 3. Ist-Stand (live 2026-09-25) ## 3. Befund: Handshake schlägt fehl
- `crs326-core` (ROS 7.24.1): WG `cf-mesh` (Ingress `100.96.0.6/32`) + `wg-hub` (FM/DW). Kein Container am Core. - Peer `warp-cf-pop`: `rx=0`, kein `last-handshake` — Cloudflare antwortet **nie** auf den WG-Handshake,
- APs fahren `cfd-min-arm64`-cloudflared-Container (`bf-public`, ~75 MB RAM, Flash nur ~54 MB frei) → **nicht anfassen**. egal welcher Endpoint (`162.159.192.1` / `.193.2` / `.193.5`).
- Firewall **deny-by-default beide Ketten** (TP5) → Egress braucht explizite `forward`-Regel. - **Ursache (recherchiert):** Cloudflare blockt **inoffizielle WireGuard-Clients** für Consumer-WARP. Der
- Routing: Default `0.0.0.0/0 → 90.146.33.1` (vlan100). Nur Routing-Tabelle `main`, keine Mangle-Marks. offizielle Client setzt ein spezielles Handshake-Feld (`reserved`/Client-ID, z. B. `b91981`), das RouterOS
(und jedes plain-wgcf-Profil) nicht setzt; dazu Abuse-Prevention. Der Mesh-Connector `cf-mesh` läuft nur,
weil das ein **anderes Produkt** ist (Zero Trust, nicht Consumer).
- Quellen: [ViRb3/wgcf Issue #542](https://github.com/ViRb3/wgcf/issues/542) ·
[#515](https://github.com/ViRb3/wgcf/issues/515) · [#158](https://github.com/ViRb3/wgcf/issues/158).
## 4. CF-MCP: Account verifizieren (read-only, Schritt 0) ## 4. Abbau (2026-09-26)
Mit `mcp__cloudflare__execute` gegenlesen (bestätigt 2026-09-25): `warp_connector` = nur `bf-core-mesh` - Alle 8 Objekte entfernt (Routing-Regel, Route, Tabelle, NAT, Firewall, Adresse, Peer, Interface). Core
(Mesh, nicht Client) · `egress_cidr_pairs` = `[]` (kein Dedicated Egress). → es gibt **noch keinen** WARP-Client. wieder im Ursprungszustand — **keine Drift**, Golden-Config-Compliance unverändert.
> ⚠️ **Grenze des CF-MCP:** die **Consumer-WARP-Registrierung** (PrivateKey + Reserved-IPs) läuft über - Backup `pre-warp-egress-20260925.backup` liegt auf dem Core (vor dem Versuch, TP22-Regel).
> `api.cloudflareclient.com`, NICHT über die Account-API — dafür gibt es **keinen** CF-API-Endpoint. Der CF-MCP - `CF_WARP_CLIENT_PRIVKEY` bleibt in `mcp/cloudflare/.env` (nutzlos, da Client geblockt; kann bei Bedarf entfernt werden).
> kann den Account **verifizieren**, aber den Client-Key **nicht** erzeugen. Dafür §5 (wgcf), genau einmal.
## 5. Einmalig: Consumer-WARP-Key (wgcf, nicht wgcf-connector) ## 5. Weg vorwärts
``` - **Dedicated Egress IP** (Cloudflare, paid) = die „saubere Lösung". Geteilte CF-IP genügt nicht — der Origin
docker run --rm -v $(pwd):/app/output ghcr.io/animmouse/wgcf register blockt offenbar auch geteilte CF-IPs (offizielles WARP am Client liefert laut Test ebenfalls `403`).
docker run --rm -v $(pwd):/app/output ghcr.io/animmouse/wgcf generate # → wgcf-profile.conf - Alternativ: offizielles WARP am Client (Handshake funktioniert dort, aber `403`).
``` - **Nicht nochmal probieren:** Consumer-WARP über natives RouterOS-WG ist auf absehbare Zeit blockiert.
- ⚠️ **`wgcf` (Consumer) ≠ `wgcf-connector` (Mesh).** Das Repo hat bisher nur den Connector benutzt.
- `.conf` liefert: **PrivateKey**, `Address = 172.16.0.2/32` (+ v6 → ignorieren, v4-only), Peer-PublicKey
`bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=` (= gleicher CF-Wellknown-Key wie Mesh), Endpoint
`engage.cloudflareclient.com:2408` → `162.159.192.x`/`.193.x`, MTU 1280.
- **PrivateKey → `~/.secrets`/`mcp/cloudflare/.env`** (`CF_WARP_CLIENT_PRIVKEY`, `chmod 600`, nie in Git).
## 6. RouterOS — MCP-first
**Primärpfad:** `mcp__mikromcp__plan_changes` (dryRun, reviewen) → `mcp__mikromcp__apply_plan`.
**Ausnahme (WG):** MikroMCP kann WG-PrivateKey nicht, `endpoint="IP:Port"` wird falsch zerlegt,
`persistent-keepalive` fehlt (TP16.1 §4.3) → diese 4 Zeilen **einmal** via `sshpass -e` (Key aus `.env`
interpoliert, nicht im Literal; Fehlerausgabe `sed`-maskieren — CLAUDE.md-Regel).
```
# (a) sshpass — WG-Bring-up (Interface+Key, Peer mit endpoint/keepalive)
/interface wireguard add name=warpout mtu=1280 private-key="<CF_WARP_CLIENT_PRIVKEY>" comment="WARP Egress (privat)"
/interface wireguard peers add interface=warpout name=warp-cf-pop \
public-key="bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=" \
endpoint-address=<162.159.192.x|193.x> endpoint-port=2408 \
allowed-address=0.0.0.0/0 persistent-keepalive=25s
```
```
# (b) MCP plan_changes→apply_plan — alles ohne Secret
/ip address add address=172.16.0.2/32 interface=warpout comment="WARP client (v4)" # manage_ip_address
/routing table add name=warpout fib # manage_routing_table
# lokale Routen in warpout — PFLICHT, sonst läuft VLAN↔VLAN über den Tunnel!
/ip route add dst-address=10.40.10.0/24 gateway=vlan10 routing-table=warpout # manage_route (local)
/ip route add dst-address=10.40.20.0/24 gateway=vlan20 routing-table=warpout # manage_route (local)
# … analog vlan30/vlan40/vlan50/vlan90 (die exakten /24 aus den Connected-Routes übernehmen)
/ip route add dst-address=0.0.0.0/0 gateway=warpout routing-table=warpout # manage_route (Internet via WARP)
# Routing-Regel je Client-VLAN — „die Ausnahme direkt über den WG-Tunnel", kein Mangle
/routing rule add interface=vlan10 action=lookup-only-in-table table=warpout comment="Client -> WARP" # manage_routing_rule
/routing rule add interface=vlan20 action=lookup-only-in-table table=warpout
# … analog vlan30/vlan40/vlan50/vlan90
/ip firewall nat add chain=srcnat out-interface=warpout action=masquerade comment="WARP egress" # kein NAT-Tool → run_command
/ip firewall filter add chain=forward in-interface=vlan10,vlan20,vlan30,vlan40,vlan50,vlan90 \
out-interface=warpout action=accept comment="WARP egress fwd" # manage_firewall_rule
```
- **Warum Routing-Regel statt Default-Route-Flip:** `main`-Default bleibt `90.146.33.1` → der **WG-Transport** von
`warpout`/`cf-mesh`/`wg-hub` (Endpunkt-IPs) und die Router-eigenen Dienste (DNS-DoH, NTP) laufen weiter über
Liwest. Nur **Client-Ingress** (VLANs) wird umgeleitet → kein Hairpin, **fm/dw und cf-mesh bleiben unberührt**.
- **Scope:** alle Client-VLANs (10/20/30/40/50/90). `vlan99` (Mgmt) + `vlan100` (WAN) bewusst **nicht** umgeleitet.
- **DNS:** bleibt auf dem Core (DoH→CF-Gateway, TP23); nur der Verbindungs-Traffic der Clients geht durch WARP.
## 7. Nautobot / Golden Config
1. **Vorher** `/system backup` → `pre-warp-egress-<datum>.backup` (TP22-Regel 3).
2. WG-Bring-up direkt (Ausnahme #4-Muster: Privkey nicht GC-deploybar); Route/Mangle/NAT/Firewall/Adresse normal.
3. **Ist-Stand → Nautobot** intended config: Privkey als `<<REDACTED>>` (byte-identisch zur `ConfigReplace`-Maske).
4. Compliance-Features ggf. um neue Sektionen erweitern, dann `--refresh-compliance` → grün, keine Drifts.
5. **TP-Anlage** (nach User-Okay): Gitea-Issue + `### TPnn` in `docs/teilprojekte.md`.
6. Diese Datei am Ende auf `✅ AUSGEFÜHRT` + As-Built-Werte setzen.
## 8. Verifikation
- Beliebiges Client-Gerät: `curl -s https://cloudflare.com/cdn-cgi/trace` → `warp=on`, `ip=104.28.x.x`
(nicht `90.146.33.177`).
- **Cannaleo-Test:** `curl -s -o /dev/null -w "%{http_code}\n" https://blaueblueten.de/` → **200** (vorher 403).
- **Regression (wichtig!):** `wg-hub`-Peers `fm`/`dw` + `cf-mesh`-Peer `cf-pop` weiterhin `last-handshake < 60s`;
WARP-Zugriff aufs BF-Netz (Mesh) weiter ok. Beweist: Router-Infra blieb auf Liwest, nichts mitgerissen.
- `warpout`-Peer: `last-handshake < 10s`, rx/tx laufen.
## 9. Rollback
- Routing-Regeln `disable` (Clients fallen auf `main`-Default = Liwest zurück) ODER `warpout`-Interface `disable`.
- Router-Infra war nie betroffen → fm/dw/cf-mesh unberührt. Reversibel; Backup §7.1.
## 10. Gotchas
- **Kein Container am Core** (arm 32-bit, 2,9 MB frei) — natives WG ist kein Container: ein paar Config-Zeilen.
AP-Flash-Enge (54 MB) ist hier **nicht** im Spiel.
- **MikroMCP-WG-Lücken** (TP16.1 §4.3): PrivateKey, `endpoint`-Zerlegung, `persistent-keepalive` → sshpass.
- **Name ohne Bindestrich** (`warpout`) für GC-Tauglichkeit.
- **WARP = geteilte CF-IP:** verbirgt die Heim-IP, ersetzt aber nicht „sauber" (manche Seiten flaggen VPN/CF-IPs).
- **Kein Auto-Failover:** stirbt WARP (Handshake weg), verlieren **Clients** den Internetzugang (Mark bleibt,
Interface ist L3-mäßig „up"); die **Router-Infra läuft weiter** über Liwest → Router bleibt per MikroMCP
erreichbar, Rollback §9. Netwatch-Failover = optional, später.
- **Verifikation über TCP/HTTP (curl),** nicht `nc -z` (trügt hinter Proxys, TP16.1 §4.5).
## 11. Offen vor Start
1. **TP-Nummer** + Gitea-Issue (User-Okay) + Prosa-Abschnitt.
2. Consumer-WARP-Konto (wgcf `register` = neues Wegwerf-Konto, geteilte IP, bewusst).