Files
bf-infra/docs/tp16.1-warp-mesh-native-ap1.md
Christoph Emsenhuber d52cf16e0b docs 📋 TP16.1: Konzept+Runbook Private Access via native Cloudflare Mesh (WireGuard) auf ap1
Incident-Nachgang 2026-07-16: ICMP über den cloudflared-WARP-Pfad ist strukturell
kaputt (TCP ok überall, Ping fm 36%/bf 100%/dw 100% Loss) — cloudflared ist ein
QUIC-L7-Proxy, kein WireGuard. Richtungsentscheid: Private Access (unterwegs ->
10.40.0.0/16 inkl. ICMP) wandert vom cloudflared-Proxy auf einen nativen
Cloudflare-Mesh-Node (WireGuard) auf ap1 -- kein Container/TUN/LXC/neue HW
(RouterOS-Container haben kein /dev/net/tun -> hAP ax3 löst es nicht, zudem WiFi6).
Public-FQDNs bleiben unverändert auf dem cloudflared-3-Tunnel-HA.

- Neu: docs/tp16.1-warp-mesh-native-ap1.md (Konzept + vollständiges Runbook +
  gemessener Account-Ist-Stand, Team emsenhuber.cloudflareaccess.com)
- cf-tunnel-mapping.md §13: ICMP-Dreiländer-Befund; "bf-pve wegen USV" REVIDIERT
  (Begründung invertiert -- bf-pve-Connectoren laufen auf NAS+macmini, nicht pve)
- cf-tunnel-mapping.md §14 + teilprojekte.md TP16.1: Richtungsentscheid dokumentiert

Scharfschalten = eigene Session (CF-Prereqs sind account-weit, treffen Live-WARP).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 22:10:00 +02:00

9.2 KiB
Raw Blame History

TP16.1 — Private Access via native Cloudflare Mesh (WARP Connector) auf ap1

Status: Konzept + Runbook fertig (2026-07-16), Scharfschalten = eigene Session. Selbst-tragend: eine frische Session kann das mit diesem Doc + docs/cf-tunnel-mapping.md straight bauen. SSoT-Kontext: docs/cf-tunnel-mapping.md §13/§14, Memory project_cf_tunnel_1033.

1. Warum überhaupt / Root Cause

Incident 2026-07-16 (unterwegs): keine BF-IPs über WARP. Diagnose:

  • TCP über den CF-WARP-Pfad funktioniert (SSH, alle Web-UIs, MCP-Endpoints erreichbar) —
  • ICMP ist strukturell kaputt. Dreiländer-Ping-Befund: fm 36 % Loss (ICMP-Proxy über QUIC-Connector, funktioniert aber mies), bf 100 % (macmini-Connector läuft seit dem http2-Fix von heute = QUIC-los → ICMP-unfähig; zusätzlich cloudflared-Container ohne Ping-Sockets), dw 100 % (192.168.0.0/16 steht in der WARP-Split-Tunnel-Exclude → Pings betreten den Tunnel gar nicht).

Kernursache: cloudflared ist kein WireGuard, sondern ein QUIC/HTTP2-L7/L4-Proxy. ICMP darüber ist Zusatz-Gefrickel (Account-ICMP-Flag + QUIC-Transport + ping_group_range-sysctl je Host) und war nie zuverlässig eingerichtet. Der WARP-Client selbst spricht WireGuard — die passende Gegenstelle für einen sauberen privaten L3-Zugang ist deshalb Cloudflare Mesh (WARP Connector), ebenfalls WireGuard.

2. Entscheidungsweg (was verworfen wurde und warum)

  • WG-Roadwarrior (eigene WG-Peers je Gerät): ❌ verworfen — User will KEINE Extra-App/kein Profil pro Gerät. „Ein Client = WARP für alles" bleibt Anforderung.
  • Alle ZT-Anbieter mit Helper-Host (CF WARP Connector als Daemon-Host, Tailscale, NetBird, Twingate): brauchen dauerhaft einen Linux-Host → verletzt „Router = einziger SPOF, keine Abhängigkeit zu anderen Rechnern".
  • Connector als RouterOS-Container: ❌ nicht möglich — RouterOS-7-Container haben kein /dev/net/tun- Passthrough; der WARP-Connector-Daemon braucht ein TUN-Device. Gilt auf jeder Router-HW (hAP ax²/ax³/CRS/RB5009). → hAP ax³ löst das NICHT (und ist zudem Wi-Fi 6, nicht 7 — kein WLAN-Gewinn ggü. ax²). HW-Kauf ist vom Tunnel-Fix entkoppelt (separat unter TP15 zu bewerten, falls 2,5G/USB/CPU gewünscht).
  • ✅ Gewählt: Cloudflare Mesh als NATIVES WireGuard-Interface auf ap1. Cloudflare Mesh spricht WireGuard, RouterOS kann natives WireGuard (der TP10-Hub ist schon einer). Ein Mesh-Node wird als WG-Peer zu einem CF-PoP registriert — kein Container, kein TUN, kein LXC, keine neue HW. Erfüllt „ap1 = einziger SPOF" am besten, keine macvlan-Blindheit (ap1 routet alle VLANs nativ L3), ICMP/TCP/UDP nativ.

