Files
bf-infra/docs/cf-tunnel-mapping.md
Christoph Emsenhuber 4b63f5cdb3 docs 📄 TP16 Schritt 5: vw-Access-Leck geschlossen + Wildcard-login_method-Fund
vw von bypass/everyone auf non_identity(Heim-IP)+allow(email:christoph) umgestellt
(reusable-Policy via App-PUT detacht). Neuer 🔴 Fund dokumentiert: Wildcard
*.emsenhuber.net login_method:github/google = jeder Eingeloggte erreicht alles
(user-gated). hass-400 = HA-Origin (nicht Access), gateway-dw WG offen. §10.6.

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

276 lines
21 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: → §10 (2026-07-10, TP16 UMGESETZT ✅).** §9 = Analyse/Zielbild, §10 = As-Built.
> Abschnitte 1–8 sind Historie (Track A, 2026-06-30); die „3 Connectors gut/Zielbild"-Aussagen dort sind
> durch §9/§10 **überholt** (Round-Robin = macvlan-Host-Isolation → 1/N-Ausfälle). Track A aus `docs/handoff-cf-tunnel-1033.md`.
## 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.
---
## 10. AS-BUILT 2026-07-10 (TP16 umgesetzt) — reziprokes 3-Tunnel-HA ✅
> Gebaut & verifiziert in eigener Session. Round-Robin-#1033 **strukturell weg** (Loop-Gegentest 0×530 über alle 19 Live-FQDNs, HA per Host-Ausfall-Sim bewiesen). Schritte 1–4+HA durch; **Schritt 5 (Access/WARP + `vw`) offen** (user-gated).
### 10.1 Reachability-Matrix (die Basis, read-only gemessen)
Einzige Blindheit im System: **NAS-Connector (host-net) ↔ NAS-Docker-macvlan** (Kernel-Isolation). Alles andere cross-host-L2 / inter-VLAN-geroutet erreichbar.
- **NAS-`vlan20` = macvlan** (parent `ovs_eth0`): gitea `.157`, grafana `.109`, pve-mcp `.173`, omada `.175`, vw `.127`, drawio `.139`, prometheus `.151`, iob_slave `.33` → **NAS-Connector blind**.
- **pve-LXC-400-`vlan20` = ipvlan** (parent `veth20`): adguard `.16/.17`, omada-mcp `.176` → pve-Connector blind, aber **keine davon ist Tunnel-Origin** → irrelevant.
- **macmini** = alles Docker-**bridge + Port-Publish** auf `.20.167` → keine Blindheit.
- `ccu .232`=RaspberryMatic(qemu/330), `iobroker .107`=iob-exposed(lxc/150), `z2m25 .106`=lxc/112, `hass/ha-mcp .105`=haos(qemu/100) = **pve-Gäste auf vmbr/VLAN20** → von allen erreichbar (keine Docker-macvlan-Kinder).
- **Ergebnis:** pve **und** macmini erreichen je 100 % der Live-Origins; NUR NAS ist für seine 5 eigenen macvlan-Dienste blind. Darum: NAS darf nie bf-nas fahren.
### 10.2 Die 3 Tunnel (config_src=cloudflare, token-managed Ingress)
| Tunnel | ID | Dienste | Connectoren (2/Tunnel) |
|---|---|---|---|
| **bf-nas** (=alter bf-Tunnel, wiederverwendet) | `70d6a4cf-…-91fab4fa7270` | gitea, grafana, pve-mcp, omada, vw, ds-bf, 3k23uow7 (+gateway-dw→404) | **pve + macmini** |
| **bf-pve** (neu) | `f7fdf3a6-…-b0f273794d09` | pve, j44d6tua, ccu, iobroker, z2m25, portainer, hass, ha-mcp | **NAS + macmini** |
| **bf-mm** (neu) | `7a322261-…-8ebce99f5ed1` | n8n, n8n-mcp, gitea-mcp, 82unkpb5 | **pve + NAS** |
Prinzip: **jeder Host-Dienst wird von den Connectoren der ANDEREN Hosts bedient** → Host-Ausfall lässt jeden Tunnel ≥1 Connector = voll HA. Innerhalb eines Tunnels kein Route-Pinning (CF round-robined) — aber beide Connectoren erreichen 100 % → Round-Robin schadet nicht.
### 10.3 Connector-Roster (6 = 2/Host, Docker `cloudflare/cloudflared:latest`, `restart=unless-stopped`)
| Host (Portainer ep) | Container | Tunnel | Netz |
|---|---|---|---|
| pve-LXC (ep2) | `cloudflared-bfnas` (c80a7db) · `cloudflared-bfmm` (faa0960) | bf-nas · bf-mm | host |
| NAS (ep14) | `cloudflared-bfpve` (97312b5) · `cloudflared-bfmm` (963217983) | bf-pve · bf-mm | host |
| macmini (ep20) | `cloudflared-bfnas` (5c5b3ba) · `cloudflared-bfpve` (3339f86) | bf-nas · bf-pve | bridge |
Tokens: nur im Container-Env + jederzeit via `GET /accounts/…/cfd_tunnel/<id>/token` (Bearer `CF_API_TOKEN`). Tunnel-IDs in `mcp/cloudflare/.env` (`CF_BF/PVE/MM_TUNNEL_ID`). **Nicht** als Compose-Stacks angelegt (raw Portainer-API-Container) → bei Neuaufbau: Container mit `TUNNEL_TOKEN=<token>` + `tunnel --no-autoupdate run`.
### 10.4 As-built Verifikation
- Loop-Smoke 19 FQDNs ×5: **0×530**. gitea/omada/vw/ds-bf/pve/portainer/ccu/iobroker/z2m25/n8n/n8n-mcp/82unkpb5 = 200; grafana 302 (Access); pve-mcp 400 (MCP-Handshake); hass 400 / ha-mcp 403 (Access davor, s. Schritt 5); gitea-mcp 404 (App-Pfad).
- HA-Sim: macmini-Host down → bf-nas via pve (4 conns), bf-pve via NAS (4 conns), bf-mm unberührt (8) — alle Dienste weiter 200. Restore → alle 3 Tunnel 8 conns.
### 10.5 Cleanup gemacht
- Tote CNAMEs gelöscht: `pbs`, `nginx-bf`, `hermes`, `hermes-geli`. NAS-cloudflared-Leichen `oc-tzcharlie`/`oc-johnny2` entfernt.
- `gateway-dw` (192.168.178.1, nur via WG) bleibt CNAME→bf-nas = **404** (kein BF-Connector hat die WG-Route). **Offen: klären/entfernen.**
### 10.6 Schritt 5 Access-Strang — TEILWEISE ✅ (2026-07-10)
**✅ `vw`-Leck geschlossen:** vw-App (`1dbc45ca`) hatte 1 Policy = **bypass/everyone (öffentlich)**. Ersetzt durch 2 eigene (engere als die Wildcard!) Policies: `non_identity bf4-home-ip` (`90.146.35.38/32` = Heim ohne Login) + `allow christoph` (email `christoph@emsenhuber.com`, **kein** `login_method:*`). Bypass war eine **reusable** Policy `a8129e37` → nicht via App/Policies-DELETE löschbar, sondern per **App-PUT detacht** (nur die 2 neuen im `policies`-Array). Verifiziert: Heim = 200, kein `everyone` mehr; Account-weiter Sweep = **keine** App mehr öffentlich. Heim-IP `90.146.35.38` = aktuell (== bf4-DNS).
**🔴 NEUER FUND (wichtiger als vw!) — Wildcard `*.emsenhuber.net` (`16aaec78`) zu offen:** Policy `christoph` hat `include: email:christoph OR login_method:github OR login_method:google`. **`login_method:<idp>` als include matcht JEDEN, der sich via GitHub/Google einloggt** — nicht nur christoph. D.h. **jeder GitHub-/Google-User erreicht nach Login alle internen Dienste** (hass, grafana, portainer, pve, gitea, …). Fix = die zwei `login_method`-Includes raus (nur `email:christoph` + ggf. weitere erlaubte Mails + `non_identity bf4` + `claude-mcp`). **NICHT einseitig geändert** (ändert Login-Verhalten überall) → User-Entscheidung. War im Memory schon als „Policy christoph verschlanken" geflaggt.
**⏸️ `hass` 400 / `ha-mcp` — zwei getrennte Layer:**
- **Access-Layer (remote):** HA-Companion-App kann kein interaktives Access-Login → Fix = iPhone in **WARP** enrollen (`Warp Login App` `6c32fe23` `allow:christoph` existiert → christoph darf enrollen). Client-seitig, braucht User am Gerät. Vom Heim-Netz (bf4-IP) ohnehin ohne Login erreichbar.
- **Origin-Layer:** `hass.emsenhuber.net` gibt **vom Heim-Netz** (Access passt via bf4-IP) trotzdem **400** (CF `server:cloudflare`, aber Origin-verursacht) = **HA lehnt den Request ab** — HA-`http:`-Config (`use_x_forwarded_for` + `trusted_proxies` inkl. cloudflared-Range, ggf. Host-Allowlist). **Separates HA-Thema, NICHT Tunnel/Access** — offen.
**gateway-dw** (192.168.178.1, nur via WG) = CNAME→bf-nas = 404 (kein BF-Connector hat WG-Route). Offen: Route bauen oder CNAME entfernen.