Files
bf-infra/docs/cf-tunnel-mapping.md
Christoph Emsenhuber 884e51edd6 docs 📄 TP16 turnkey: CF-Tunnel Round-Robin=macvlan-Host-Isolation → reziprokes HA (Umsetzung eigene Session)
Root-Cause endgĂŒltig (User-Diagnose bestĂ€tigt): ein cloudflared ist blind NUR
fĂŒr macvlan/ipvlan-Container auf seinem EIGENEN Host → mehrere Connectoren auf
1 Tunnel + Round-Robin = 1/N garantierte 1033 ("jeden 3. Schuss eine Niete").
Kein Route→Connector-Pinning innerhalb eines Tunnels → HA nur ĂŒber getrennte
Tunnel: reziprokes Per-Host-Design (jeder Dienst von den anderen Hosts bedient,
3 Tunnel/2 cloudflared je Host = voll HA gegen Single-Host-Ausfall).

- cf-tunnel-mapping.md §9: Invariante + Live-Inventory v119 (Access-Modi,
  DOWN-Origins pbs/nginx-bf/hermes×2) + Ziel-Design + Umsetzungsreihenfolge;
  Abschnitte 1-8 als Historie markiert.
- teilprojekte.md TP16 umgeschrieben: Root-Cause, reziprokes HA, Access-Strang
  (hass-400=CF-Access→WARP, vw=bypass→schĂŒtzen), Status "dokumentiert,
  Umsetzung = eigene Session".
- Reine Doku, keine Tunnel-/DNS-/Container-Änderung.

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