Quelle/Vorlage: animmouse „Setup Cloudflare WARP Connector on MikroTik" + „Setup Cloudflare Mesh using WireGuard". Ehrliche Einschränkung: von uns noch nicht gebaut — starker, technisch schlüssiger Lead; echter Beweis = bauen+pingen.

3. Ist-Stand Account (gemessen 2026-07-16, read-only)

  • Team-Domain: emsenhuber.cloudflareaccess.com → Mesh-Node-Identität = warp_connector@emsenhuber.cloudflareaccess.com
  • Noch KEIN warp_connector-Tunnel im Account (GET /accounts/…/warp_connector = []).
  • Device-Settings: use_zt_virtual_ip: false (Unique-Device-IP AUS — muss für Mesh AN).
  • Split-Tunnel-Modus = Exclude; Exclude-Liste enthält u.a. 100.64.0.0/10 (schluckt die Mesh-Overlay-Range 100.96.0.0/12 → Mesh-Traffic würde aktuell NICHT durch WARP gehen). Enthält NICHT 10.0.0.0/8 → deshalb geht 10.40.0.0/16 schon heute über WARP (= warum TCP funktioniert).
  • vnet-Route 10.40.0.0/16 (vnet 1480b545…, Route-ID 5546dcb6-5901-4da6-8d91-b17f94703f71) zeigt aktuell auf cfd_tunnel bf-pve (f7fdf3a6…). Das bleibt der Fallback, bis Mesh bewiesen ist — nichts vorher löschen.
  • ap1-WireGuard IST-Stand: 1 Interface wg-hub (listen 51821, MTU 1412), Peers fm (10.101.0.0/24) + dw (10.95.10.0/24). Das neue Mesh-Interface ist separat (outbound zum CF-PoP, kein Listen-Port) → keine Kollision.

4. Runbook (nächste Session — Reihenfolge)

4.0 Plan-Probe (billig, reversibel) — ZUERST

POST /accounts/{account_id}/warp_connector {name:"bf-ap1-mesh"} via CF_API_TOKEN (curl/Bearer — der cloudflare- MCP ist read-only, s. §11 der Mapping-Doc). Erfolgt der Create → Mesh ist im Free-ZT-Plan erlaubt. Scheitert er mit Plan-/Auth-Fehler → Stopp, Fallback = LXC-auf-pve-WARP-Connector (alter Plan, ebenfalls dokumentiert). Token danach: GET /accounts/…/warp_connector/{tunnel_id}/token → das ist das eyJhIjoi…In0=-Register-Token.

