Compare commits
22 Commits
425070ce11
...
tp38-oob
| Author | SHA1 | Date | |
|---|---|---|---|
| e87619e89b | |||
| 177ba100eb | |||
| bce40d182d | |||
| 1d86983f63 | |||
| 27effe937e | |||
| 2cf32bde14 | |||
| 1f19a3b4a9 | |||
| 3e727f1b3b | |||
| 037d2bd22c | |||
| 0e6742f1d7 | |||
| b7d82fe300 | |||
| 13a996c6d9 | |||
| 2a21afe74a | |||
| 9fdcab58ad | |||
| 441e97ed84 | |||
| 89eb9dc3ac | |||
| 4e80ffac28 | |||
| 548d73d84a | |||
| 3eb03ae7b4 | |||
| 3a97bbc41c | |||
| 7d237577e1 | |||
| 777c4e0984 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,10 +1,6 @@
|
||||
.DS_Store
|
||||
.secrets
|
||||
|
||||
# Per-Projekt-MCP-Configs: können Tokens/URLs enthalten, projekt-spezifisch, nicht ins Repo
|
||||
.mcp.json
|
||||
|
||||
|
||||
# Python bytecode
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
67
.mcp.json
Normal file
67
.mcp.json
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"home-assistant": {
|
||||
"type": "http",
|
||||
"url": "${MCP_HOME_ASSISTANT_URL}"
|
||||
},
|
||||
"mikromcp": {
|
||||
"type": "stdio",
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"mikromcp",
|
||||
"serve"
|
||||
],
|
||||
"env": {
|
||||
"MIKROMCP_CONFIG_PATH": "/Users/christophemsenhuber/dev/bf-infra/mcp/mikromcp/config/routers.yaml",
|
||||
"MIKROMCP_DEFAULT_ROUTER": "ap1",
|
||||
"ROUTER_AP1_USER": "admin",
|
||||
"ROUTER_AP1_PASS": "${MCP_MIKROMCP_ROUTER_AP1_PASS}",
|
||||
"ROUTER_AP2_USER": "admin",
|
||||
"ROUTER_AP2_PASS": "${MCP_MIKROMCP_ROUTER_AP2_PASS}",
|
||||
"CRS326_CORE_USER": "admin",
|
||||
"CRS326_CORE_PASS": "${MCP_MIKROMCP_CRS326_CORE_PASS}",
|
||||
"CRS326_BRANCH_USER": "admin",
|
||||
"CRS326_BRANCH_PASS": "${MCP_MIKROMCP_CRS326_BRANCH_PASS}",
|
||||
"ROUTER_AP3_USER": "admin",
|
||||
"ROUTER_AP3_PASS": "${MCP_MIKROMCP_ROUTER_AP3_PASS}"
|
||||
}
|
||||
},
|
||||
"hostinger-api": {
|
||||
"alwaysLoad": true,
|
||||
"type": "stdio",
|
||||
"command": "hostinger-api-mcp",
|
||||
"args": [],
|
||||
"env": {
|
||||
"HOSTINGER_API_TOKEN": "${MCP_HOSTINGER_API_TOKEN}"
|
||||
}
|
||||
},
|
||||
"cloudflare": {
|
||||
"alwaysLoad": true,
|
||||
"type": "http",
|
||||
"url": "https://mcp.cloudflare.com/mcp"
|
||||
},
|
||||
"ollama": {
|
||||
"type": "stdio",
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"ollama-mcp"
|
||||
],
|
||||
"env": {
|
||||
"OLLAMA_HOST": "http://127.0.0.1:11434"
|
||||
}
|
||||
},
|
||||
"pve-mcp": {
|
||||
"type": "http",
|
||||
"url": "http://10.40.20.173:3000/"
|
||||
},
|
||||
"n8n-mcp": {
|
||||
"type": "http",
|
||||
"url": "http://10.40.20.167:3001/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Bearer ${N8N_MCP_BEARER}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
CLAUDE.md
16
CLAUDE.md
@@ -20,6 +20,12 @@ DNS/DHCP-Ablösung, WLAN via **CAPsMAN auf dem Core** (TP28, 2026-08-17 — der
|
||||
am 09-01 zurueckgebaut; Hebel 2–4 entfallen, **kein Geraete-Write** (Soll stand: `ft=yes ft-over-ds=yes`,
|
||||
**Compliance 140/140**). **Am 2026-09-04 hat Christoph `ft=no` auf `sec-main` als Dauerzustand
|
||||
entschieden** (Hebel 2 doch gezogen: Template + bf-golden-config + Nautobot-Sync, `wifi-security` gruen).
|
||||
⚠️ **Rueckgenommen am 2026-09-14 (Terrasse-In-situ-Session): `ft=yes ft-over-ds=yes` zurueck** — mit
|
||||
`ft=no` war jeder Roam eine Voll-Reassoziation, darin starben 2 Anrufe; Rueckkehrstand = Fund-E-Known-Good
|
||||
von 09-02 (ruhig auf 7.24.1). Weg: Template + `push-gc-template.py` + `gc-configplan.py
|
||||
--refresh-compliance` + `gc-manual-plan.py --deploy` (Plan `b1135f3e`, Completed) → **140/140, 0 Drifts**;
|
||||
CAP-Abnahme: **keine** Inline-Overrides auf ap1/ap2/ap3. Commands:
|
||||
`docs/transaktionen/TP25-ft-yes-secmain.commands.rsc`, s. Handoff 2026-09-14.
|
||||
🔴 **Nachtrag 09-04: `ft=no` war NICHT uniform.** ap3 trug einen Werks-Inline `security.ft=yes` auf
|
||||
`wifi1/wifi2` (Bring-up unset `!ft-over-ds`, aber nicht `!ft`; Abnahme zählt nur benannte
|
||||
security-Objekte → Inline-Wert unsichtbar). Gemischtes FT-ESS → Strong-Signal-Abbrüche (−43/−45 dBm)
|
||||
@@ -98,11 +104,11 @@ GW je VLAN = `.1` (crs326-core L3) · Mgmt VLAN99: core `.99.1`, branch `.99.2`,
|
||||
|---|---|---|
|
||||
| ~~ALLNET Core-Switch (sw1)~~ | — | ❌ **außer Betrieb (2026-08-08)** — durch `crs326-core` (L3-Router + Core-Switch, Technik UG) ersetzt; physisch abgelöst. (Telnet-Runner `switch/` = nur noch historisch.) |
|
||||
| ~~Omada Access-Switch (sw2)~~ | — | ❌ **abgebaut 2026-07-23** (TP15 Branch-Tausch) — durch `crs326-branch` in Technik OG ersetzt, physisch entfernt |
|
||||
| **crs326-branch** (CRS326, Technik OG) | **10.40.99.2** (VLAN99) · Bootstrap Rev4 2026-08-08 | RouterOS **7.24.1** · `admin`/`~/.secrets` (`CRS326_BRANCH_*`) · REST `http://10.40.99.2/rest` · MikroMCP `crs326-branch` ✅ **live** (2026-08-16 verifiziert) · **TP15 ✅: ersetzt sw2** (L2-Switch), volle Portbelegung (ether1 Uplink-Trunk, 2/8 NAS, 3 Drucker, 4 Dock, 5/6 Sonos, 7 macmini, 24 ap2) · sw-id RGZJ-UK0T, MAC 04:F4:1C:B4:15:58 |
|
||||
| **crs326-branch** (CRS326, Technik OG) | **10.40.99.2** (VLAN99) · Bootstrap Rev4 2026-08-08 | RouterOS **7.24.1** · `admin`/`~/.secrets` (`CRS326_BRANCH_*`) · REST `http://10.40.99.2/rest` · MikroMCP `crs326-branch` ✅ **live** (2026-08-16 verifiziert) · **TP15 ✅: ersetzt sw2** (L2-Switch), volle Portbelegung (ether1 Uplink-Trunk, 2/8 NAS, 3 Drucker, 4 Dock, 5/6 Sonos, 7 macmini, 24 ap3) · sw-id RGZJ-UK0T, MAC 04:F4:1C:B4:15:58 |
|
||||
| **crs326-core** (CRS326, Technik UG) | **10.40.99.1** (VLAN99-SVI = L3-GW; same-subnet-Fallback `10.40.10.1`) · Identity `crs326-core` | RouterOS **7.24.1** · `admin`/`~/.secrets` (`CRS326_CORE_*`) · MikroMCP routerId `crs326-core` ✅ **live** (2026-08-16 verifiziert) · **TP15/TP21.1 ✅ 2026-08-08: PRODUKTIVER L3-Router** (ersetzt ap1) — Routing/DHCP (7 Server + 54 Leases)/DNS (**DoH zum CF-Gateway mit `verify-doh-cert=yes`**, TP23 Stufe 1 ✅ 2026-08-18; `servers=1.1.1.1` nur noch Bootstrap) · **NTP-Server für den Standort**/NAT/WG-Hub (fm+dw live); WAN `vlan100`=Liwest `90.146.33.177` · sw-id 4W04-URHT, MAC 04:F4:1C:B4:17:76 |
|
||||
| hAP ax² #1 (ap1) | **10.40.99.11** (VLAN99) · Identity `ap1` | RouterOS **7.24.1** · `admin`/`~/.secrets` (`ROUTER_AP1_*`) · REST `http://10.40.99.11/rest` · MikroMCP `ap1` ✅ live · **TP28 ✅ 2026-08-17: reiner CAP** (Manager = `crs326-core`) · 🔴 **FUNKSTILL seit 2026-08-30**: keine Provisioning-Regel am Manager, weil ap3 daneben steht und denselben Kanal 5180 fährt. Gerät bleibt erreichbar. Beim Umzug ans Sideboard → `5260/Ce` (Band B, DFS) und Uplink auf `core ether3` — Uplink `ether1` (PoE-Port, `poe-out=off`) an crs326-core `ether15`; SSIDs/Kanäle kommen vom Manager, ch36/ch1 · MAC D0:EA:11:4D:40:E0 · Config-Referenz `routeros/.secrets/ap1-prov-base.rsc` |
|
||||
| hAP ax² #2 (ap2) | **10.40.99.12** (VLAN99) · Identity `ap2` | RouterOS **7.24.1** · `admin`/`~/.secrets` (`ROUTER_AP2_*`) · REST `http://10.40.99.12/rest` · MikroMCP `ap2` · **TP28 ✅ 2026-08-17: reiner CAP** — Uplink `ether1` (PoE) an crs326-branch `ether24`; ch44/ch11 (TP25: ch149 war unter ETSI leistungsbegrenzt) · MAC D0:EA:11:4D:40:3A · Config `routeros/.secrets/ap2-prov-base.rsc` |
|
||||
| **cAP ax (ap3)** | **10.40.99.13** (VLAN99) · Identity `ap3` | ✅ **LIVE seit 2026-08-30** (TP28-Nachtrag) · `cAPGi-5HaxD2HaxD`, RouterOS **7.24.1** + RouterBOOT 7.24.1 (**seit 2026-08-31 ist die ganze Flotte auf 7.24.1**, TP27-Angleichung erledigt) · reiner CAP, Manager `crs326-core` · Uplink `ether1` → **core `ether21`** (Trunk) · Kanäle **`5180/ax/Ce/I`** (5 GHz) + **`2437/ax`** (ch6) nach TP25-Plan · 🔴 **nur 2 Ethernet-Ports** (`ether1` PoE-in, `ether2` PoE-out, **kein** Bridge-Port) → `ap.extra_ports=[]` · `device-mode=basic` (scheduler/fetch/romon **erlaubt**, anders als ap1/ap2) · Dateien `routeros/tp28-ap3-phase{1,2}-*.rsc` + `-service-accounts.rsc` + `-werksreste.rsc` |
|
||||
| hAP ax² #1 (ap1) | **10.40.99.11** (VLAN99) · Identity `ap1` | RouterOS **7.24.1** · `admin`/`~/.secrets` (`ROUTER_AP1_*`) · REST `http://10.40.99.11/rest` · MikroMCP `ap1` ✅ live · **TP28 ✅ 2026-08-17: reiner CAP** (Manager = `crs326-core`) · ✅ **aktiv am Sideboard** (Wohnzimmer; Uplink `ether1` → core `ether3`, PoE-Port `poe-out=off`) — Kanäle `5260/Ce` (Band B, DFS, Fallback 5280) + `2412`/ch1, vom Manager · MAC D0:EA:11:4D:40:E0 · Config-Referenz `routeros/.secrets/ap1-prov-base.rsc` |
|
||||
| hAP ax² #2 (ap2) | **10.40.99.12** (VLAN99) · Identity `ap2` | RouterOS **7.24.1** · `admin`/`~/.secrets` (`ROUTER_AP2_*`) · REST `http://10.40.99.12/rest` · MikroMCP `ap2` · **TP28 ✅ 2026-08-17: reiner CAP** — **Technik UG**, Uplink `ether1` (PoE) an core `ether21`; Kanäle `5300/Ce` (Band B, DFS, Fallback 5320) + `2462`/ch11 · MAC D0:EA:11:4D:40:39 (ether1; Bridge/Mgmt `:3A`) · Config `routeros/.secrets/ap2-prov-base.rsc` |
|
||||
| **cAP ax (ap3)** | **10.40.99.13** (VLAN99) · Identity `ap3` | ✅ **LIVE seit 2026-08-30** (TP28-Nachtrag) · `cAPGi-5HaxD2HaxD`, RouterOS **7.24.1** + RouterBOOT 7.24.1 (**seit 2026-08-31 ist die ganze Flotte auf 7.24.1**, TP27-Angleichung erledigt) · reiner CAP, Manager `crs326-core` · **Technik OG**, Uplink `ether1` → **branch `ether24`** (Trunk) · Kanäle **`5180/ax`** (Band A, non-DFS, 5 GHz) + **`2437`** (ch6) nach TP25-Plan · 🔴 **nur 2 Ethernet-Ports** (`ether1` PoE-in, `ether2` PoE-out, **kein** Bridge-Port) → `ap.extra_ports=[]` · `device-mode=basic` (scheduler/fetch/romon **erlaubt**, anders als ap1/ap2) · Dateien `routeros/tp28-ap3-phase{1,2}-*.rsc` + `-service-accounts.rsc` + `-werksreste.rsc` |
|
||||
| **🔑 Einheitliches Admin-PW (2026-08-08)** | alle 4 MikroTik (core/branch/ap1/ap2) | user `admin`, gleiches PW (`~/.secrets/credentials.env` → `ROUTER_*_PASS`/`CRS326_*_PASS`; „Überlebensversicherung", User-Vorgabe). Werks-Defaults ap1/ap2 damit obsolet. |
|
||||
| NAS (nas-bf, DS923) | 10.40.20.10 | SSH `adm.christoph@10.40.20.10` (kein PW nötig) · Docker (Portainer endpointId=14) |
|
||||
| platform-pg (LXC 105, pve) | 10.40.20.20 | SSH via pve (`pct exec 105 --`) · **TP20 ✅ 2026-07-16: PG16, DB `nautobot`, Creds `postgres/.secrets`** |
|
||||
@@ -276,7 +282,7 @@ GW je VLAN = `.1` (crs326-core L3) · Mgmt VLAN99: core `.99.1`, branch `.99.2`,
|
||||
danach die Ports gegen vorher vergleichen**, sonst verliert man still einen Dienst.
|
||||
- **VLAN20-Docker-Hosts: Host-DNS nach dem Umzug prüfen (2026-07-10, TP14.2a):** NAS + pve-LXC zeigten `/etc/resolv.conf` noch auf totes `.41.254` → `docker pull` ghcr scheitert (`EAI_AGAIN`, aber Egress ok!). Fix = `.20.1`: LXC `pct set 400 --nameserver 10.40.20.1`; **Synology-Falle: DSM-„Allgemein"-DNS ≠ was `dockerd` liest** — Interface zieht DNS per DHCP → Fix an der *Netzwerkschnittstelle* „DNS manuell". Laufende Container frieren den `127.0.0.11`-Upstream zum Erstellzeitpunkt ein (Recreate nötig). Merkregel: `docker-pull-hängt` + `dns.lookup EAI_AGAIN` aber `TCP zu ghcr-IP:443 ok` = toter Resolver, nicht Egress.
|
||||
- 📜 **~~ALLNET VLAN-DB (TP1)~~ — historisch.** Die VLAN-Semantik gilt weiter (**40=MEDIA, 50=UNTRUSTED**), die Portangaben (GE1/GE2/GE8) beziehen sich auf ein ausgebautes Gerät.
|
||||
- **ap2 hängt an `crs326-branch ether24`** (Trunk, native VLAN1 + tagged 10-99); **branch-Uplink `ether1` → `crs326-core ether8`** (korrigiert 2026-08-16 — die frühere Angabe „→ sw1 GE8" stammt aus der Zeit vor dem Core-Tausch; MAC-hart belegt in TP22 Schritt 5).
|
||||
- **ap3 hängt an `crs326-branch ether24`** (Trunk, native VLAN1 + tagged 10-99); **branch-Uplink `ether1` → `crs326-core ether8`** (korrigiert 2026-08-16 — die frühere Angabe „→ sw1 GE8" stammt aus der Zeit vor dem Core-Tausch; MAC-hart belegt in TP22 Schritt 5). ap2 hängt seit dem TP25-Tausch (2026-09-15) an `core ether21` (Technik UG), ap1 an `core ether3` (Sideboard).
|
||||
- **Mesh = NEIN** (beide APs haben wired Trunk-Uplink → Loop-Risiko).
|
||||
- **Beide APs = CAPs, Manager ist `crs326-core` (TP28 ✅ 2026-08-17).** Der Entscheid „kein CAPsMAN" von 2026-07-22 ist **revidiert**: er galt der Konstellation ap1=Manager+AP, in der ein Manager seine eigenen Radios nicht provisionieren kann — mit dem Core als Manager sind beide APs symmetrisch. Der Core braucht dafür **kein** `wifi-qcom`, `capsman` steckt im Basispaket.
|
||||
- 🔴 **`/interface wifi scan` geht am CAP NICHT — nur am Manager** (Fund 2026-08-23). Das Gerät
|
||||
|
||||
@@ -71,7 +71,7 @@ dns:
|
||||
ipset_file: ""
|
||||
bootstrap_prefer_ipv6: false
|
||||
upstream_timeout: 10s
|
||||
private_networks: []
|
||||
private_<redacted>: []
|
||||
use_private_ptr_resolvers: true
|
||||
local_ptr_upstreams: []
|
||||
use_dns64: false
|
||||
|
||||
@@ -82,7 +82,7 @@ terpene.teilzeitladen.xyz {
|
||||
"type": "http",
|
||||
"url": "https://n8n-mcp.emsenhuber.net/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Bearer 47a34f5589388d37d8b7503abac07b930df264c469ef0674aaeeea9b71dde847"
|
||||
"Authorization": "Bearer <redacted>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
111
docs/handoff-20260914-tp25-ap2-insitu-terrassse.md
Normal file
111
docs/handoff-20260914-tp25-ap2-insitu-terrassse.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# Handoff 2026-09-14 — TP25: ap2-In-situ-Messung (Terrasse), Hebel-A-Machbarkeitsprüfung
|
||||
|
||||
**Anlass:** Christoph beobachtete 19:18 auf der Terrasse springende WLAN-Balken (1→2→3 binnen
|
||||
Sekunden) und zwei Anruf-Aussetzer; danach Umstellung des Telefons auf 5G-Zellular. Verdacht:
|
||||
Das Telefon probe die APs ab und falle dabei hinaus.
|
||||
|
||||
**Beteiligte:** iPhone `F2:62:4C:E1:AF:09` (das bekannte Fund-E-Gerät), Manager `crs326-core`.
|
||||
Alle Reads am Manager; **kein einziger Geräte-Write** in dieser Session.
|
||||
|
||||
## cap-wifi-Karte (verifiziert live 19:22, vor jeder Auswertung gelesen)
|
||||
|
||||
`cap-wifi1` = ap2 5G (5300/ax/Ce/DI, tx-power 18) · `cap-wifi6` = ap2 2,4G (2462, tx-power 15) ·
|
||||
`cap-wifi2` = ap3 5G (5180) · `cap-wifi4` = ap3 2,4G · `cap-wifi3`/`cap-wifi5` = ap1 (5G 5280/2,4G).
|
||||
⚠️ Das CLAUDE.md sagt „ap1 FUNKSTILL seit 08-30" — **überholt**: seit dem 09-04-Kanalplan-Commit
|
||||
hat ap1 wieder eine Provisioning-Zeile und dient live (heute 16:51:53 sogar ein Radar-Event auf
|
||||
5280 mit sauberem Kanalwechsel auf 5260/5280-Liste). Doku-Drift, hier vermerkt.
|
||||
|
||||
## Befund 1 — das Flapping ist echt und überwiegend band-intern an ap2
|
||||
|
||||
Kollektor-Log 18:53–19:18: **~30 Roams**, fast alle `cap-wifi1 ↔ cap-wifi6` = **ap2 5G ↔ ap2 2,4G**
|
||||
(derselbe AP), Feldstärke −68…−81 dBm. Drei echte Abwürfe `disconnected, not responding`
|
||||
(19:01:29, 19:12:10, 19:47:51 — der letzte tötete den Anruf). Ein Ausflug zu ap1-5G (19:35:45,
|
||||
**−64**) und ap3 (−78…−82).
|
||||
|
||||
## Befund 2 — In-situ vor ap2: Hardware-Verdacht WIDERLEGT
|
||||
|
||||
Christoph stellte sich 1–2 m vor ap2. Registration-Table live (3 Stichproben + Log):
|
||||
|
||||
| Position | Interface | Signal | Verhalten |
|
||||
|---|---|---|---|
|
||||
| 1–2 m vor ap2 | cap-wifi1 (5G) | **−49…−51** | **>2 min stabil, 0 Roams** |
|
||||
| Rückweg (Weg) | cap-wifi1 → cap-wifi6 | −76…−78 | 2 Roams binnen 26 s |
|
||||
| Terrassenplatz | cap-wifi6 (2,4G) | **−65…−73** | 36 s im 1-s-Takt, 0 Roams, ±4 dB |
|
||||
|
||||
⇒ Der offene TP25-Unterpunkt „**ap2 unterperformt (2 m/−80, 23:02-Befund)**" ist **in situ
|
||||
widerlegt**: ap2 sendet auf 2 m mit −49…−51 dBm und bleibt dort stabil. Der 23:02-Befund
|
||||
reproduziert sich nicht — plausibel, weil seitdem der 09-04-Kanalplan (5220→5300/5320,
|
||||
Band-B-Liste) committed ist; alternativ war die damalige Position/Attribution anders.
|
||||
**ap2 RF/Antenne/HW: sauber. Kein Hardware-Tausch begründet.**
|
||||
|
||||
## Befund 3 — Ursache-Modell Terrasse: 5-GHz-Zellkante + client-getriebene Band-Aggressivität
|
||||
|
||||
- Terrassenplatz: 5 GHz **−76…−81** (Zellkante), 2,4 GHz **−65…−73** — die ~7 dB sind normale
|
||||
Bandspreizung plus Wand. Link-Budget, kein Defekt.
|
||||
- Das iPhone **bleibt**, sobald ein Band klar gewinnt (am Platz: 2,4 GHz, minutenlang ruhig).
|
||||
Das Thrash passiert ausschließlich in der **Überlappungszone −70…−77**, wo beide Bänder
|
||||
gleichauf liegen und 5 GHz ständig um die iOS-Aufgabeschwelle (~−75) pendelt.
|
||||
- Client-Aggressivität als Second Layer: 19:44:21 stand das Telefon bei **−52 auf ap2-5G** und
|
||||
floh 13 s später auf 2,4 (−77) — dasselbe Muster wie im Archiv-Fund E („Abbruch bei −47").
|
||||
Steering-Objekte `st-main`/`st-guest` haben **keine Schwellen** (nur rrm/wnm) — der AP
|
||||
drängt nichts aktiv per BTM, die Entscheidungen trifft das iPhone.
|
||||
- Mit `ft=no` (Dauerzustand seit 09-04) ist jeder Roam eine Voll-Reassoziation in Sekundenhöhe
|
||||
⇒ genau darin sterben Anrufe.
|
||||
|
||||
## Hebel-A-Machbarkeitsprüfung (Dry-Run, kein Write)
|
||||
|
||||
**Ziel:** 5-GHz-Boden für `dirtyvader-main` (reject unter ~−76), damit das Telefon an der
|
||||
Zellkante sofort endgültig auf 2,4 GHz committet statt zu thrashen.
|
||||
|
||||
Live + MikroTik-Doku verifiziert:
|
||||
- `signal-range` wird **kontinuierlich** geprüft (Grace über `allow-signal-out-of-range`,
|
||||
Default 0s) — der Mechanismus trägt grundsätzlich.
|
||||
- ABER: `/interface/wifi/access-list` hat **kein `band`-Property**. Band-Scoping nur über
|
||||
`interface=` möglich — und die `cap-wifiN`-Namen wechseln bei jedem CAP-Rejoin (Gotcha
|
||||
2026-08-31): die Regel würde stillschweigend auf ein falsches Radio zeigen (im Worst Case
|
||||
ein 2,4-Master ⇒ Lockout-Schatten). Alternativen fallen alle durch:
|
||||
- **Nur SSID scope** (ohne Band): trifft auch 2,4 GHz — Schlafzimmer-Gegenmessung 08-22
|
||||
(−84 dBm am Counter-AP) ⇒ Lockout, exakt das 08-22-Gegenargument.
|
||||
- **Nur MAC scope** (iPhone): trifft beide Bänder — das iPhone saß heute selbst bei −89 auf
|
||||
2,4 GHz (19:01) ⇒ WiFi-Verlust in schwachen Räumen.
|
||||
- **Fazit: Der Band-Boden ist in der aktuellen wifi-qcom-Access-List nicht sauber ausdrückbar.
|
||||
Nicht umgesetzt; Dry-Run-Preview des Kandidaten gefahren, kein Apply.**
|
||||
|
||||
Kandidat (NICHT angewendet, nur als Referenz wie er *heute* aussehen würde):
|
||||
|
||||
```
|
||||
/interface wifi access-list add interface=cap-wifi1 ssid-regexp=dirtyvader-main \
|
||||
signal-range=-120..-76 action=reject comment="TP25-hebel-a-5g-boden"
|
||||
```
|
||||
(× cap-wifi1/2/3 — die drei 5G-Master — bricht bei jedem CAP-Rejoin)
|
||||
|
||||
**Verbleibende Hebel:**
|
||||
1. **`ft=yes` uniform auf `sec-main`** — macht Roams nahtlos ⇒ Anrufe überleben das (verbleibende)
|
||||
Springen. Bewusste Aufweichung der 09-04-Entscheidung (`ft=no`), Fund-E-Ursache (7.24.1) ist
|
||||
längst behoben, FT-Flotte uniform. Ein Config-Weg: Template + Compliance + Transaktion.
|
||||
2. **Deckungsfix (TP25 Variante 3)** — der eigentliche Hebel: ein AP muss an der Terrasse
|
||||
eindeutig stärker sein als alle anderen. Bemerkenswert: ap1-5G erreichte die Terrasse heute
|
||||
mit −64 (besser als ap2-5G mit −78) — ap1 sitzt bereits auf der Band-B-Liste 5260/5280.
|
||||
3. Monitoring: wireless-Logging läuft persistent; das Flapping ist damit künftig rückwirkend
|
||||
diagnostizierbar.
|
||||
|
||||
## Nachweise
|
||||
|
||||
- Live-Log am Manager: 43 + 18 + 8 Zeilen `wireless,info` zu `F2:62:4C:E1:AF:09`, 18:53–19:56.
|
||||
- 1-s-Sampling: zwei 18-Sekunden-Loops (`:for` am Manager, Registration-Table), 20:01:44–20:02:26.
|
||||
- Monitor-Reads: `cap-wifi1` → `5300/ax/Ce/DI tx-power 18`; `cap-wifi6` → `2462/ax tx-power 15`.
|
||||
- Doku-Verifikation Access-List: help.mikrotik.com/docs/display/ROS/Wifi (signal-range kontinuierlich,
|
||||
kein band-Property, first-match-wins, kein impliziter Reject).
|
||||
|
||||
## Offen / nächste Schritte
|
||||
|
||||
1. Entscheidung Christoph: `ft=yes` ja/nein (Hebel 1 oben) — ich lege dazu auf Go den
|
||||
GC-ConfigPlan als Dry-Run vor.
|
||||
2. Deckungsfix-Terminierung (Variante 3 / ap1-Endausbau) — TP25 bleibt offen.
|
||||
3. CLAUDE.md-Drift „ap1 FUNKSTILL" beim nächsten CLAUDE.md-Edit korrigieren (nur Vermerk hier,
|
||||
kein stiller Fix).
|
||||
4. Gitea-TP25-Issue **#17** hat einen Kommentar mit diesem Befund erhalten.
|
||||
5. 🔴 **Sicherheitsvorfall dieser Session:** durch einen Env-Parse-Fehler stand der
|
||||
`GITEA_ACCESS_TOKEN` in einer URL im Traceback — **Token ist als kompromittiert zu
|
||||
betrachten und zu rotieren** (neues Token erzeugen, `~/.hermes/.env` aktualisieren, altes
|
||||
widerrufen). Siehe Merkregel-Klasse „Werte nie suchen, um sie zu sehen".
|
||||
@@ -0,0 +1,72 @@
|
||||
# Handoff 2026-09-15 — TP25: Steering-Threshold 5G deployed, Terrasse verifiziert, MacBook-Klebrigkeit „wird nicht umgesetzt"
|
||||
|
||||
**Anlass:** Folgesession zum TP25-Handoff „zuordnung-und-redundanz" ([[handoff-20260915-tp25-zuordnung-und-redundanz]]). Ziele: (1) Doku-Drift schließen, (2) Roaming-Threshold für die Terrasse (5G bricht früher zur 2,4G ab), (3) Terrasse-Nachmessung nach dem Deploy.
|
||||
|
||||
## 1. Steering-Threshold 5G — DEPLOYED, 140/140
|
||||
|
||||
**Problem:** Am Rundgang 09-15 saß der Terrasse-Client auf der **−80/5G-Kante** (genau der Default
|
||||
`transition-threshold`); auf 2,4 GHz wäre das nicht passiert.
|
||||
|
||||
**Umsetzung (nur 5G):** neues Steering-Profil `st-main-5g` mit `transition-threshold=-72`
|
||||
(statt Default −80) und `transition-threshold-time=5s` (statt 10s). Die drei 5G-Configs
|
||||
(`cfg-main-5g-ap1/ap2/ap3`) zeigen darauf; die drei 2G-Configs bleiben auf `st-main` (unset −80),
|
||||
weil 2,4 GHz draußen (Terrasse/außerhalb) Reichweite behalten soll. **8 dB Abstand = kleine Hysterese.**
|
||||
|
||||
Weg: Template-Edit (`nautobot/mikrotik_routeros.j2`) → `push-gc-template.py` (GC-Commits `6a4b504f`,
|
||||
`242ed108`) → manueller Plan (`gc-manual-plan.py`, Plan `cc8340a8`, Completed) → Refresh:
|
||||
**140/140, 0 Drifts.** Commands-File:
|
||||
[`docs/transaktionen/TP25-steering-5g-threshold.commands.rsc`](transaktionen/TP25-steering-5g-threshold.commands.rsc).
|
||||
|
||||
## 2. Gotcha: Parameter-Reihenfolge im Template
|
||||
|
||||
Nach dem ersten Push meldete Compliance **139/140** mit einem `wifi-steering`-Drift: `extra`/`missing`
|
||||
derselben Zeile, aber mit unterschiedlicher Feld-Reihenfolge. **RouterOS exportiert `transition-threshold`
|
||||
vor `wnm` (alphabetisch)** — mein Template hatte `wnm` davor. Fix = Template-Zeile auf die Export-Reihenfolge
|
||||
gebracht (`… rrm=yes transition-threshold=-72 transition-threshold-time=5s wnm=yes`). Kein Re-Deploy nötig
|
||||
(das Gerät war schon korrekt, nur das Template war es nicht). **Merkregel: bei neuen Parametern im
|
||||
`/interface wifi steering add` die RouterOS-Export-Reihenfolge (alphabetisch) verwenden, sonst Drift ohne
|
||||
Fehlfunktion.**
|
||||
|
||||
## 3. Terrasse-Nachmessung — Threshold wirkt am iPhone, nicht am MacBook
|
||||
|
||||
Zwei Apple-Geräte 20 cm auseinander auf der Terrasse, beide auf `dirtyvader-main`, beide physisch
|
||||
rein/raus bewegt (A/B):
|
||||
|
||||
| Gerät | Band | Signal | Roam-Verhalten |
|
||||
|---|---|---|---|
|
||||
| iPhone `F2:62:4C:E1:AF:09` | **2,4 GHz** | −55…−66 | ✅ roamt sauber (rein→5G, raus→2,4G) |
|
||||
| MacBook `56:71:6C:22:E6:A9` | **5 GHz** | −73…−75 | ❌ kein Roam (uptime 1h15m unverändert) |
|
||||
|
||||
**Befund:** gleiche Bewegung, gegensätzliches Verhalten. iOS folgt dem Band-Wechsel; **macOS hält 5 GHz
|
||||
klebrig fest** und ignoriert die 802.11v-Transition-Request — selbst unter der −72-Schwelle und beim
|
||||
physischen Umhertragen. Christoph: das MacBook hatte an diesem Ort nie Probleme (−73/5G reicht ihm).
|
||||
|
||||
## 4. Entscheidung: MacBook-Klebrigkeit = ❌ WIRD NICHT UMGESETZT
|
||||
|
||||
Der einzige Hebel dagegen wäre `transition-time=immediate` (deauth-Erzwingung nach der
|
||||
Transition-Request statt bloßem Vorschlag) — ein schärferer Eingriff mit Abbruch-Risiko für aktive
|
||||
Sitzungen. **Christoph-Entscheid 2026-09-15: nicht umsetzen.** Kein Handlungsbedarf, da das MacBook
|
||||
dort funktioniert. Nur dokumentiert, falls es später doch wieder aufkommt.
|
||||
|
||||
## 5. Doku-Drift geschlossen (diese Session)
|
||||
|
||||
- **CLAUDE.md:** ap1 „FUNKSTILL"→aktiv am Sideboard (`core ether3`), ap2→Technik UG (`core ether21`,
|
||||
ether1-MAC `:39`), ap3→Technik OG (`branch ether24`), Branch-Portliste `24 ap3`, Gotcha-Zeile
|
||||
ap2/ap3-Uplink. Kanäle mitkorrigiert (ap1 `5260/Ce`, ap2 `5300/Ce`).
|
||||
- **teilprojekte.md:** neuer Stand-Block 2026-09-15 (definitive Zuordnung + Tausch-Befund ap2↔ap3).
|
||||
- **Nautobot Location** (war `None`): ap1→`Wohnzimmer Sideboard`, ap2→`Technik UG`, ap3→`Technik OG`.
|
||||
|
||||
## 6. Handoff-Punkte (aus dem Vorgänger) — aufgelöst
|
||||
|
||||
1. **ap1 behalten/abbauen** → **behalten** (Christoph). APs bleiben an ihren jetzigen Orten.
|
||||
2. **Tausch korrigieren** (cAP ax → Sideboard) → **verworfen**; aktueller Zustand bleibt.
|
||||
3. **Drei-Räume-Schatten** nachmessen → **verworfen**; Signal war beim letzten Rundgang gut.
|
||||
4. **Doku-Drift** → ✅ geschlossen (s. §5).
|
||||
|
||||
## Übergabeprompt (nächste Session)
|
||||
|
||||
> TP25: Steering-Threshold 5G deployed (st-main-5g, −72/5s, 140/140), Terrasse am iPhone verifiziert
|
||||
> (2,4G statt 5G/−80). MacBook-Klebrigkeit auf 5G dokumentiert und per Christoph-Entscheid
|
||||
> „wird nicht umgesetzt" (transition-time=immediate). Doku-Drift geschlossen, Handoff-Punkte aufgelöst
|
||||
> (ap1 bleibt, APs bleiben, Drei-Räume verworfen). Siehe
|
||||
> [[handoff-20260915-tp25-steering-threshold-und-terrasse]].
|
||||
105
docs/handoff-20260915-tp25-tausch-und-zuordnung.md
Normal file
105
docs/handoff-20260915-tp25-tausch-und-zuordnung.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# Handoff 2026-09-15 — TP25: AP-Zuordnung geklärt, Messrunde (Vorher), Tausch ap1↔ap3 begonnen
|
||||
|
||||
**Anlass:** Christoph wieder on site in Linz. Zurückgestellter Job = TP25 Deckungsfix Variante 3
|
||||
(„Deckenstrahler an den guten Platz, hAP in den Schatten"). Session lief als große Messrunde
|
||||
(Vorher) + physischer Tausch ap1↔ap3. **Tausch ist physisch angefangen, aber der Netzzustand ist
|
||||
zum Sitzungsende unklar — ap2 ist down.**
|
||||
|
||||
## 🔑 AP-Zuordnung — EINDEUTIG per physischem Test geklärt
|
||||
|
||||
Die Session lief lange mit vertauschter Zuordnung (auch Christoph hat sie zwischenzeitlich falsch
|
||||
„korrigiert"). Der **Kabel-Test** hat sie eindeutig festgelegt:
|
||||
|
||||
| Gerät | IP | Position | Uplink |
|
||||
|---|---|---|---|
|
||||
| **ap1** | 10.40.99.11 | **Sideboard / Wohnzimmer** | core `ether3` |
|
||||
| **ap2** | 10.40.99.12 | **Technik OG** | core `ether8` → branch `ether24` |
|
||||
| **ap3** | 10.40.99.13 | Technik UG | core `ether21` |
|
||||
|
||||
**Beweis:** Christoph zog das Kabel in Technik OG → `cap-wifi1`/`cap-wifi6` (= ap2,
|
||||
Radio-MAC `D0:EA:11:4D:40:3E/3F`) verschwanden aus der cap-wifi-Karte, ap1/ap3 blieben.
|
||||
⇒ ap2 = Technik OG, ap1 = Sideboard. Die ARP zeigt ap2 noch ~30 s „reachable" (Cache), die
|
||||
CAPWAP-Karte ist die Wahrheit.
|
||||
|
||||
⚠️ **CLAUDE.md-Drift:** die Hardware-Tabelle sagt für ap1 „core ether15" — überholt, ap1 hängt an
|
||||
`ether3`. Und die Doku-Aussage „ap1 FUNKSTILL seit 08-30" ist überholt (ap1 dient live).
|
||||
|
||||
## Messrunde (Vorher) — Methode
|
||||
|
||||
iPhone `F2:62:4C:E1:AF:09` (Fund-E-Gerät) wurde per **Access-List-Reject** gezielt auf je einen AP
|
||||
gelenkt (die anderen zwei APs ablehnen), dann Registration-Table am Manager gelesen. Reject-Regeln
|
||||
nur auf `ssid-regexp=dirtyvader-main`, am Ende immer `remove [find where comment~"TP25-messung"]`.
|
||||
|
||||
⚠️ **Zwei Methodik-Gotchas (neu):**
|
||||
1. `interface=` in der Access-List nimmt **nur EINEN Wert** (keine Komma-Liste) — pro AP zwei
|
||||
Regeln (5G- + 2,4G-Radio). Eine Komma-Liste wirft `input does not match any value of interface`.
|
||||
2. **MAC-Tippfehler** `F2:62:4C:E1:41:AF:09` (ein „41" zu viel) ist mir **zweimal** passiert und
|
||||
hat stille Fehl-Reads (leere Registration-Table) erzeugt. Korrekt ist `F2:62:4C:E1:AF:09`.
|
||||
|
||||
**Methodischer Vorbehalt:** die wiederholten Rejects + Disconnects drosseln die iOS-Wiederverbindung.
|
||||
Ein „✗ tot"-Wert direkt nach mehreren Disconnects kann teils Artefakt sein — Christoph hat den
|
||||
ap1-tot-Befund auf der Terrasse aber selbst per manuellen Verbindungsversuchen bestätigt.
|
||||
|
||||
## Messwerte (Vorher)
|
||||
|
||||
**Innenräume** (Durchschaltung, je Station alle 3 APs):
|
||||
|
||||
| Ort | ap1 (Sideboard) | ap2 (OG) | ap3 (UG) |
|
||||
|---|---|---|---|
|
||||
| Küche | 5G −52 | — | — |
|
||||
| Schlafzimmer | 5G −52 | ✗ tot | 2,4G −57 / 5G −73 |
|
||||
| Bad | 2,4G −71…−76 | ✗ tot | 5G −73 / 2,4G −72 |
|
||||
| Klo | ✗ tot | 2,4G −75…−81 | 5G −69 |
|
||||
| Technik OG | (−52 erst, dann ✗)† | 5G −47…−57 | 5G −68…−71 |
|
||||
|
||||
**Terrasse** (3 Runden je AP: sitzend → Rundgang entlang der Mauern → wieder sitzen):
|
||||
|
||||
| | ap1 (Sideboard) | ap2 (OG) | ap3 (UG) |
|
||||
|---|---|---|---|
|
||||
| Sitzend | ✗ tot | 5G −78…−85 / 2,4G −67 (Thrash) | ✗ tot |
|
||||
| Rundgang | ✗ überall | 2,4G −63…−74 / 5G −73…−75 | ✗ (nur 1 Mauerdurchlass −70…−82) |
|
||||
|
||||
† Vorbehalt s.o.
|
||||
|
||||
**Kernbefunde:**
|
||||
1. **Die Terrasse wird ausschließlich von ap2 (Technik OG) bedient — marginal** (Band-Thrash
|
||||
5G −78…−85 / 2,4G −67). ap1 (Sideboard) erreicht die Terrasse **nicht**, ap3 nur an einem
|
||||
Mauerdurchlass kurz (−70…−82). Die Prämisse „Sideboard-AP deckt die Terrasse" ist **widerlegt**.
|
||||
2. **ap1 (Sideboard) ist der Innenraum-König:** Küche −52, Schlafzimmer −52, Bad −71…−76.
|
||||
3. **ap3 (cAP ax, UG) hält als einziger beide Geschoße** (UG: Schlafzimmer/Bad/Klo −69…−73,
|
||||
OG: Technik OG −68…−71 über die Decke).
|
||||
|
||||
## Tausch ap1↔ap3 — Status UNKLAR (Sitzungsende)
|
||||
|
||||
Christoph hat ap1 und ap3 physisch getauscht: **ap3 (cAP ax) liegt jetzt „am Kasten auf
|
||||
ap1-Position"**, bewusst „oben/unten ausgerichtet wie Deckenmontage" (Abstrahlwinkel). Ports/VLAN
|
||||
sollten laut Vorgabe gleich bleiben.
|
||||
|
||||
**Live-Befund direkt nach dem Tausch (Vorsicht, Zustand kann sich noch setzen):**
|
||||
- ap2 = **down** (10.40.99.12 ARP `incomplete`, fehlt in cap-wifi-Karte). Vermutlich Kabel beim
|
||||
Tausch abgezogen.
|
||||
- ap1 = reachable, noch an `ether3` (Sideboard).
|
||||
- ap3 = reachable, aber Bridge-Host zeigt es an **`ether8` (branch)**, nicht an `ether21`.
|
||||
- `ether21` ist **leer**.
|
||||
|
||||
⇒ Der Tausch ist im Netz noch nicht so angekommen, wie physisch beabsichtigt. **Bevor irgendetwas
|
||||
weitergemessen wird: ap2 wieder einstecken und die tatsächliche Verkabelung (welches Kabel an
|
||||
welchem Gerät) klären.**
|
||||
|
||||
## Offen / nächste Schritte
|
||||
|
||||
1. **ap2 (Technik OG) wieder versorgen** — Kabel prüfen, ARP `10.40.99.12` wieder `reachable`.
|
||||
2. **Verkabelung nach dem Tausch verifizieren:** Bridge-Host-Tabelle (`mac-address~"D0:EA:11"`)
|
||||
gegen Soll (ap1=`ether3`, ap2=`ether8`/branch, ap3=`ether21`) stellen. ap3 hängt aktuell an
|
||||
`ether8` — klären, ob das Absicht ist oder Verwechslung.
|
||||
3. **Nachher-Messung** derselben Stationen (Terrasse + Innenräume), erst wenn 1+2 sauber sind.
|
||||
4. **Nautobot hat keine Location/Position** für ap1/ap2/ap3 hinterlegt (`location: None`). Nach dem
|
||||
abgeschlossenen Tausch die korrekten Positionen dort nachtragen (SSoT-Drift schließen).
|
||||
5. Gitea-TP25-Issue #17 bekommt den Befund als Kommentar (Zitat auf Messwerte + Zuordnung).
|
||||
|
||||
## Messwerte-Kurzform (für Folgesession)
|
||||
|
||||
`cap-wifi`-Karte war am Sitzungsende nach ap2-Rejoin: `cap-wifi1`=ap3-5G, `cap-wifi2`=ap3-2,4G,
|
||||
`cap-wifi3`=ap1-5G, `cap-wifi5`=ap1-2,4G, ap2 fehlte (down). **Die cap-wifiN-Nummern verschieben
|
||||
sich bei jedem CAP-Rejoin — vor jeder Messung neu lesen** (`/interface wifi radio print terse
|
||||
proplist=cap,radio-mac,interface` am Manager).
|
||||
96
docs/handoff-20260915-tp25-zuordnung-und-redundanz.md
Normal file
96
docs/handoff-20260915-tp25-zuordnung-und-redundanz.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# Handoff 2026-09-15 — TP25: AP-Zuordnung fixiert, Tausch-Befund, ap1-Redundanz gemessen
|
||||
|
||||
**Anlass:** Folgesession zur unklaren Tausch-Lage vom Vormittag ([[handoff-20260915-tp25-tausch-und-zuordnung]]).
|
||||
Ziele: (1) AP-Positionen definitiv per IP/MAC/Switch-Port klären, (2) ob die Messwerte den richtigen
|
||||
Geräten zugeordnet sind, (3) Rundgang-Messung im natürlichen Zustand, (4) ap1-Redundanz-Test (ap1 aus).
|
||||
|
||||
## 🔑 AP-Zuordnung — DEFINITIV (IP + MAC + Switch-Port)
|
||||
|
||||
| Gerät | IP | ether1-MAC | Bridge/Mgmt-MAC | Radios (5G/2,4G) | Port | Position |
|
||||
|---|---|---|---|---|---|---|
|
||||
| **ap1** | .11 | `D0:EA:11:4D:40:E0` | `:E1` | `:E5` / `:E6` | core **ether3** | Sideboard (Wohnzimmer) |
|
||||
| **ap2** | .12 | `D0:EA:11:4D:40:39` | `:3A` | `:3E` / `:3F` | core **ether21** | Technik **UG** |
|
||||
| **ap3** | .13 | `D0:EA:11:FF:16:9D` | `:9E` | `:9F` / `:A0` | branch **ether24** | Technik **OG** |
|
||||
|
||||
Beweis: Neighbor-Tabelle (MNDP, L2) + Bridge-Host-Tabelle + Port-Link-Status am Core, live gelesen.
|
||||
|
||||
⚠️ **MAC-Korrektur:** ap2s `ether1` ist **`:39`**, nicht `:3A`. `:3A` ist die Bridge-/Mgmt-MAC
|
||||
(die CLAUDE.md als „ap2" führt). ap2s Radios sind **`:3E`/`:3F`** — das Handoff-09-15 hatte damit
|
||||
recht; meine frühere „um eins versetzt"-Korrektur war falsch (ich hatte `:3A` fälschlich als
|
||||
ether1-Basis angenommen).
|
||||
|
||||
## Tausch-Befund — ap2↔ap3 statt ap1↔ap3
|
||||
|
||||
Geplant (Deckungsfix Variante 3): **ap1↔ap3** (cAP ax → Sideboard, hAP → UG-Schatten).
|
||||
Tatsächlich getauscht: **ap2↔ap3**:
|
||||
- **ap1** blieb Sideboard (ether3)
|
||||
- **ap2** ging von OG → UG (ether21)
|
||||
- **ap3** (cAP ax) ging von UG → OG (branch ether24)
|
||||
|
||||
⇒ Drei-Wege-Drehung mit dem **falschen Paar**. Der „Deckenstrahler" (cAP ax) steht jetzt in **OG**,
|
||||
nicht am guten Platz (Sideboard). Ursache war die ap1/ap2-Verwechslung während der Session.
|
||||
|
||||
## Rundgang 1 — alle APs an, natürlicher Zustand (ohne Fixierung)
|
||||
|
||||
Methode: Registration-Table am Manager im 1-s-Takt, iPhone `F2:62:4C:E1:AF:09` auf `dirtyvader-main`.
|
||||
|
||||
- **0 Disconnects**, Signal **−45…−77 dBm** (alles brauchbar, meist deutlich besser).
|
||||
- Roaming natürlich über **alle 3 APs** (ap3→ap2→ap1→ap2→ap3) — funktioniert.
|
||||
- **Terrasse** (das Sorgenkind): **−58 dBm stabil** an OG-Position (jetzt cAP ax), 2,4G.
|
||||
- **ap1 (Sideboard)** wurde nur **kurz gestreift** (−52…−60); den Rest dominieren ap3 (OG) + ap2 (UG).
|
||||
- Kein Band-Thrash: nur ein sinnvoller 2,4G-Ausflug bei 5G-Zellkante (−77), sonst sauber 5G.
|
||||
|
||||
## Rundgang 2 — ap1 komplett aus (Redundanz-Test)
|
||||
|
||||
**Methode (neues CAPsMAN-Wissen):** ap1-Radios lassen sich **nicht** über `cap-wifiN` abschalten
|
||||
(`failure: can not change dynamic interface`). Richtig: Provisioning-Regeln auf `action=none`, dann
|
||||
re-provisionieren:
|
||||
```
|
||||
/interface wifi provisioning set [find where radio-mac=D0:EA:11:4D:40:E5 or radio-mac=D0:EA:11:4D:40:E6] action=none
|
||||
/interface wifi capsman remote-cap provision [find where identity="ap1"]
|
||||
```
|
||||
Rückbau = `action=create-dynamic-enabled` + dieselbe re-provision. (Merkregel: `cap-wifiN` sind
|
||||
dynamische Interfaces; Abschalten geht nur über die Provisioning-Regel + re-provision.)
|
||||
|
||||
**Ergebnis:**
|
||||
- **Main-Client (iPhone):** ohne ap1 voll abgedeckt (ap2+ap3), tiefster Wert **−80 dBm** (ap3/OG 5G,
|
||||
an der Terrasse — dieselbe bekannte Zellkante, nur diesmal auf 5G statt 2,4G erwischt), kein Disconnect.
|
||||
- **IOT:** vorher 27 Geräte (19 ap1 + 8 ap2). Nach Abschalten **alle 27 zurück** — 23 auf ap2, 4 auf ap3.
|
||||
MAC-gegengeprüft, keiner verloren. **Aber ~4 Geräte sitzen marginal bei −77…−80 dBm** (Wohnzimmer-Geräte,
|
||||
vorher nah am Sideboard-AP, jetzt an der ap2/UG-2,4G-Zellkante).
|
||||
- **ap1 wieder eingeschaltet** (Revert) — Zustand vor dem Test wiederhergestellt.
|
||||
|
||||
## Befund: ap1 technisch redundant, aber 4 IOT-Geräte an der Kante
|
||||
|
||||
| Aspekt | Ergebnis |
|
||||
|---|---|
|
||||
| Main-Client | ✅ ohne ap1 voll abgedeckt, tiefster Wert −80, kein Disconnect |
|
||||
| IOT (27) | ✅ alle verbunden, **aber ~4 marginal −77…−80 dBm** |
|
||||
|
||||
ap1 ist **technisch redundant** — nichts fällt aus, wenn es weg ist. Aber die ~4 Wohnzimmer-IOT-Geräte
|
||||
verlieren ihre Signal-Reserve (verbunden ja, Aussetzer-Risiko erhöht). „ap1 abbauen" ist eine echte
|
||||
Option, aber kein Selbstläufer.
|
||||
|
||||
## Offen / nächste Schritte
|
||||
|
||||
1. **Entscheidung ap1:** behalten (Status quo) oder Richtung Abbau? Nur sinnvoll, wenn die ~4 marginalen
|
||||
IOT-Geräte akzeptiert werden (oder deren Platzierung/ap2-Abdeckung verbessert wird).
|
||||
2. **Tausch korrigieren?** Aktuell cAP ax @ OG, hAP @ UG, hAP @ Sideboard — misst gut, ist aber nicht der
|
||||
geplante Zustand (cAP ax → Sideboard). Der **Drei-Räume-Schatten** (Schlafzimmer/Bad/Küche, 08-22:
|
||||
−82…−84) ist mit dem jetzigen Arrangement **noch nicht verifiziert** — der Rundgang lief ohne
|
||||
Raumnamen/Fixierung. Nächste Messung sollte die drei Räume gezielt prüfen.
|
||||
3. **Doku-Drift schließen** (nicht in dieser Session angefasst): CLAUDE.md-Hardware-Tabelle (ap2-MAC
|
||||
`:3A`→`:39` ether1, ap2 Position OG→UG, ap3 UG→OG, ap1 „FUNKSTILL" überholt), teilprojekte.md TP25-Abschnitt,
|
||||
Nautobot Location (nach wie vor `None`).
|
||||
4. Gitea-Issue #17 trägt den Befund als Kommentar.
|
||||
|
||||
## Übergabeprompt (nächste Session)
|
||||
|
||||
> TP25 weiter: Die AP-Zuordnung ist jetzt definitiv geklärt (Handoff 2026-09-15 „zuordnung-und-redundanz").
|
||||
> ap1=Sideboard (core ether3), ap2=Technik UG (core ether21), ap3=Technik OG (branch ether24) — der Tausch
|
||||
> hat ap2↔ap3 vertauscht statt ap1↔ap3, ap1 blieb stehen. Rundgang ergab: Coverage überall gut (0 Disconnects,
|
||||
> −45…−77 dBm), Terrasse −58 stabil an OG, ap1 nur kurz gestreift. ap1-Aus-Test: Main-Client voll abgedeckt,
|
||||
> alle 27 IOT-Geräte kehren zurück, aber ~4 Wohnzimmer-IOT sitzen marginal −77…−80 dBm. ap1 ist wieder an.
|
||||
> Offen: (1) ap1 behalten oder abbauen? (2) Tausch auf Plan korrigieren (cAP ax → Sideboard)? (3) Drei-Räume-
|
||||
> Schatten (Schlafzimmer/Bad/Küche) gezielt nachmessen. (4) Doku-Drift (CLAUDE.md MAC/Positionen, Nautobot
|
||||
> Location) schließen.
|
||||
File diff suppressed because one or more lines are too long
@@ -1099,7 +1099,7 @@ des Dimmers (= Lichtausfall in Diele UG/Wohnzimmer) wurde daraufhin **nicht** au
|
||||
- **Abh.:** keine harten. **TP15 ✅** (die zu versorgende Hardware steht und hat DC-Eingänge). Verwandt: **TP18** (Garage-Nodes brauchen je Site eine Stromversorgung), **TP11** (USV-Zustand ins Monitoring). **Kein Blocker für TP5/TP6.**
|
||||
- **Historie:** war bis 2026-08-16 Unterpunkt von TP15 („🔋 DC-USV: MeanWell LRS-150-48 + DDR-120-48 + LiFePO4 20Ah (~€190), 48V-Bus; CRS326 DC-input passt"). Vollständige Recherche inkl. Schaltbild, Effizienzvergleich und Gerätetabelle: `docs/hw-refresh-requirements.md §9` (+ §10 D/E/F für die offenen Fragen).
|
||||
|
||||
### TP25 — WLAN-Stabilisierung ▸ ⏳ **FUND E ✅ GESCHLOSSEN 2026-09-02: die Abschlussmessung ist ruhig (4 reauth in 8,6 h, 0 Ausfälle, Verlauf 218→40→4) ⇒ `7.24.1` (TP27) war die Ursache, nicht `ft-over-ds`. Hebel 1 widerlegt+zurückgebaut, Hebel 2–4 entfallen, kein Geräte-Write** ([Handoff](handoff-20260902-tp25-fund-e-messung.md)) — **offen bleibt nur: ap2 unterperformt (2 m/−80 dBm, 23:02-Befund) als eigener In-situ-Unterpunkt** · Kern erledigt: 🟢 **(2026-08-22) Dead Spot Terrasse repariert** (43 % → 9 % Verlust, 20,4 s → 1,0 s). **Fund F ✅ aufgelöst (08-24, geräteseitig — kein Netzfehler)**, **5-GHz-Umfeldscan ✅ (08-24)**, Kanalplan für AP 3 ✅ gerechnet. Offen nur noch die Umsetzung, wenn der dritte AP kommt. Nicht mehr kritischer Pfad — Sammel-TP für Christophs Beobachtungen 1–6
|
||||
### TP25 — WLAN-Stabilisierung ▸ ⏳ **ap2-UNTERPUNKT ✅ WIDERLEGT 2026-09-14 (In-situ, [Handoff](handoff-20260914-tp25-ap2-insitu-terrassse.md)): ap2 sendet auf 2 m mit −49…−51 dBm, stabil, 0 Roams — Hardware sauber, kein Tausch begründet. Terrasse = 5-GHz-Zellkante (−76…−81 vs. 2,4 GHz −65…−73), Thrash nur in der Band-Überlappungszone −70…−77. Hebel „Access-List-Band-Boden" in der Machbarkeitsprüfung GESCHEITERT (kein `band`-Property, cap-wifiN-Rejoin-Falle) — s. Block unten** — **FUND E ✅ GESCHLOSSEN 2026-09-02: die Abschlussmessung ist ruhig (4 reauth in 8,6 h, 0 Ausfälle, Verlauf 218→40→4) ⇒ `7.24.1` (TP27) war die Ursache, nicht `ft-over-ds`. Hebel 1 widerlegt+zurückgebaut, Hebel 2–4 entfallen, kein Geräte-Write** ([Handoff](handoff-20260902-tp25-fund-e-messung.md)) · Kern erledigt: 🟢 **(2026-08-22) Dead Spot Terrasse repariert** (43 % → 9 % Verlust, 20,4 s → 1,0 s). **Fund F ✅ aufgelöst (08-24, geräteseitig — kein Netzfehler)**, **5-GHz-Umfeldscan ✅ (08-24)**, Kanalplan für AP 3 ✅ gerechnet. Nicht mehr kritischer Pfad — Sammel-TP für Christophs Beobachtungen 1–6
|
||||
> 📚 **Kondensiert am 2026-08-23 (Doku-Session, Punkt F).** Dieser Abschnitt war mit 394 Zeilen
|
||||
> 18 % der Datei. Die **Langfassung steht vollständig und unverändert** im Archiv:
|
||||
> [`teilprojekte-archiv.md` → TP25 (Langfassung)](teilprojekte-archiv.md#tp25-lang) — Messchronik (A)–(G),
|
||||
@@ -1108,6 +1108,79 @@ des Dimmers (= Lichtausfall in Diele UG/Wohnzimmer) wurde daraufhin **nicht** au
|
||||
> Merkregeln.** Wer an TP25 weiterarbeitet, kommt mit diesem Abschnitt aus; wer wissen will
|
||||
> *warum* etwas so entschieden wurde, liest die Langfassung.
|
||||
|
||||
**Stand 2026-09-15 — AP-Zuordnung DEFINITIV geklärt, Tausch-Befund ap2↔ap3** ([Handoff](handoff-20260915-tp25-zuordnung-und-redundanz.md)). Positionen per IP+MAC+Switch-Port (MNDP/Bridge-Host/Port-Link) live belegt: **ap1 = Sideboard/Wohnzimmer (`core ether3`), ap2 = Technik UG (`core ether21`), ap3 = Technik OG (`branch ether24`)**. Der geplante Tausch (ap1↔ap3, cAP ax → Sideboard) hat faktisch **ap2↔ap3** gedreht — ap1 blieb stehen, der cAP ax steht jetzt in OG. MAC-Korrektur: ap2 `ether1` ist `:39`, nicht `:3A` (`:3A` = Bridge/Mgmt-MAC). Rundgang (natürlicher Zustand, 1-s-Takt): **0 Disconnects**, −45…−77 dBm, Roaming über alle 3 APs; **Terrasse −58 stabil** (jetzt cAP ax/OG, 2,4G), ap1 nur kurz gestreift. ap1-Aus-Test: Main-Client voll abgedeckt (tiefster Wert −80), **alle 27 IOT kehren zurück**, aber ~4 Wohnzimmer-IOT marginal −77…−80 ⇒ ap1 technisch redundant, nicht ausfallkritisch. ap1 wieder an (Revert). Offen: (1) ap1 behalten/abbauen, (2) Tausch auf Plan korrigieren (cAP ax → Sideboard?), (3) Drei-Räume-Schatten (Schlafzimmer/Bad/Küche) gezielt nachmessen — noch nicht verifiziert, (4) Doku-Drift (diese Session).
|
||||
|
||||
**Stand 2026-09-14, 20:05 — ap2-In-situ: Hardware entlastet, Terrasse = 5-GHz-Zellkante,
|
||||
Band-Boden nicht sauber ausdrückbar** ([Handoff](handoff-20260914-tp25-ap2-insitu-terrassse.md)).
|
||||
Live-Session auf der Terrasse (Christoph kooperierte physisch — der Test, der am 08-31 „nachts
|
||||
nicht möglich" war): das Fund-E-iPhone flappte 18:53–19:18 ~30×, fast ausschließlich
|
||||
**ap2-5G ↔ ap2-2,4G** (−68…−81), mit 3 Abwürfen (2 Call-Aussetzer). Vor ap2 (1–2 m): **−49…−51 dBm,
|
||||
>2 min stabil, 0 Roams** ⇒ der offene Verdacht „ap2 RF/Antenne/HW" (23:02-Befund, 2 m/−80) ist
|
||||
**in situ widerlegt** — der 23:02-Wert reproduziert sich seit dem 09-04-Kanalplan (5300/5320,
|
||||
tx-power 18 live) nicht mehr. Am Terrassenplatz ist **2,4 GHz klar besser** (−65…−73 vs. 5 GHz
|
||||
−76…−81) und das Telefon dort **ruhig** (36 s im 1-s-Takt, 0 Roams) — es thrasht nur in der
|
||||
Überlappungszone −70…−77 beider Bänder; zusätzlich client-getrieben (floh 19:44 selbst von −52
|
||||
auf 2,4/−77; Steering hat keine Schwellen, der AP drängt nichts). Mit `ft=no` ist jeder Roam ein
|
||||
spürbarer Voll-Reconnect ⇒ so sterben Anrufe. **Hebel „Access-List-Boden < −76 auf 5G":
|
||||
Machbarkeitsprüfung negativ** — `/interface/wifi/access-list` hat kein `band`-Property,
|
||||
Interface-Scoping bricht am cap-wifiN-Rejoin, SSID-/MAC-Scope träfen 2,4 GHz mit (Schlafzimmer
|
||||
−84 ⇒ Lockout). **Nicht umgesetzt.** Verbleibende Hebel: (1) ✅ **DURCH 2026-09-14, 20:30 Uhr** — `ft=yes ft-over-ds=yes`
|
||||
uniform auf `sec-main` (Ruecknahme der 09-04-Entscheidung; Go per Fragenrunde nach Dry-Run). Weg:
|
||||
Template-Edit + `push-gc-template.py` (GC-Commit `744a17e3`) → `--refresh-compliance` (Drift
|
||||
`wifi-security` wie erwartet) → `gc-manual-plan.py --deploy` (Plan `b1135f3e`, Completed, Asserts gruen;
|
||||
ein Polling-Timeout am Skript war folgenlos — Geraet stand bereits auf ft=yes) → Refresh: **140/140, 0
|
||||
Drifts**. CAP-Abnahme: **keine** Inline-Overrides auf ap1/ap2/ap3. Commands-File:
|
||||
[`docs/transaktionen/TP25-ft-yes-secmain.commands.rsc`](transaktionen/TP25-ft-yes-secmain.commands.rsc).
|
||||
Abnahme ✅ **DURCH (2026-09-14, 20:33–20:34 Uhr, live)**: Anruf auf der Terrasse ueberstand
|
||||
**fuenf Band-Wechsel binnen 60 s** (nur `roamed to`, keine `disconnected` mehr im Fenster —
|
||||
Christoph: „call steht"). (2) Deckungsfix
|
||||
Variante 3 (ap1-5G erreichte die Terrasse mit −64) — beendet das Springen selbst.
|
||||
Nachtrag 20:37: ein **Totalverlust** anderer Klasse (Roam auf ap1-2,4 bei −89, danach iOS-Aufgeben
|
||||
ohne jeden Reconnect-Versuch; identisch schon 19:01 mit ft=no gesehen) — **keine ft=yes-Regression**,
|
||||
sondern der strukturelle Rest. **Wechselrichter/DTU (Hoymiles HMS-800W-2T, geht mit der Sonne an/ab,
|
||||
09-14: 07:09–19:35): nachts unbeteiligt; tagsüber ~5:05-Zyklus (connect/`connection lost`/reconnect +
|
||||
DHCP-Churn) auf ap2-2,4/ch11 bei −53.** Messplan „DTU vs. Terrasse" angelegt ([Issue #17, Kommentar
|
||||
#225](https://gitea.emsenhuber.net/admin/bf-infra/issues/17#issuecomment-225)): Referenz-Client auf
|
||||
ch11 pinnen (tp25-Methodik), 30–60 min Ping, Korrelation gegen die 5:05-Taktmarken. ⚠️ **Korrektur
|
||||
09-14 abends ([Kommentar #227](https://gitea.emsenhuber.net/admin/bf-infra/issues/17#issuecomment-227)):
|
||||
Der urspruenglich genannte Hebel „OpenDTU/AhoyDTU-Dongle" existiert fuer DASSES Geraet NICHT** — HMS-
|
||||
**XXXXW**-2T (W = eingebaute DTU „DTUBI", protobuf-Protokoll) wird von AhoyDTU/OpenDTU nicht
|
||||
unterstuetzt (lumapu/ahoy#1189 seit 09-2023 offen; Christophs eigene AhoyDTU nachweislich
|
||||
inkompatibel; nur die Nicht-W-Variante HMS-800-**2T** ginge per CMT2300-Funk). Die lokale Ebene
|
||||
(hms-mqtt-publisher = „hmsmqtt", dtuGateway, ha-hoymiles-wifi) redet **mit der internen DTU uebers
|
||||
Netzwerk** — keines davon nimmt die DTU von der Luft, hmsmqtt pollt sogar zusaetzlich. **Einziger
|
||||
Airtime-Hebel bleibt DNS-Hoheit ueber die Cloud**, von Christoph bewusst zurueckgestellt (Cloud-
|
||||
Aufzeichnungen noch benoetigt, bis hmsmqtt + WLAN stabil); ob eine DTU ohne Cloud ruhiger oder
|
||||
gespraechiger wird, ist selbst eine offene Messfrage. Pin auf anderen AP kontraindiziert
|
||||
(−53 direkt an ap2); 5-Min-Takt ist S-Miles-Telemetrie per Design, kein Ethernet an der DTU-WLite.
|
||||
✅ **Netzwerk-Mechanismus geklaert (09-14, Nacht; [Issue #17, Kommentar
|
||||
#228](https://gitea.emsenhuber.net/admin/bf-infra/issues/17#issuecomment-228)):** Der **Fund-F-5:05-Zyklus
|
||||
ist das Cloud-Recovery-Verhalten der DTU.** Wireshark-Analyse (hms-mqtt-publisher PR #110, HMS-800W-2T):
|
||||
lokaler Poll <30 s resettet den Countdown und setzt Cloud-Updates aus; **nach 4–5 min erfolgloser
|
||||
Cloud-Updates** startet die DTU eine neue TCP-Session — und dabei (unser Log-Beweis 09-14) eine
|
||||
**vollstaendige WiFi-Disassoziation inkl. DHCP-Churn**. Die heute gemessenen Zyklus-Abstaende decken
|
||||
sich mit dem Befund aufs Minutenkomma. Ursache war hmsmqtt mit **30 500 ms** (Grenzzone);
|
||||
DTU-Firmware aelter, hmsmqtt funktioniert (⇒ #134-Key-Rotation-Falle nicht primaer).
|
||||
**Hebel = Poll-Rate, nicht DNS-Hoheit:** Christoph hat **30500 → 45000 ms** gesetzt (09-14 abends;
|
||||
Community-Wert, 10 Monate stabil). ✅ **Verifikation DURCH (09-15, 12:11; [Issue #17, Kommentar
|
||||
#230](https://gitea.emsenhuber.net/admin/bf-infra/issues/17#issuecomment-230)): DTU online seit 06:41:49,
|
||||
uptime 5 h 29 min, 0 Disconnects** (Vergleich 09-14 mit 30,5 s: fuenf Zyklen in den ersten 18 min).
|
||||
Die DTU sitzt heute auf **ap3-2,4** (cap-wifi4-virtual1, −49; cap-Karte unveraendert, Attribution
|
||||
belastbar) — also aktuell auch vom Terrassen-Band ch11 weg. **Fund F ist damit abgeschlossen** —
|
||||
Ursache war die DTU-Cloud-Recovery, getriggert durch hmsmqtt-Polling-Kollision. Messplan #225 ist
|
||||
gegenstandslos (der zu messende Effekt existiert nicht mehr); eine ch11-Tagzeitmessung bleibt nur
|
||||
sinnvoll, falls die Terrasse tagsueber weiterhin Call-Probleme zeigt. 📅 **terminiert ([Issue #17,
|
||||
Kommentar #232](https://gitea.emsenhuber.net/admin/bf-infra/issues/17#issuecomment-232)): Deckungsfix
|
||||
Variante 3 — Umsetzung 2026-09-15/16** (Christoph: „heute oder morgen"): Deckenstrahler an den guten
|
||||
Platz, verdrängter hAP in den Drei-Raeume-Schatten (Schlafzimmer −84,6/38 %, Bad −82,3/24 %,
|
||||
Kueche −82,0/23 % laut 08-22-Messung). Vorher-Messung Terrasse (Referenz 09-14: 5 GHz −76…−81,
|
||||
2,4 GHz −65…−73) → Umsetzung → Nachher-Messung + Anruf-Abnahme; Kanalplan (09-04) bleibt unberuehrt,
|
||||
nur Platzierung aendert sich; Config-Aenderungen nur ueber den GC-Weg. Offen vor Ort: Zielraum fuer
|
||||
den verdraengten hAP (PoE/Steckdose) und ap1-Uplink-Thema (Sideboard → `core ether3`) mitdenken.
|
||||
Randnotizen: ap1 „FUNKSTILL" im CLAUDE.md ist überholt (dient live, Radar-Event 16:51 auf 5280
|
||||
sauber abgehandelt); Template-Abschnitt [6c] („Fund E WIEDER OFFEN", Stand 08-30) ist inhaltlich
|
||||
überholt — beim nächsten Template-Edit mit aktualisieren, kein separater Edit nur für den Kommentar.
|
||||
|
||||
**Stand 2026-08-22, 23:30 — die Terrasse ist repariert.** Erster Lauf mit beiden Ping-Strecken
|
||||
([`tp25-runde-20260822-2330-auswertung.md`](tp25-runde-20260822-2330-auswertung.md)): **43 % Verlust /
|
||||
20,4 s längste Lücke (08-21) → 9 % / 1,0 s** bei gleichem Gerät und gleicher Rolle. Wirksam war das
|
||||
@@ -1804,6 +1877,7 @@ Umzug **nebeneinander**, ein zweiter AP am selben Punkt bringt nichts und stört
|
||||
| 6 | **MariaDB `root`** (LXC 302, `10.40.20.23`) | root-DB-Login | 🔴 am 2026-09-01 (TP39) ins Transkript geraten — die `/root/.my.cnf` trug `password <wert>` **ohne `=`**, die Feld-Maskierung ankerte auf `=` und griff nicht | Wert in `/root/.my.cnf` (chmod 600) | `SET PASSWORD` + `.my.cnf` nachziehen; **kein** externer Konsument (Dienste nutzen eigene DB-User) ⇒ billigste Rotation der Liste |
|
||||
| 7 | **`TERPENE_ANDROID_KEYSTORE_PW`** | Terpene-Android-TWA-Signing (`android/android.keystore`, alias `terpene`) | 🔴 am 2026-09-01 (TP41) durch **Regex-Suffix-Loch** (`_PW` nicht abgedeckt) ins Transkript geraten | Wert in `~/.secrets/credentials.env` + Keystore-Datei | **Store-/Key-Passwort** via `keytool -storepasswd`/`-keypasswd` ändern + `credentials.env` nachziehen; Konsument = Android-Build/Play-Signing (**Cross-Projekt blaueblüten**) — den **Key selbst NICHT** neu erzeugen |
|
||||
| 8 | **`N8N_SMTP_PASS`** (Gmail-App-PW für `johnny.claw.0x00@gmail.com`) | SMTP-Versand aus n8n (Portainer-Stack 174 `n8n`, macmini) | 🔴 am 2026-09-01 (n8n-mcp-SSRF-Session) beim Ausgeben des Stack-174-Files ins Transkript geraten — Redaktionsmuster hatte `PASSWORD`, aber **nicht bare `PASS`** → `N8N_SMTP_PASS=<wert>` blieb stehen | Wert in Portainer-Stack 174 (`environment`) | **Gmail-App-Passwort widerrufen** (Google-Konto → App-Passwörter) + neues erzeugen, Stack-174-Env nachziehen + redeploy; Konsument = n8n-SMTP-Node(s) |
|
||||
| 9 | **`GITEA_ACCESS_TOKEN`** (API-Zugang `gitea.emsenhuber.net`) | Session-Tooling (`bin/gitea-tp-sync.py`, Ad-hoc-API-Calls) | 🔴 am 2026-09-14 (TP25-In-situ-Session) **ins Transkript** geraten: Env-Parse-Fehler schob den Token in die URL-Konstruktion, `urllib` warf `ValueError: unknown url type` und druckte ihn im Traceback | Mechanismus zu: Token gehört **nur in den `Authorization`-Header, nie in eine URL** — und der Fehlerpfad, der ihn enthält, darf ihn nicht ausgeben (gleiche Familie wie #1/#5/#6/#7/#8, diesmal Unterklasse „Fehlerausgabe statt Maskierung") | neu anlegen (Gitea → Settings → Applications), `~/.hermes/.env` nachziehen, altes widerrufen; Konsumenten = `gitea-tp-sync.py` + Session-Ad-hoc-Calls |
|
||||
|
||||
> ✅ **Der Leak-MECHANISMUS hinter #1 ist seit 2026-08-31 zu — der Wert bleibt trotzdem verbrannt.**
|
||||
> Alle sechs Skripte im Repo, die `sshpass -p <PW>` benutzten (`nautobot/gc-transaktion.py` und
|
||||
@@ -1837,6 +1911,15 @@ Umzug **nebeneinander**, ein zweiter AP am selben Punkt bringt nichts und stört
|
||||
> Mal neu (und falsch) tippt: `sed -E 's/([A-Z0-9_]*(PASS|PASSWORD|PWD|PW|TOKEN|SECRET|KEY|BEARER))=[^[:space:]]*/\1=<redacted>/g'`
|
||||
> — ankert auf den **Schlüsselnamen inkl. Präfix** und deckt alle bisher gesehenen Suffixe ab.
|
||||
>
|
||||
> 🔴 **#9 ist der sechste Vorfall derselben Familie, aber eine neue Unterklasse** (SHELLY 08-28,
|
||||
> Nautobot-Tokens 08-31, MariaDB-root 09-01, Keystore 09-01, SMTP 09-01): diesmal kein
|
||||
> Maskierungsmuster, sondern ein **Fehlerpfad** — ein Env-Parse-Fehler schob den Token in die
|
||||
> URL-Konstruktion, und `urllib` druckte ihn im `ValueError: unknown url type`-Traceback.
|
||||
> **Merkregel: ein Secret gehört in keine Datenstruktur, die eine Exception ausgeben kann**
|
||||
> (URL-Konstruktion validieren, bevor das Secret hineinwandert; Fehlerpfade dürfen den
|
||||
> fehlerhaften Wert nicht mitschleppen). Das Redaktions-Snippet oben hilft hier nicht — es
|
||||
> kann nichts maskieren, was als Fehlermeldung und nicht als Dateiinhalt kommt.
|
||||
>
|
||||
> ℹ️ **#3 war bis 2026-08-24 TP17.2** und ist jetzt vollständig hier (s. Detailabschnitt unten) —
|
||||
> es benutzt denselben Geräte-Durchgang wie #2, **ein Reboot statt zwei**. #4 gehört sachlich zu
|
||||
> **TP14.4**, das als TP bestehen bleibt (dort steckt das CF-Access-Profil, nicht nur der Token).
|
||||
|
||||
8
docs/transaktionen/TP25-ft-yes-secmain.commands.rsc
Normal file
8
docs/transaktionen/TP25-ft-yes-secmain.commands.rsc
Normal file
@@ -0,0 +1,8 @@
|
||||
# TP25 — sec-main zurueck auf ft=yes / ft-over-ds=yes (Ruecknahme der 09-04-Entscheidung "ft=no als Dauerzustand")
|
||||
# Go: Christoph 2026-09-14 ("go fuer ft=yes, dry-run vorlegen"), Terrasse-In-situ-Session
|
||||
# Anlass: 2 Call-Aussetzer + ~30 Roams in 25 min — mit ft=no ist jeder Roam (Band- und AP-Wechsel)
|
||||
# eine Voll-Reassoziation in Sekundenhoehe; genau darin sterben Anrufe.
|
||||
# Nachweis, dass ft-over-ds=yes + 7.24.1 ruhig ist: Fund-E-Abschlussmessung 09-02 (4 reauth/8,6 h, 0 Ausfaelle).
|
||||
# Nur am Manager noetig: sec-main wird per CAPsMAN an alle CAPs verteilt (Uniformitaet per Konstruktion);
|
||||
# Inline-Overrides je CAP gibt es seit dem ap3-Fix 09-04 nicht mehr — Abnahme prueft sie trotzdem (Merkregel).
|
||||
/interface wifi security set sec-main ft=yes ft-over-ds=yes
|
||||
10
docs/transaktionen/TP25-steering-5g-threshold.commands.rsc
Normal file
10
docs/transaktionen/TP25-steering-5g-threshold.commands.rsc
Normal file
@@ -0,0 +1,10 @@
|
||||
# TP25 — 5G bricht frueher zur 2.4G ab (Terrasse sass am Rundgang 09-15 auf der -80/5G-Kante)
|
||||
# Go: Christoph 2026-09-15 ("committen und threshold deployen")
|
||||
# Nur 5G: neues Steering-Profil st-main-5g mit transition-threshold=-72 (statt Default -80) und
|
||||
# transition-threshold-time=5s (statt 10s). 2G bleibt auf st-main (unset -80) — Reichweite draussen.
|
||||
# Nur am Manager noetig: steering/config werden per CAPsMAN an die CAPs verteilt.
|
||||
# Rollback = steering der drei Configs zurueck auf st-main + st-main-5g loeschen.
|
||||
/interface wifi steering add name=st-main-5g neighbor-group=bf-main rrm=yes wnm=yes transition-threshold=-72 transition-threshold-time=5s
|
||||
/interface wifi configuration set [find name=cfg-main-5g-ap1] steering=st-main-5g
|
||||
/interface wifi configuration set [find name=cfg-main-5g-ap2] steering=st-main-5g
|
||||
/interface wifi configuration set [find name=cfg-main-5g-ap3] steering=st-main-5g
|
||||
@@ -84,7 +84,7 @@ dns:
|
||||
ipset_file: ""
|
||||
bootstrap_prefer_ipv6: false
|
||||
upstream_timeout: 10s
|
||||
private_networks: []
|
||||
private_<redacted>: []
|
||||
use_private_ptr_resolvers: false
|
||||
local_ptr_upstreams: []
|
||||
use_dns64: false
|
||||
|
||||
@@ -353,10 +353,76 @@ def job_tp42_dhcp_domain():
|
||||
return [(["crs326-core"], core_set, "TP42-dhcp-domain-bf")]
|
||||
|
||||
|
||||
def job_tp38_oob():
|
||||
"""TP38 (2026-09-15): OOB-MGMT-Port (ether23 untagged VLAN99) + Branch-Input-Firewall.
|
||||
|
||||
Zwei Geraete, zwei config_sets:
|
||||
* branch: ether23 untaggen, VLAN99 um untagged=ether23 erweitern, 8 Input-Regeln
|
||||
(deny-by-default). Die Regeln werden in der Reihenfolge angelegt, in der das
|
||||
Template sie rendert — established zuerst, drop zuletzt — damit kein LOCKOUT:
|
||||
die laufende Nautobot-SSH-Session (10.40.20.30) matcht auf Regel 1 (established),
|
||||
bevor Regel 8 (drop) greift.
|
||||
* core: ether23 untaggen, VLAN99 untagged=ether23, EINE Regel "OOB->core mgmt" mit
|
||||
place-before vor die Log-Regel (sonst landet sie hinter dem finalen drop und
|
||||
waere wirkungslos + non-compliant).
|
||||
|
||||
KEIN LOCKOUT-RISIKO: ether23 ist auf beiden Geraeten frei (running=false); der
|
||||
VLAN99-Umbau aendert nur `untagged`, nicht `tagged`; der Deploy laeuft von Nautobot
|
||||
(10.40.20.30), das in jeder gesetzten Firewall-Freigabe enthalten bleibt.
|
||||
"""
|
||||
bridge_set = (
|
||||
':do { /interface bridge port set [find interface=ether23] pvid=99 '
|
||||
'frame-types=admit-only-untagged-and-priority-tagged comment="TP38-OOB-MGMT" } '
|
||||
'on-error={ :log info "tp38: ether23 set geworfen" }'
|
||||
)
|
||||
vlan_set = (
|
||||
':do { /interface bridge vlan set [find vlan-ids=99] untagged=ether23 } '
|
||||
'on-error={ :log info "tp38: vlan99 untagged geworfen" }'
|
||||
)
|
||||
|
||||
branch_fw = "\n".join([
|
||||
'add action=accept chain=input comment="TP38: established" connection-state=established,related,untracked',
|
||||
'add action=drop chain=input comment="TP38: invalid" connection-state=invalid',
|
||||
'add action=accept chain=input comment="TP38: icmp" protocol=icmp',
|
||||
'add action=accept chain=input comment="TP38: mndp" dst-port=5678 protocol=udp',
|
||||
'add action=accept chain=input comment="TP38: mgmt LAN" dst-port=22,80,8291,8728 protocol=tcp src-address=10.40.0.0/16',
|
||||
'add action=accept chain=input comment="TP38: mgmt mesh" dst-port=22,80,8291,8728 protocol=tcp src-address=100.96.0.0/12',
|
||||
'add action=log chain=input comment="TP38: input log-only" log-prefix=TP38-BRANCH-WOULD-DROP',
|
||||
'add action=drop chain=input comment="TP38: input deny-by-default"',
|
||||
])
|
||||
branch_set = "\n".join([
|
||||
bridge_set,
|
||||
vlan_set,
|
||||
*[f"/ip firewall filter {ln}" for ln in branch_fw.splitlines()],
|
||||
':log info ("tp38: branch pvid=" . [:tostr [/interface bridge port get [find interface=ether23] pvid]]'
|
||||
' . " fw=" . [:tostr [:len [/ip firewall filter find where comment~"TP38"]]] . "/8")',
|
||||
])
|
||||
|
||||
# ⚠️ `add ... place-before=[find ...]` wird ueber Netmiko IGNORIERT (Regel landet am
|
||||
# Ketten-Ende, also HINTER dem finalen drop = wirkungslos; beim Deploy 2026-09-15 so
|
||||
# aufgeschlagen). Deshalb: erst add (appends), dann `move` vor die Log-Regel.
|
||||
core_set = "\n".join([
|
||||
bridge_set,
|
||||
vlan_set,
|
||||
'/ip firewall filter add action=accept chain=input comment="TP38: OOB->core mgmt" '
|
||||
'dst-port=22,80,8291,8728 in-interface=vlan99 protocol=tcp',
|
||||
'/ip firewall filter move [find where comment="TP38: OOB->core mgmt"] '
|
||||
'destination=[find where comment="TP5: input log-only"]',
|
||||
':log info ("tp38: core pvid=" . [:tostr [/interface bridge port get [find interface=ether23] pvid]]'
|
||||
' . " oob=" . [:tostr [:len [/ip firewall filter find where comment="TP38: OOB->core mgmt"]]])',
|
||||
])
|
||||
|
||||
return [
|
||||
(["crs326-branch"], branch_set, "TP38-oob-branch"),
|
||||
(["crs326-core"], core_set, "TP38-oob-core"),
|
||||
]
|
||||
|
||||
|
||||
JOBS = {
|
||||
"drift-cleanup": job_drift_cleanup,
|
||||
"mgmt-acl": job_mgmt_acl,
|
||||
"tp42-dhcp-domain": job_tp42_dhcp_domain,
|
||||
"tp38-oob": job_tp38_oob,
|
||||
}
|
||||
|
||||
|
||||
|
||||
105
nautobot/ingest-tp38-oob.py
Normal file
105
nautobot/ingest-tp38-oob.py
Normal file
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3
|
||||
r"""TP38: OOB-Port + Input-Firewall als Daten nach Nautobot schreiben.
|
||||
|
||||
Zwei getrennte Aenderungen, ein Skript:
|
||||
|
||||
1. BRANCH (crs326-branch): `firewall_filter` im local_config_context_data ANLEGEN
|
||||
(8 Input-Regeln, deny-by-default). Der src-Rahmen 10.40.0.0/16 + 100.96.0.0/12
|
||||
spiegelt bewusst das `available-from` der /ip service-Zeilen — kein neues
|
||||
Fenster, nur stateful + deny-by-default + WOULD-DROP-Log.
|
||||
2. CORE (crs326-core): EINE Regel "TP38: OOB->core mgmt" in die bestehende
|
||||
firewall_filter-Liste EINFUEGEN (vor log/drop), damit der OOB-Port (untagged
|
||||
ether23, VLAN99) auch den Core selbst verwalten kann.
|
||||
|
||||
Attributreihenfolge = alphabetisch, exakt wie RouterOS `/export` sie schreibt
|
||||
(gleiche Konvention wie ingest-core-firewall.py).
|
||||
|
||||
python3 nautobot/ingest-tp38-oob.py # Dry-Run
|
||||
python3 nautobot/ingest-tp38-oob.py --apply
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import urllib.request
|
||||
|
||||
NB = os.environ.get("NAUTOBOT_URL", "http://10.40.20.30:8080")
|
||||
|
||||
BRANCH_RULES = [
|
||||
'add action=accept chain=input comment="TP38: established" connection-state=established,related,untracked',
|
||||
'add action=drop chain=input comment="TP38: invalid" connection-state=invalid',
|
||||
'add action=accept chain=input comment="TP38: icmp" protocol=icmp',
|
||||
'add action=accept chain=input comment="TP38: mndp" dst-port=5678 protocol=udp',
|
||||
'add action=accept chain=input comment="TP38: mgmt LAN" dst-port=22,80,8291,8728 protocol=tcp src-address=10.40.0.0/16',
|
||||
'add action=accept chain=input comment="TP38: mgmt mesh" dst-port=22,80,8291,8728 protocol=tcp src-address=100.96.0.0/12',
|
||||
'add action=log chain=input comment="TP38: input log-only" log-prefix=TP38-BRANCH-WOULD-DROP',
|
||||
'add action=drop chain=input comment="TP38: input deny-by-default"',
|
||||
]
|
||||
|
||||
CORE_NEW_RULE = 'add action=accept chain=input comment="TP38: OOB->core mgmt" dst-port=22,80,8291,8728 in-interface=vlan99 protocol=tcp'
|
||||
|
||||
|
||||
def nb(path, method="GET", payload=None):
|
||||
tok = os.environ.get("NAUTOBOT_TOKEN") or sys.exit("NAUTOBOT_TOKEN nicht gesetzt")
|
||||
req = urllib.request.Request(
|
||||
f"{NB}{path}", method=method,
|
||||
data=json.dumps(payload).encode() if payload is not None else None,
|
||||
headers={"Authorization": f"Token {tok}", "Content-Type": "application/json",
|
||||
"Accept": "application/json"})
|
||||
with urllib.request.urlopen(req, timeout=60) as r:
|
||||
raw = r.read()
|
||||
return json.loads(raw) if raw else {}
|
||||
|
||||
|
||||
def get_device(name):
|
||||
return nb(f"/api/dcim/devices/?name={name}&depth=1")["results"][0]
|
||||
|
||||
|
||||
def patch_device(dev, ctx, label):
|
||||
dev_id = dev["id"]
|
||||
nb(f"/api/dcim/devices/{dev_id}/", "PATCH", {"local_config_context_data": ctx})
|
||||
print(f" ~ {label} geschrieben.")
|
||||
|
||||
|
||||
def main():
|
||||
apply_ = "--apply" in sys.argv
|
||||
|
||||
# --- BRANCH ---
|
||||
branch = get_device("crs326-branch")
|
||||
bctx = dict(branch.get("local_config_context_data") or {})
|
||||
if bctx.get("firewall_filter") == BRANCH_RULES:
|
||||
print("== branch: firewall_filter unveraendert ==")
|
||||
else:
|
||||
bctx["firewall_filter"] = BRANCH_RULES
|
||||
print(f"== branch: {len(BRANCH_RULES)} Input-Regeln ==")
|
||||
for ln in BRANCH_RULES:
|
||||
print(" " + ln)
|
||||
if apply_:
|
||||
patch_device(branch, bctx, "branch firewall_filter")
|
||||
|
||||
# --- CORE ---
|
||||
core = get_device("crs326-core")
|
||||
cctx = dict(core.get("local_config_context_data") or {})
|
||||
ff = list(cctx.get("firewall_filter") or [])
|
||||
if CORE_NEW_RULE in ff:
|
||||
print("\n== core: Regel schon vorhanden ==")
|
||||
else:
|
||||
# vor der Log-Regel einsortieren (die sitzt direkt vor dem finalen drop).
|
||||
insert_at = len(ff)
|
||||
for i, ln in enumerate(ff):
|
||||
if "log-prefix=TP5-INPUT-WOULD-DROP" in ln:
|
||||
insert_at = i
|
||||
break
|
||||
ff.insert(insert_at, CORE_NEW_RULE)
|
||||
cctx["firewall_filter"] = ff
|
||||
print(f"\n== core: fuege OOB-Regel an Position {insert_at} ein ==")
|
||||
print(" " + CORE_NEW_RULE)
|
||||
if apply_:
|
||||
patch_device(core, cctx, "core firewall_filter")
|
||||
|
||||
if not apply_:
|
||||
print("\nDRY-RUN — mit --apply schreiben. Danach: "
|
||||
"push-gc-template.py + gc-configplan.py --refresh-compliance")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -73,9 +73,11 @@
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=ether14 pvid=30
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=ether15
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=ether16 pvid=100
|
||||
{% for n in range(17, 25) %}
|
||||
{% for n in range(17, 23) %}
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=ether{{ n }}
|
||||
{% endfor %}
|
||||
/interface bridge port add bridge=bridge comment=TP38-OOB-MGMT frame-types=admit-only-untagged-and-priority-tagged interface=ether23 pvid=99
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=ether24
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=sfp-sfpplus1
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=sfp-sfpplus2
|
||||
# ether4 = Wohnzimmer-Sideboard: 2026-08-13 von Trunk auf untagged VLAN40 gezogen (TP21.1/4).
|
||||
@@ -94,7 +96,7 @@
|
||||
/interface bridge vlan add bridge=bridge tagged=ether1,ether3,ether8,ether13,ether15,ether21 untagged=ether2,ether4,ether5 vlan-ids=40
|
||||
/interface bridge vlan add bridge=bridge tagged=ether1,ether3,ether8,ether15,ether21 vlan-ids=50
|
||||
/interface bridge vlan add bridge=bridge tagged=ether1,ether3,ether8,ether15,ether21 vlan-ids=90
|
||||
/interface bridge vlan add bridge=bridge tagged=ether3,ether8,ether15,ether21,bridge vlan-ids=99
|
||||
/interface bridge vlan add bridge=bridge tagged=ether3,ether8,ether15,ether21,bridge untagged=ether23 vlan-ids=99
|
||||
/interface bridge vlan add bridge=bridge tagged=ether1 untagged=ether16 vlan-ids=100
|
||||
|
||||
# [1] INTERFACE-LISTS
|
||||
@@ -222,10 +224,12 @@
|
||||
/interface wifi datapath add bridge=bridge name=dp-media vlan-id=40
|
||||
/interface wifi datapath add bridge=bridge name=dp-untrusted vlan-id=50
|
||||
/interface wifi datapath add bridge=bridge name=dp-guest vlan-id=90
|
||||
# sec-main: ft=no seit 2026-09-04 (User-Entscheid nach TP25-Messung). Fast-Transition
|
||||
# komplett aus; ft-over-ds ist damit gegenstandslos (gilt nur bei ft=yes) und steht auf no.
|
||||
# Fund E hatte ft-over-ds=no BEI ft=yes widerlegt -- das hier ist ein anderer Hebel (FT aus).
|
||||
/interface wifi security add authentication-types=wpa3-psk ft=no ft-over-ds=no name=sec-main passphrase="<<REDACTED>>"
|
||||
# sec-main: ft=yes/ft-over-ds=yes zurueckgesetzt am 2026-09-14 (Ruecknahme des 09-04-Entscheids
|
||||
# "ft=no als Dauerzustand"; Go nach Terrasse-In-situ-Session: mit ft=no war jeder Roam eine
|
||||
# Voll-Reassoziation -- darin starben Anrufe). Known-Good: genau dieser Stand lief in der
|
||||
# Fund-E-Abschlussmessung 09-02 ruhig (4 reauth/8,6 h, 0 Ausfaelle) auf 7.24.1.
|
||||
# 2026-09-04 stand hier: ft=no ft-over-ds=no (User-Entscheid nach TP25-Messung).
|
||||
/interface wifi security add authentication-types=wpa3-psk ft=yes ft-over-ds=yes name=sec-main passphrase="<<REDACTED>>"
|
||||
/interface wifi security add authentication-types=wpa2-psk,wpa3-psk disabled=no ft=no name=sec-infra passphrase="<<REDACTED>>"
|
||||
/interface wifi security add authentication-types=wpa2-psk,wpa3-psk disabled=no ft=no name=sec-iot passphrase="<<REDACTED>>"
|
||||
/interface wifi security add authentication-types=wpa2-psk,wpa3-psk ft=no name=sec-media passphrase="<<REDACTED>>"
|
||||
@@ -239,11 +243,16 @@
|
||||
# BSSIDs einer SSID melden, auf die sie gar nicht assoziieren koennen (TP28).
|
||||
/interface wifi steering add name=st-main neighbor-group=bf-main rrm=yes wnm=yes
|
||||
/interface wifi steering add name=st-guest neighbor-group=bf-guest rrm=yes wnm=yes
|
||||
/interface wifi configuration add channel=ch-5g-ap1 country=Austria datapath=dp-main mode=ap name=cfg-main-5g-ap1 security=sec-main ssid=dirtyvader-main steering=st-main
|
||||
/interface wifi configuration add channel=ch-5g-ap2 country=Austria datapath=dp-main mode=ap name=cfg-main-5g-ap2 security=sec-main ssid=dirtyvader-main steering=st-main
|
||||
# st-main-5g (TP25, 2026-09-15): transition-threshold=-72 statt Default -80 -- 5G bricht frueher
|
||||
# zur 2.4G ab (Terrasse sass am Rundgang 09-15 auf der -80/5G-Kante). transition-threshold-time=5s
|
||||
# statt 10s. NUR 5G: die drei 2G-Configs bleiben auf st-main (unset=-80), weil 2.4G draussen
|
||||
# (Terrasse/ausserhalb der Wohnung) Reichweite behalten soll. 8 dB Abstand = kleine Hysterese.
|
||||
/interface wifi steering add name=st-main-5g neighbor-group=bf-main rrm=yes transition-threshold=-72 transition-threshold-time=5s wnm=yes
|
||||
/interface wifi configuration add channel=ch-5g-ap1 country=Austria datapath=dp-main mode=ap name=cfg-main-5g-ap1 security=sec-main ssid=dirtyvader-main steering=st-main-5g
|
||||
/interface wifi configuration add channel=ch-5g-ap2 country=Austria datapath=dp-main mode=ap name=cfg-main-5g-ap2 security=sec-main ssid=dirtyvader-main steering=st-main-5g
|
||||
/interface wifi configuration add channel=ch-2g-ap1 country=Austria datapath=dp-main mode=ap name=cfg-main-2g-ap1 security=sec-main ssid=dirtyvader-main steering=st-main
|
||||
/interface wifi configuration add channel=ch-2g-ap2 country=Austria datapath=dp-main mode=ap name=cfg-main-2g-ap2 security=sec-main ssid=dirtyvader-main steering=st-main
|
||||
/interface wifi configuration add channel=ch-5g-ap3 country=Austria datapath=dp-main mode=ap name=cfg-main-5g-ap3 security=sec-main ssid=dirtyvader-main steering=st-main
|
||||
/interface wifi configuration add channel=ch-5g-ap3 country=Austria datapath=dp-main mode=ap name=cfg-main-5g-ap3 security=sec-main ssid=dirtyvader-main steering=st-main-5g
|
||||
/interface wifi configuration add channel=ch-2g-ap3 country=Austria datapath=dp-main mode=ap name=cfg-main-2g-ap3 security=sec-main ssid=dirtyvader-main steering=st-main
|
||||
/interface wifi configuration add country=Austria datapath=dp-guest mode=ap name=cfg-guest security=sec-guest ssid=dirtyvader-guest steering=st-guest
|
||||
/interface wifi capsman set ca-certificate=auto certificate=auto enabled=yes interfaces=vlan99 upgrade-policy=none
|
||||
@@ -273,17 +282,16 @@
|
||||
# python3 nautobot/gc-transaktion.py begin --device crs326-core \
|
||||
# --scope wifi-access-list --change-id TEST-... --expires JJJJ-MM-TT
|
||||
#
|
||||
# 🔴 Hier landet TP25 **Fund E** (`signal-range`-Boden gegen klebende Clients),
|
||||
# sobald er entschieden ist. Die alte Auflage lautete "vor dem Eintragen den
|
||||
# Sticky-Fall erneut messen" -- das ist am 2026-08-30 passiert: dasselbe iPhone
|
||||
# machte 16 Bandwechsel in 20 Minuten bei -53..-81 dBm, erst an ap3, dann an ap2.
|
||||
# Fund E ist damit WIEDER OFFEN.
|
||||
# Eingetragen wird hier trotzdem NICHTS, und zwar bewusst: ein signal-range-Boden
|
||||
# ist der invasivste der drei Hebel und kann Clients AUSSPERREN -- genau das war
|
||||
# 08-22 das Gegenargument (in den schwachen Raeumen gibt es keinen besseren AP,
|
||||
# auf den ein Boden steuern koennte). Erst kommen (1) `2g-probe-delay=yes` und
|
||||
# (2) `ft-over-ds=no`, jeder einzeln und als Transaktion, mit dem seit 2026-08-30
|
||||
# laufenden wireless-Logging als Messgrundlage. Siehe teilprojekte.md TP25 Fund E.
|
||||
# 🔴 Stand 2026-09-14 (Terrasse-In-situ-Session): der `signal-range`-Boden gegen
|
||||
# klebende Clients ist GEPRUEFT und GESCHEITERT -- `/interface wifi access-list`
|
||||
# hat kein `band`-Property (Band-Scoping ginge nur ueber cap-wifiN-Interface-Namen,
|
||||
# die bei jedem CAP-Rejoin wechseln), SSID-/MAC-Scope ohne Band träfe 2,4 GHz mit
|
||||
# (Lockout-Risiko, Schlafzimmer -84). Der Boden ist damit NICHT umsetzbar; der
|
||||
# Ersatz gegen die Call-Aussetzer ist `ft=yes ft-over-ds=yes` auf sec-main
|
||||
# (2026-09-14 zurueckgesetzt, s. docs/transaktionen/TP25-ft-yes-secmain.commands.rsc
|
||||
# und handoff-20260914-tp25-ap2-insitu-terrassse.md): Roams laufen als nahtlose
|
||||
# FT-Transition statt Voll-Reassoziation. Das Band-Springen selbst endet erst
|
||||
# mit dem Deckungsfix (TP25 Variante 3). Siehe teilprojekte.md TP25 (Stand 09-14).
|
||||
|
||||
# Kanonischer Mgmt-Nummernplan (User-Bestaetigung 2026-08-13, verbindlich):
|
||||
# core .99.1 | branch .99.2 | ap1 .99.11 | ap2 .99.12
|
||||
@@ -416,9 +424,20 @@
|
||||
/system ntp client servers add address=10.40.99.1
|
||||
/ip route add comment=TP21-default dst-address=0.0.0.0/0 gateway=10.40.99.1
|
||||
|
||||
# INPUT-FIREWALL (TP38, 2026-09-15) — deny-by-default fuer die Mgmt-Ebene (10.40.99.2).
|
||||
# Der Branch ist L2-only: ALLE Mgmt-Anfragen kommen auf der einen vlan99-SVI an, egal ob
|
||||
# VLAN10 (ueber den Core geroutet), cf-mesh (100.96.0.0/12) oder der OOB-Port (untagged
|
||||
# ether23, 10.40.99.x). Deshalb matcht die Quelle per src-address, nicht per in-interface.
|
||||
# Der src-Rahmen 10.40.0.0/16 + 100.96.0.0/12 spiegelt bewusst das `available-from` der
|
||||
# /ip service-Zeilen — kein neues Fenster, nur stateful + deny-by-default + WOULD-DROP-Log.
|
||||
{% for line in obj.get_config_context().get("firewall_filter", []) %}
|
||||
/ip firewall filter {{ line }}
|
||||
{% endfor %}
|
||||
|
||||
# L2-FABRIC — wie beim Core ein Literal-Block (Begruendung dort).
|
||||
# ether9-23 tragen pvid=20 OHNE VLAN-Membership (Bootstrap-Rev4-Rest, funktionslos) —
|
||||
# ether9-22 tragen pvid=20 OHNE VLAN-Membership (Bootstrap-Rev4-Rest, funktionslos) —
|
||||
# bewusst so abgebildet, damit eine spaetere Bereinigung als Drift sichtbar wird.
|
||||
# ether23 ist seit TP38 der OOB-MGMT-Port (untagged VLAN99), s. unten.
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=ether1
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=ether2
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=ether3 pvid=10
|
||||
@@ -427,9 +446,10 @@
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=ether6 pvid=40
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=ether7 pvid=20
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=ether8
|
||||
{% for n in range(9, 24) %}
|
||||
{% for n in range(9, 23) %}
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=ether{{ n }} pvid=20
|
||||
{% endfor %}
|
||||
/interface bridge port add bridge=bridge comment=TP38-OOB-MGMT frame-types=admit-only-untagged-and-priority-tagged interface=ether23 pvid=99
|
||||
/interface bridge port add bridge=bridge comment=defconf interface=ether24
|
||||
/interface bridge port add bridge=bridge comment=defconf disabled=yes interface=sfp-sfpplus1
|
||||
/interface bridge port add bridge=bridge comment=defconf disabled=yes interface=sfp-sfpplus2
|
||||
@@ -439,7 +459,7 @@
|
||||
/interface bridge vlan add bridge=bridge comment=MEDIA tagged=ether1,ether24,bridge untagged=ether5,ether6 vlan-ids=40
|
||||
/interface bridge vlan add bridge=bridge comment=UNTRUSTED tagged=ether1,ether24,bridge vlan-ids=50
|
||||
/interface bridge vlan add bridge=bridge comment=GUEST tagged=ether1,ether24,bridge vlan-ids=90
|
||||
/interface bridge vlan add bridge=bridge comment=MGMT tagged=ether1,ether24,bridge vlan-ids=99
|
||||
/interface bridge vlan add bridge=bridge comment=MGMT tagged=ether1,ether24,bridge untagged=ether23 vlan-ids=99
|
||||
{% elif obj.role.name == "Wireless AP" %}
|
||||
{% set ap = obj.get_config_context()["ap"] %}
|
||||
{% set mgmt_host = obj.primary_ip4.host %}
|
||||
|
||||
75
opencode.json
Normal file
75
opencode.json
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"mcp": {
|
||||
"home-assistant": {
|
||||
"type": "remote",
|
||||
"url": "{env:MCP_HOME_ASSISTANT_URL}",
|
||||
"enabled": false
|
||||
},
|
||||
"hostinger-api": {
|
||||
"type": "local",
|
||||
"command": [
|
||||
"npx",
|
||||
"-y",
|
||||
"hostinger-api-mcp"
|
||||
],
|
||||
"environment": {
|
||||
"HOSTINGER_API_TOKEN": "{env:MCP_HOSTINGER_API_TOKEN}"
|
||||
},
|
||||
"enabled": false
|
||||
},
|
||||
"mikromcp": {
|
||||
"type": "local",
|
||||
"command": [
|
||||
"npx",
|
||||
"-y",
|
||||
"mikromcp",
|
||||
"serve"
|
||||
],
|
||||
"environment": {
|
||||
"MIKROMCP_CONFIG_PATH": "/Users/christophemsenhuber/dev/bf-infra/mcp/mikromcp/config/routers.yaml",
|
||||
"MIKROMCP_DEFAULT_ROUTER": "crs326-core",
|
||||
"ROUTER_AP1_USER": "admin",
|
||||
"ROUTER_AP2_USER": "admin",
|
||||
"ROUTER_AP3_USER": "admin",
|
||||
"CRS326_CORE_USER": "admin",
|
||||
"CRS326_BRANCH_USER": "admin",
|
||||
"ROUTER_AP1_PASS": "{env:MCP_MIKROMCP_ROUTER_AP1_PASS}",
|
||||
"ROUTER_AP2_PASS": "{env:MCP_MIKROMCP_ROUTER_AP2_PASS}",
|
||||
"ROUTER_AP3_PASS": "{env:MCP_MIKROMCP_ROUTER_AP3_PASS}",
|
||||
"CRS326_CORE_PASS": "{env:MCP_MIKROMCP_CRS326_CORE_PASS}",
|
||||
"CRS326_BRANCH_PASS": "{env:MCP_MIKROMCP_CRS326_BRANCH_PASS}"
|
||||
},
|
||||
"enabled": false
|
||||
},
|
||||
"cloudflare": {
|
||||
"type": "remote",
|
||||
"url": "https://mcp.cloudflare.com/mcp",
|
||||
"enabled": true
|
||||
},
|
||||
"ollama": {
|
||||
"type": "local",
|
||||
"command": [
|
||||
"npx",
|
||||
"-y",
|
||||
"ollama-mcp"
|
||||
],
|
||||
"environment": {
|
||||
"OLLAMA_HOST": "http://127.0.0.1:11434"
|
||||
},
|
||||
"enabled": false
|
||||
},
|
||||
"pve-mcp": {
|
||||
"type": "remote",
|
||||
"url": "http://10.40.20.173:3000/",
|
||||
"enabled": true
|
||||
},
|
||||
"n8n-mcp": {
|
||||
"type": "remote",
|
||||
"url": "http://10.40.20.167:3001/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {env:N8N_MCP_BEARER}"
|
||||
},
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"instructions": ["CLAUDE.md"],
|
||||
"permission": "allow",
|
||||
"mcp": {
|
||||
"gitea-mcp": {
|
||||
"type": "remote",
|
||||
"url": "http://10.40.20.167:3000/mcp",
|
||||
"enabled": true
|
||||
},
|
||||
"mikromcp": {
|
||||
"type": "local",
|
||||
"command": ["npx", "-y", "mikromcp", "serve"],
|
||||
"environment": {
|
||||
"MIKROMCP_CONFIG_PATH": "/Users/christophemsenhuber/dev/bf-infra/mcp/mikromcp/config/routers.yaml",
|
||||
"MIKROMCP_DEFAULT_ROUTER": "ap1"
|
||||
},
|
||||
"enabled": true,
|
||||
"timeout": 30000
|
||||
},
|
||||
"pve-mcp": {
|
||||
"type": "remote",
|
||||
"url": "http://10.40.20.173:3000/",
|
||||
"enabled": true,
|
||||
"timeout": 15000
|
||||
},
|
||||
"home-assistant": {
|
||||
"type": "remote",
|
||||
"url": "http://10.40.20.105:9583/private_29X8x73taoNEq6gzmbVdyg",
|
||||
"enabled": true,
|
||||
"timeout": 15000
|
||||
},
|
||||
"cloudflare": {
|
||||
"type": "remote",
|
||||
"url": "https://mcp.cloudflare.com/mcp",
|
||||
"enabled": true,
|
||||
"timeout": 15000,
|
||||
"oauth": {}
|
||||
},
|
||||
"portainer": {
|
||||
"type": "local",
|
||||
"command": ["uvx", "--from", "mcp-portainer~=2.42.0", "mcp-portainer"],
|
||||
"environment": {
|
||||
"PORTAINER_URL": "https://10.40.20.126:9443",
|
||||
"PORTAINER_API_KEY": "{env:PORTAINER_API_KEY}",
|
||||
"PORTAINER_TLS_VERIFY": "0"
|
||||
},
|
||||
"enabled": true,
|
||||
"timeout": 15000
|
||||
},
|
||||
"shelly-mcp": {
|
||||
"type": "remote",
|
||||
"url": "http://10.40.20.180:3030/mcp",
|
||||
"headers": {},
|
||||
"enabled": true,
|
||||
"timeout": 15000
|
||||
}
|
||||
},
|
||||
"command": {
|
||||
"handoff": {
|
||||
"description": "Session-Übergabe generieren oder laden",
|
||||
"template": "Du bist das Handoff-Tool für das BF-Infra-Projekt.\n\n1. Ermittle, was zu tun ist:\n - Lese `docs/handoff-*.md` und finde die neueste Datei (nach Datum).\n - Wenn `$ARGUMENTS` \"resume\" oder einen Dateinamen enthält: lade die genannte oder neueste Handoff-Datei.\n - Wenn `$ARGUMENTS` leer ist oder \"generate\" enthält: generiere eine neue Handoff-Datei.\n\n2. Generieren (`/handoff`):\n - Lese `docs/teilprojekte.md` (Quick-Index-Block, Zeilen ~174-200) für den aktuellen TP-Status.\n - Prüfe offene Config-Transaktionen: `bash` mit `python3 nautobot/gc-transaktion.py status`.\n - Schreibe `docs/handoff-YYYYMMDD-thema.md` mit: Titel, Ausgangslage (was erledigt, was läuft), offene Schritte, Fallen/Gotchas, Einstieg für die nächste Session.\n - Sag dem User, welche Datei erstellt wurde.\n\n3. Laden (`/handoff resume`):\n - Lese die neueste Handoff-Datei vollständig.\n - Gib Zusammenfassung: Thema, Stand, offene Schritte.\n - Frage: \"Soll ich die Arbeit aus dieser Handoff-Datei fortsetzen?\"\n\nWichtig: Keine Secrets in die Handoff-Datei schreiben. Verweise auf existierende Doku statt zu duplizieren. Ziel < 200 Zeilen."
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user