226 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Cloudflare-Tunnel — Mapping & #1033-Diagnose (Single Source of Truth)
> **Aktueller Stand: → §9 (2026-07-10, TP16).** Abschnitte 1–8 sind Historie (Track A, 2026-06-30);
> die „3 Connectors gut/Zielbild"-Aussagen dort sind durch §9 **ĂŒberholt** (Round-Robin = macvlan-Host-Isolation → 1/N-AusfĂ€lle).
> Track A aus `docs/handoff-cf-tunnel-1033.md`. **TP16 = Analyse turnkey, Umsetzung eigene Session.**
## 1. Alle Tunnel im Account (`393c
66c36`)
| Tunnel | ID | Status | Conns | Verwendung |
|---|---|---|---|---|
| **bf.emsenhuber.net** | `70d6a4cf-
-91fab4fa7270` | **healthy** | **12 (=3 Connectors)** | **BF-Dienste — relevant** |
| fm.emsenhuber.net | `b697d124-
-384cced4db1a` | healthy | 4 (1 Connector) | FM-Standort (nas-fm), separat |
| TeilzeitCharlie | `6c784c98-
` | down | 0 | tot |
| coolify | `4f54ad8a-
` | down | 0 | tot |
| johnny2 | `acc73eb5-
` | down | 0 | tot |
| openclaw | `7a8f7b53-
` | down | 0 | tot (odroid-m1, offline) |
## 2. bf-Tunnel — die 3 Connectors (Round-Robin!)
Fingerprint via Colo-Locations (CF-API ↔ lokale cloudflared-Logs) + Arch.
**Wichtig:** DS923+ = AMD Ryzen = amd64; macmini = Apple Silicon = arm64.
| CF-Connector | arch | Host (Portainer) | LAN-IP | Docker-Netz | Vantage |
|---|---|---|---|---|---|
| `1856dfc3-
` | arm64 | **macmini** (ep20) | 10.40.20.167 | **bridge** `cloudflared_default` | **VLAN20** |
| `db713b30-
` | amd64 | **pve-LXC** (ep2) | 10.40.20.126 | host | **VLAN20** (TP14.2 2026-07-10 → #1033-Zielbild) |
| `d7454e68-
` | amd64 | **nas-bf DS923** (ep14) | 10.40.41.10 | host | VLAN1/.41 |
Alle 3 fahren **denselben Tunnel-Token** (`tunnel run`, token-managed Ingress im Dashboard).
CF round-robined Requests ĂŒber alle 3 → **jeder Origin muss von allen 3 Vantages erreichbar sein**, sonst sporadisch 1033.
Leichen auf dem NAS (exited, harmlos, aufrÀumen): `oc-tzcharlie-cloudflared`, `oc-johnny2-cloudflared`.
## 3. Ingress (token-managed, v104) — Reachability je Connector
Quelle: macmini aktiv geprobt; pve/NAS aus echten cloudflared-Fehler-Logs (tail 2000).
`OK` = erreichbar, `FAIL` = no route / down, `?` = nicht beobachtet (vermutl. OK).
| Hostname | Origin | pve | NAS | macmini | Befund |
|---|---|---|---|---|---|
| pve | https://10.40.41.100:8006 | OK | ? | OK | ok |
| hass | http://10.40.41.105:8123 | OK | **FAIL** | OK | NAS no-route (sporadisch) |
| ha-mcp | http://10.40.41.105:9583 | OK | **FAIL?** | OK | wie hass |
| pbs | https://10.40.41.135:8007 | ? | ? | **FAIL** | macmini no-route |
| n8n | http://10.40.41.167:5678 | **FAIL** | **FAIL** | **FAIL** | **.167 STALE** (Host weg) |
| mcp-ms365 | http://10.40.41.167:3005 | **FAIL** | **FAIL** | **FAIL** | **.167 STALE** |
| hermes | http://10.40.41.167:9119 | **FAIL** | **FAIL** | **FAIL** | **.167 STALE** |
| gitea-mcp | http://10.40.41.167:3000 | **FAIL** | **FAIL** | **FAIL** | **STALE → lĂ€uft auf 10.40.20.167:3000** |
| n8n-mcp | http://10.40.41.167:3001 | **FAIL** | **FAIL** | **FAIL** | **STALE → lĂ€uft auf 10.40.20.167:3001** |
| 82unkpb5 (ssh) | ssh://10.40.41.167:22 | **FAIL** | **FAIL** | **FAIL** | **STALE → macmini 10.40.20.167:22** |
| vw | http://10.40.41.127:80 | OK | **FAIL (1736×)** | **FAIL** | **pve-lokaler Container** — nur pve erreicht |
| ccu | http://10.40.41.232:80 | OK | ? | OK | wahrsch. pve-lokal |
| iobroker | http://10.40.41.19:8080 | ? | **FAIL** | **FAIL** | nur pve? prĂŒfen |
| gateway-dw | http://192.168.178.1 | ? | ? | **FAIL** | **DW-Netz, nur ĂŒber WG — kein BF-Connector hat die Route** |
| gitea | http://10.40.41.157:3000 | OK | ? | OK | ok (macmini transient) |
| nginx-bf | http://10.40.41.123:81 | OK | ? | OK | ok |
| ds-bf | http://10.40.41.10:8080 | OK | OK | OK | ok |
| portainer | https://10.40.20.126:9443 | OK | OK | OK | TP14.2: Origin .41→.20.126; Tunnel-Smoke 200 |
| grafana | http://10.40.41.109:3000 | ? | ? | OK | ok |
| pve-mcp | http://10.40.41.173:3000 | ? | ? | OK | ok |
| gateway-bf | http://10.40.41.254 | OK | ? | OK | ok (FB) |
| j44d6tua (ssh) | ssh://10.40.41.100:22 | OK | ? | OK | ok |
| 3k23uow7 (ssh) | ssh://10.40.41.10:22 | OK | OK | OK | ok |
| (catch-all) | http_status:404 | — | — | — | — |
## 4. DNS-Probleme (Zone emsenhuber.net, `1b5bc02f
`)
**Orphan-CNAME → bf-Tunnel, aber KEINE Ingress-Regel → 404:**
- `mcp-qdrant.emsenhuber.net`, `ssh-nasbfnew.emsenhuber.net`
**CNAME → tote/gelöschte Tunnel → konstante 1033:**
- `oc`, `dashboard`, `drawio` → openclaw (down)
- `jc` → johnny2 (down) · `charlie` → TeilzeitCharlie (down) · `coolify` → coolify (down)
- `oc2` → `d8df70a7
`, `oc3` → `3702dc6e
`, `win11test` → `de818071
` — **Tunnel existiert nicht mehr**
(FM-Tunnel-CNAMEs `ds-fm`/`gateway-fm` → `b697d124
` healthy = ok, separat.)
## 5. Root-Cause #1033 (zusammengefasst)
1. **3 Connectors mit asymmetrischer Reachability** + Round-Robin = sporadisch 1033 (Kernursache, log-bewiesen).
2. **pve-lokale Container** (`vw .127`, `ccu .232`) nur vom pve-Connector erreichbar (macvlan, kein LAN-Route von NAS/macmini).
3. **Stale Origin `.41.167`**: macmini nach VLAN20 (`10.40.20.167`) gewandert → 5 Dienste zeigen ins Leere.
4. **gateway-dw** braucht WG-Route — kein BF-Connector hat sie.
5. **DNS-MĂŒll**: 9 CNAMEs auf tote Tunnel (konstante 1033) + 2 Orphans (404).
## 6. Fix-Plan (gestaffelt — Freigabe nötig)
**Stufe 1 — Sofort-EntschĂ€rfung — ✅ ANGEWENDET 2026-06-30:**
- bf-Tunnel auf **nur pve-Connector** reduziert (NAS ep14 + macmini ep20 cloudflared gestoppt, reversibel via `start`).
- Verifiziert: Tunnel `healthy`, 1 Connector (`db713b30`/pve). Smoketest `vw` 4×200 (vorher 1736 Fehlversuche), `hass`/`portainer` 302. **Kein 1033 mehr.**
**Stufe 2 — Stale-Origins fixen (Dashboard-Ingress) — OFFEN, braucht Entscheidungen:**
Die .167-Dienste laufen real auf dem **macmini (ep20, VLAN20 10.40.20.167)** — aber uneinheitlich:
- `gitea-mcp` → `10.40.20.167:3000` ✓ · `n8n-mcp` → `10.40.20.167:3001` ✓ · `82unkpb5 ssh` → `10.40.20.167:22` ✓ (saubere Host-Ports)
- `n8n` (`n8nio/n8n`): **kein Host-Port** (`pub=[]`) → nur im Docker-Netz, von pve NICHT routbar. Entscheidung: Port publishen ODER macmini-lokalen Connector ODER stilllegen.
- `hermes`: **2 Instanzen** — `hermes-christoph` `10.40.20.167:8642`, `hermes-geli` `10.40.20.167:8643`. Ingress-Port `9119` obsolet → klĂ€ren, welche `hermes.emsenhuber.net` bedienen soll.
- `mcp-ms365`: **auf keinem Host gefunden** → Ingress + DNS entfernen?
- ⚠ **Vor Repoint zu verifizieren:** erreicht der pve-Connector (.41.126, FB-Default-GW!) ĂŒberhaupt VLAN20 (.20.167)? → beim Apply per Smoketest prĂŒfen, sonst Rollback.
**Stufe 3 — DNS-Hygiene:**
- Tote CNAMEs löschen: `oc`,`oc2`,`oc3`,`win11test`,`jc`,`charlie`,`coolify`,`dashboard`,`drawio`.
- Orphans `mcp-qdrant`,`ssh-nasbfnew`: Ingress-Regel ergÀnzen **oder** CNAME löschen.
- NAS-Leichen `oc-tzcharlie`/`oc-johnny2` entfernen.
---
## 7. CHANGE-SET — ✅ KOMPLETT 2026-06-30
> Zugang ĂŒber **scoped API-Token** in `mcp/cloudflare/.env` (OAuth-MCP blieb read-only).
> **A1 + A2 + A3 alle angewendet.** Endzustand: Tunnel healthy/1 Connector (pve), Ingress v106,
> 23 Ingress-Hostnames ↔ 23 DNS-CNAMEs, keine Waisen, keine CNAMEs auf tote Tunnel.
### ✅ Erledigt
- **A1:** n8n-Compose-Port `10.40.41.167→10.40.20.167` (Stack 174 redeploy, Volume/Encryption-Key erhalten,
`/healthz` 200). NAS-Leichen `oc-tzcharlie`/`oc-johnny2` entfernt.
- **A2 (Ingress v106):** gitea-mcp/n8n-mcp/82unkpb5/n8n/hermes → `.20.167`; `hermes-geli` (:8643) neu;
`mcp-ms365` entfernt. Keine `.41.167`-Origins mehr. pve→VLAN20 verifiziert (n8n-mcp 200 via bf4).
- **App-Level-Notizen (kein 1033):** `gitea-mcp` 404 auf `/` (Sub-Pfad?), `hermes` 502 (Origin .20.167:8642
erreicht, App liefert 502) — separat prĂŒfen.
### ✅ A3 (DNS) erledigt
- `hermes-geli` CNAME → `70d6a4cf
.cfargotunnel.com` (proxied) angelegt → jetzt erreichbar (302).
- Gelöscht: `oc`,`oc2`,`oc3`,`win11test`,`jc`,`charlie`,`coolify`,`dashboard`,`drawio`,`mcp-ms365`,
`mcp-qdrant`,`ssh-nasbfnew`.
- Konsistenz verifiziert: 23↔23, keine Orphans, keine toten Tunnel-Verweise.
### UrsprĂŒnglicher Plan (Referenz)
### A. Portainer (Write vorhanden — kann sofort, careful):
- **macmini n8n-Container** mit `-p 5678:5678` neu erstellen (Volumes/ENV erhalten!) → Origin `10.40.20.167:5678`.
- NAS-Leichen entfernen: `oc-tzcharlie-cloudflared`, `oc-johnny2-cloudflared` (exited).
### B. Tunnel-Ingress `70d6a4cf
` (PUT /configurations) — Ziel-Origins:
| Hostname | NEU | alt |
|---|---|---|
| gitea-mcp | `http://10.40.20.167:3000` | .41.167:3000 |
| n8n-mcp | `http://10.40.20.167:3001` | .41.167:3001 |
| 82unkpb5 (ssh) | `ssh://10.40.20.167:22` | .41.167:22 |
| n8n | `http://10.40.20.167:5678` | .41.167:5678 (nach A) |
| hermes | `http://10.40.20.167:8642` | .41.167:9119 |
| **hermes-geli** (NEU) | `http://10.40.20.167:8643` | — |
| mcp-ms365 | **Regel löschen** | .41.167:3005 |
⚠ **Vor B: pve→VLAN20-Reachability per Smoketest verifizieren** (1 Repoint, extern testen, sonst Rollback — pve hat FB-Default-GW).
### C. DNS (Zone `1b5bc02f
`) — CNAMEs löschen:
`oc`, `oc2`, `oc3`, `win11test`, `jc`, `charlie`, `coolify`, `dashboard`, `drawio`, `mcp-ms365`.
**Neu anlegen:** `hermes-geli.emsenhuber.net` CNAME → `70d6a4cf-aa1d-4a91-b918-91fab4fa7270.cfargotunnel.com` (proxied).
**Orphans** `mcp-qdrant`, `ssh-nasbfnew`: ohne Ingress → löschen (oder Ingress ergĂ€nzen, falls Dienst gewĂŒnscht — offen).
**Stufe 4 — Zielbild (ĂŒberlappt Track C / IP-Migration):**
- Origins auf konkret routbare IPs in VLAN20 konsolidieren, dann **HA-Connector-Paar** (z.B. pve + NAS) **beide in VLAN20**, sodass jeder Connector jede Origin erreicht. `gateway-dw` ĂŒber WG-fĂ€higen Connector lösen.
- TP5-Firewall ZULETZT (erst wenn alle Origins/Connectors in VLAN20).
---
## 8. Update 2026-07-09 — NAS→VLAN20-Cutover + Ingress v116
Nach NAS-DSM-Cutover auf `10.40.20.10` und Docker-Migration auf ein Macvlan `vlan20`
(alle NAS-Container jetzt `10.40.20.x`, s. `docs/nas-vlan20/`):
**Ingress v115→v116 (via scoped Token, `cf_repoint`):** 6 Origins `.41→.20` repointet —
`ha-mcp` .105:9583, `3k23uow7`(NAS-ssh) .10:22, `gitea` .157, `vw` .127, `grafana` .109, `pve-mcp` .173.
Keine `.41`-Stale unter den migrierten Hosts mehr. Bleibt `.41`: pve .100, j44d6tua .100,
portainer .126, nginx-bf .123, gateway-bf .254.
**Connector-Reachability — geklĂ€rt (kein Routing-Problem):** Der pve-Connector `.41.126` **erreicht
VLAN20** — `vw.emsenhuber.net` → **200** ĂŒber den Tunnel (Vaultwarden `.20.127` lĂ€uft). ap1 macht das
Inter-VLAN-Routing VLAN1↔VLAN20, das steht. Ein `502` direkt **nach** dem Ingress-PUT war **transient**
(Connector-Origin-Cache/ARP noch nicht warm), verschwindet nach kurzer Zeit. `grafana` `502` = Container
`exited` (starten → geht). **Kein pve-Static-Route nötig.**
**Bleibt offen (Stufe 4, Connector-Vantage — nicht dringend):** Round-Robin-Asymmetrie #1033, falls
mehrere Connectors aktiv: macmini (`.20.167`, VLAN20) erreicht NAS-Macvlan, scheitert aber an
pve-lokalen Origins/pbs/gateway-dw; NAS-eigener host-net-Connector taugt nicht (Host↔eigene-Macvlan-
Isolation). Zielbild = **ein** Connector, der alles erreicht — löst sich weitgehend von selbst, sobald
pve (+ Connector) mit dem PVID1-Cutoff in VLAN20 wandert (dann sind Origins+Connector im selben L2).
---
## 9. Ist-Inventory & Endanalyse 2026-07-10 (TP16) — SSoT-Stand
> ⚠ Die „3 Connectors sind gut/Zielbild"-Framings der Abschnitte 2/6/8 oben sind **ĂŒberholt** — maßgeblich
> ist dieser Abschnitt. **Analyse turnkey; Umsetzung = eigene Session** (User-Entscheidung).
### 9.1 Invariante (die Regel, an der alles hÀngt)
- **Ein cloudflared-Connector ist blind NUR fĂŒr macvlan/ipvlan-Container auf seinem EIGENEN Host**
(Linux-Kernel: Host ↔ eigene macvlan/ipvlan-Children isoliert). Fremdhost-L2 + co-lokierte *Bridge*-Container
erreicht er sehr wohl.
- **Mehrere Connectoren auf EINEM Tunnel = geteilter Ingress + CF-Round-Robin.** Jede Origin, die auf dem Host
*eines* Connectors als macvlan/ipvlan liegt, fĂ€llt bei ~**1/N** der Requests aus (#1033, „jeden 3. Schuss eine Niete").
**Strukturell** — nicht durch „Origins fixen" heilbar, solange ein Connector Origins seines eigenen Hosts bedient.
- **Kein Route→Connector-Pinning INNERHALB eines Tunnels.** „AusgewĂ€hlte Routen fĂŒr ausgewĂ€hlte Connectoren" gibt
es nur ĂŒber **getrennte Tunnel** (CNAME → jeweiliger Tunnel; pro Tunnel eigene Connectoren).
### 9.2 Live-Inventory (gemessen 2026-07-10, Ingress **v119**, 24 Hostnames + catch-all, 2 live Connectoren `b797ee1b`/`f480dc69`)
CF-Access: **`vw` = `bypass` (ÖFFENTLICH!)** ⚠ · `hass` & Rest geschĂŒtzt via Wildcard `*.emsenhuber.net`
(`allow:christoph` / `non_identity:bf4` / `allow:claude-mcp`).
| Hostname | Origin | Live | Host/Netz (zu verifizieren) |
|---|---|---|---|
| pve / j44d6tua(ssh) | `.41.100:8006` / `:22` | UP | Proxmox-Host (VLAN1) |
| hass / ha-mcp | `.20.105:8123` / `:9583` | UP | HA-Host .105 |
| pbs | `.20.135:8007` | **DOWN** | Proxmox Backup Server |
| n8n / hermes / hermes-geli / gitea-mcp / n8n-mcp / 82unkpb5(ssh) | `.20.167:*` | n8n/mcp UP · **hermes+hermes-geli DOWN** | macmini |
| portainer | `.20.126:9443` | UP | pve-LXC (host-net) |
| nginx-bf | `.41.123:81` | **DOWN** | **noch VLAN1!** |
| ds-bf / 3k23uow7(ssh) | `.20.10:8080` / `:22` | UP | NAS-Host |
| gitea / grafana / pve-mcp | `.20.157` / `.20.109` / `.20.173` | UP | **NAS-macvlan** (NAS-Connector-blind) |
| omada | `.20.175:8043` | UP | **NAS-macvlan** (NAS-Connector-blind) |
| ccu / vw / iobroker / z2m25 | `.20.232` / `.20.127` / `.20.107:8081` / `.20.106:8080` | UP | **Host/Netz unklar → messen** |
| gateway-dw | `192.168.178.1` | — | **nur via WG** (kein BF-Connector hat Route) |
### 9.3 Ziel-Design: reziproke Per-Host-Tunnel (HA)
Jeder Host-Dienst wird von den Connectoren der **anderen** Hosts bedient (nie vom eigenen), gegenseitig:
| Tunnel (= Dienste eines Hosts) | Connectoren auf | HA |
|---|---|---|
| pve-Dienste | NAS + macmini | 1 abdrehbar |
| NAS-Dienste (omada/pve-mcp/gitea/grafana/
) | pve + macmini | 1 abdrehbar |
| macmini-Dienste (`.20.167`) | pve + NAS | 1 abdrehbar |
3 Tunnel, jeder Host fĂ€hrt **2 cloudflared** (fĂŒr die 2 anderen Tunnel) → Host-Ausfall ⇒ jeder Tunnel ≄1 Connector = **voll HA**.
Der macmini ist vollwertiger dritter Knoten (nicht „vergessen").
### 9.4 Umsetzungs-Reihenfolge (eigene Session)
1. **Reachability-Matrix je Host** (pve/NAS/macmini → jede der 24 Origins, read-only) — klĂ€rt v.a. `vw`/`ccu`/`iobroker`/`z2m25`
(Bridge nur-eigener-Host? macvlan? ipvlan-auf-pve → dann pve-blind!). Ergebnis bestimmt die Tunnel-Gruppierung.
2. **Interim-Sofortfix:** bf-Tunnel auf **pve-only** (pve erreicht alles außer gateway-dw) → 0×1033. Reversibel.
3. **Reziprokes 3-Tunnel-HA bauen:** 3 Tunnel anlegen, ~24 CNAMEs re-pointen, 6 Connectoren (2/Host, je eigenes Token),
Alt-Token aus NAS/macmini-cloudflared entfernen. `vw`/`ccu` ggf. auf VLAN20-macvlan heben (dann L2-erreichbar).
4. **Tote Origins bereinigen:** `pbs`, `nginx-bf` (noch .41!), `hermes`, `hermes-geli`.
5. **Access-Strang (Track B):** `hass`-400 ohne Passthrough → iPhone in **WARP** enrollen; **`vw` von bypass → geschĂŒtzt**.
6. **Loop-Gegentest** aller FQDNs (0×1033), `gateway-dw` als WG-Sonderfall klĂ€ren/entfernen.