diff --git a/docs/warp-egress-native-crs326.md b/docs/warp-egress-native-crs326.md index 1cc4cba..b3ea3da 100644 --- a/docs/warp-egress-native-crs326.md +++ b/docs/warp-egress-native-crs326.md @@ -1,132 +1,53 @@ # 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). -> **Zweck:** ausgehenden **Client**-Verkehr (alle VLANs) über Cloudflare egressen → **geteilte CF-IP** statt -> 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**. - ---- +> **Status:** ❌ **VERWORFEN 2026-09-26** — Cloudflare blockt inoffizielle Consumer-WARP-WireGuard-Clients. +> Live gebaut, verifiziert, dann vollständig zurückgebaut. Key + Backup bleiben zur Nachvollziehbarkeit liegen. ## 1. Kontext / Warum -- Cannaleo-Origin `164.90.191.7` (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. -- Ziel: CF-Egress für **alle Clients/VLANs** (nur die zwei aktiven Nutzer, keine Einschränkung nötig). +- 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). +- **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`. - **Clients über WARP, Router-Infra über Liwest** (Policy-Route via **Routing-Regel** → Routing-Tabelle `warpout`). -- **Verworfen:** WARP-Client als RouterOS-Container (kein `/dev/net/tun`); Mesh-Node als Egress (egressed über - die **eigene** Public-IP = die blockierte); cloudflared (reiner Ingress); **Default-Route-Flip** (würde die - WG-Transporte von `wg-hub`/`cf-mesh`/`warpout` mitreißen → fm/dw kaputt, Hairpin). -- **Nicht-Ziel:** Dedicated Egress (paid) — bewusst „vorerst" geteilte CF-IP. +1. **Consumer-WARP-Key** per `wgcf` registriert (ViRb3 v2.3.0, Wegwerf-Konto via `api.cloudflareclient.com`). + → `mcp/cloudflare/.env` (`CF_WARP_CLIENT_PRIVKEY`, gitignored) + `~/.secrets/wgcf-client/` (account + profil). +2. Auf `crs326-core` (WG-Zeilen via `sshpass -e`, Rest per MikroMCP/ssh): + - `/interface wireguard add name=warpout mtu=1280 private-key=… comment="WARP Egress (privat)"` + - Peer `warp-cf-pop`: public-key `bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=`, + 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. -- APs fahren `cfd-min-arm64`-cloudflared-Container (`bf-public`, ~75 MB RAM, Flash nur ~54 MB frei) → **nicht anfassen**. -- Firewall **deny-by-default beide Ketten** (TP5) → Egress braucht explizite `forward`-Regel. -- Routing: Default `0.0.0.0/0 → 90.146.33.1` (vlan100). Nur Routing-Tabelle `main`, keine Mangle-Marks. +- Peer `warp-cf-pop`: `rx=0`, kein `last-handshake` — Cloudflare antwortet **nie** auf den WG-Handshake, + egal welcher Endpoint (`162.159.192.1` / `.193.2` / `.193.5`). +- **Ursache (recherchiert):** Cloudflare blockt **inoffizielle WireGuard-Clients** für Consumer-WARP. Der + 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` -(Mesh, nicht Client) · `egress_cidr_pairs` = `[]` (kein Dedicated Egress). → es gibt **noch keinen** WARP-Client. -> ⚠️ **Grenze des CF-MCP:** die **Consumer-WARP-Registrierung** (PrivateKey + Reserved-IPs) läuft über -> `api.cloudflareclient.com`, NICHT über die Account-API — dafür gibt es **keinen** CF-API-Endpoint. Der CF-MCP -> kann den Account **verifizieren**, aber den Client-Key **nicht** erzeugen. Dafür §5 (wgcf), genau einmal. +- Alle 8 Objekte entfernt (Routing-Regel, Route, Tabelle, NAT, Firewall, Adresse, Peer, Interface). Core + wieder im Ursprungszustand — **keine Drift**, Golden-Config-Compliance unverändert. +- Backup `pre-warp-egress-20260925.backup` liegt auf dem Core (vor dem Versuch, TP22-Regel). +- `CF_WARP_CLIENT_PRIVKEY` bleibt in `mcp/cloudflare/.env` (nutzlos, da Client geblockt; kann bei Bedarf entfernt werden). -## 5. Einmalig: Consumer-WARP-Key (wgcf, nicht wgcf-connector) +## 5. Weg vorwärts -``` -docker run --rm -v $(pwd):/app/output ghcr.io/animmouse/wgcf register -docker run --rm -v $(pwd):/app/output ghcr.io/animmouse/wgcf generate # → wgcf-profile.conf -``` -- ⚠️ **`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="" 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-.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 `<>` (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). +- **Dedicated Egress IP** (Cloudflare, paid) = die „saubere Lösung". Geteilte CF-IP genügt nicht — der Origin + blockt offenbar auch geteilte CF-IPs (offizielles WARP am Client liefert laut Test ebenfalls `403`). +- Alternativ: offizielles WARP am Client (Handshake funktioniert dort, aber `403`). +- **Nicht nochmal probieren:** Consumer-WARP über natives RouterOS-WG ist auf absehbare Zeit blockiert.