4.1 CF-Prerequisites setzen (⚠️ account-weit, trifft LIVE-Geräte → 1× kurzer WARP-Reconnect einplanen)

  1. Unique Device IP AN: PATCH /accounts/…/devices/settings {use_zt_virtual_ip:true} (Dashboard: Team & Resources → Devices → Management → „Assign a unique IP address to each device").
  2. „Allow all Cloudflare One traffic to reach enrolled devices" AN (gleiche Seite).
  3. Device-Profile „Cloudflare Mesh" anlegen: Match identity.email == warp_connector@emsenhuber.cloudflareaccess.com, Tunnel-Protokoll = WireGuard (POST /accounts/…/devices/policy).
  4. Split-Tunnel-Exclude anpassen (PUT /accounts/…/devices/policy/exclude — ⚠️ ersetzt die GANZE Liste, erst GET, dann editiert zurückschreiben): 100.64.0.0/10 raus, dafür 100.64.0.0/11 + 100.112.0.0/12 rein (= 100.64/10 minus 100.96/12 → Mesh-Overlay 100.96.0.0/12 läuft nun durch WARP statt als „local" behandelt zu werden).

4.2 WireGuard-Config extrahieren (einmalig, ephemer)

Auf macmini oder pve (Docker vorhanden):

docker run --rm -v $(pwd):/app/output ghcr.io/animmouse/wgcf-connector <REGISTER_TOKEN>

→ erzeugt wgcf-connector-<id>.conf mit: PrivateKey, Address (100.96.x.y/32), Peer-PublicKey (= CF-Wellknown bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=), Endpoint (162.159.193.x:2408). Registriert den Node via CF-API (macht Netz-Call), läuft danach nie wieder. PrivateKey nach mcp/cloudflare/.env o. ~/.secrets (nicht committen).

4.3 ap1 nativ konfigurieren (MikroMCP: plan_changes dryRun → apply_plan)

/interface wireguard add name=cf-mesh mtu=1420 private-key="<PrivateKey aus .conf>"
/interface wireguard peers add interface=cf-mesh name=cf-pop \
    public-key="bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=" \
    endpoint-address=162.159.193.1 endpoint-port=2408 \
    allowed-address=0.0.0.0/0,::/0 persistent-keepalive=25s
/ip address add address=<100.96.x.y>/32 interface=cf-mesh
/ip route add dst-address=100.96.0.0/12 gateway=cf-mesh
  • Endpoint: falls die Config 162.159.192.x liefert → 162.159.193.x nehmen (Latenz-Tuning laut Guide).
  • MTU 1420 aus dem Guide; gegen unsere Hub-MTU 1412 gegenprüfen (ggf. angleichen bei Path-MTU-Problemen).
  • Kein Extra-Static-Route für den Rückweg nötig (anders als der LXC-Plan): ap1 IST der L3-Router aller VLANs.
  • Firewall: forward ist aktuell permissiv (TP5-Deny offen) → kein neues Loch nötig; falls doch ein Drop greift, gezielte Accept 100.96.0.0/12 ↔ 10.40.0.0/16 dokumentiert ergänzen.
  • ⚠️ Governance: „Config nur via Nautobot" (TP21) → diese ap1-Zeilen entweder über Nautobot GC abwickeln oder als vom User genehmigte Ausnahme dokumentieren (Nachtrag in GC als Follow-up).

4.4 Subnetz-Route + vnet-Route umziehen

  • Im Mesh-Node 10.40.0.0/16 als CIDR-Route announcen (Dashboard Networks → Routes: Node = neuer Mesh-Tunnel, oder API).
  • vnet-Route 5546dcb6… von bf-pve auf den neuen warp_connector-Tunnel umhängen: PATCH /accounts/…/teamnet/routes/5546dcb6… {tunnel_id: <warp_connector_id>}.
  • Rollback jederzeit: PATCH zurück auf f7fdf3a6… (bf-pve) — cloudflared/bf-pve bleibt die ganze Zeit bestehen.

4.5 Verifikation (Abnahme)

  • MacBook, WARP connected: ping 10.40.20.105, ping 10.40.10.1, ping 10.40.99.12 → verlustfrei (Regressions-Gegenprobe zu heute: fm 36 % / bf 100 %).
  • TCP-Gegenprobe inkl. NAS-macvlan-IP direkt: ssh 10.40.20.167, https://10.40.20.100:8006, 10.40.20.157:3000 (gitea) mehrfach → Beweis „keine Blindheit".
  • FQDN-Smoke (Stichprobe gitea/hass/pve über *.emsenhuber.net) → der cloudflared-Public-Teil (3-Tunnel-HA) blieb unberührt.

5. Danach (Cleanup, teils ins „vertagt"-Gespräch)

  • Nach Mesh-Beweis: warp-routing auf bf-nas/bf-pve/bf-mm ggf. auf false (Hygiene — Public-Tunnel bedienen keine privaten Netze mehr). CF-vnet-Route-Historie bereinigen.
  • Vertagt (User „müssen wir noch reden, hat Zeit"): 4 tote Tunnel (TeilzeitCharlie/coolify/johnny2/openclaw), Ghost-Connector-Session bf-pve (arm64-Leiche vom 12.07.), gateway-dw-CNAME.

6. Risiken / Fallbacks

  • Einziger Eingriff mit Nutzer-Impact = vnet-Route-Umzug → Rollback = 1 PATCH zurück auf bf-pve.
  • CF-Prerequisites sind account-weit (Unique-IP-ReIP, Split-Tunnel) → 1× kurzer WARP-Reconnect; alle reversibel.
  • Plan-Gate: wenn warp_connector-Create scheitert → LXC-auf-pve-WARP-Connector als Fallback (TUN-Passthrough c 10:200 rwm, warp-cli connector new, ap1-Static-Route 100.96.0.0/12→LXC).
  • ax³/ZeroTier/Tailscale = separate Eval-Fußnoten, nicht Teil dieses Fixes.