Files
bf-infra/docs/tp5-deny-by-default-runbook.md
Christoph Emsenhuber f31172e4d9 TP5-Runbook: D3 entschieden (ICMP-Sweep = lanscan.app, gehoert in die JIT-Gruppe)
Der Dauersweep von .10.82 auf alle Shellys ist lanscan.app — ein Ad-hoc-Scan vom
Arbeitsplatz, kein Dienst. Also keine permanente MAIN->IOT-ICMP-Regel, sondern
Teil der selbstverfallenden JIT-Admin-Gruppe (deckt sich mit D4).

Hinweis fuer den Log-Lauf ergaenzt: der Scan erzeugt sonst Rauschen in Etappe 1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 16:38:29 +02:00

175 lines
9.8 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.
# TP5 — Deny-by-default auf `crs326-core` · Session-Runbook
> **Stand der Vorbereitung: 2026-08-14** (Live-Erhebung auf `crs326-core` via MikroMCP).
> **Status: vorbereitet, nicht ausgeführt.** Diese Datei ist der Einstieg für die TP5-Session —
> kanonischer Scope bleibt `docs/teilprojekte.md` → TP5.
---
## 0. Worum es geht (in einem Absatz)
Die `forward`-Kette auf dem Core endet heute **ohne Drop**: alles, was nicht von einer der 6 TP5-Hole-Regeln
erfasst wird, läuft trotzdem durch. Die VLAN-Segmentierung ist damit **dokumentiert, aber nicht durchgesetzt**.
TP5 schließt genau diese eine Lücke — plus die Whitelists, die es dafür braucht. Es ist der letzte Schritt
vor TP6 (CAKE), dem eigentlichen Projektziel.
**Das Risiko ist asymmetrisch:** ein zu früh gesetzter Drop nimmt DHCP, DNS, Mgmt und das halbe Smart-Home
gleichzeitig mit — und zwar auch den Pfad, über den man den Fehler zurücknehmen wollte. Deshalb ist unten
**Etappe 1 ein Log-Lauf ohne jede Blockierung.** Wer direkt zum Drop springt, arbeitet blind.
---
## 1. Ist-Stand (live erhoben 2026-08-14, `crs326-core`)
### 1.1 `forward` — 13 Regeln, kein abschließender Drop
| # | Aktion | Bedeutung |
|---|---|---|
| 1 | accept `established,related,untracked` | defconf |
| 2 | fasttrack `established,related` | defconf (`hw-offload=true`) |
| 3 | drop `invalid` | defconf |
| 4 | drop in-list=WAN `!dstnat` | defconf |
| 5–6 | accept in/out `wg-hub` | TP10 (FM/DW-Spokes) |
| 7–8 | accept `vlan10↔vlan40` | TP5: MAIN↔MEDIA |
| 9–10 | accept `vlan20↔vlan40` | TP5: INFRA↔MEDIA |
| 11–12 | accept `vlan90↔vlan40` | TP5: GUEST↔MEDIA |
| — | **(nichts)** | ⬅️ **hier fehlt der Deny-by-default** |
### 1.2 `input` — 12 Regeln, LAN pauschal offen
TP10-Seal komplett (`est` · `inv` · `dhcp` · `icmp` · **`lan`** · `wandrop`) + WG-Listen 51821 + 5× mDNS.
⚠️ **`TP10-seal-lan` (`in-interface-list=LAN`, accept) nimmt jeden LAN-Input an** — inkl. VLAN99-Mgmt,
VLAN90-Guest und VLAN50. Die 5 `TP5: mDNS in vlanXX`-Regeln stehen **dahinter** und zählen daher
**0 Pakete** (seal-lan: 3,5 Mio.). Sie sind nicht kaputt, nur noch nicht dran.
### 1.3 NAT + Interface-Listen
- `srcnat`: `accept dst-address=10.40.0.0/16` (**no-NAT inter-VLAN, steht vor masquerade**) → `masquerade out-list=WAN`.
- `WAN` = `vlan100` · `LAN` = `vlan10,20,30,40,50,90,99` (**vlan99 ist Mitglied von LAN** — relevant für 1.2 und für D4).
---
## 2. Was heute real über VLAN-Grenzen läuft
Erhoben aus `/ip/firewall/connection` (Momentaufnahme) + den kumulativen Regel-Countern.
⚠️ **Beides zusammen lesen:** conntrack zeigt nur, was *gerade* offen ist; die Counter zeigen, was *jemals* lief.
Beispiel: `INFRA→MEDIA` hat 178.142 Pakete auf dem Zähler, stand aber im Snapshot auf 0 Verbindungen.
| Richtung | Snapshot | Was genau |
|---|---|---|
| **v20 → v30** | 24 | **HA (`.20.105`) pollt 22 Shellys auf `tcp/80`** + `.30.137:6638` |
| **v10 → v30** | 224 | **223× ICMP von `.10.82` („Mac") auf alle Shellys** + 1× udp/3722 |
| **v10 → v20** | 10 | `.10.82`/`.10.183` → NAS `.20.10:6690` (Synology Drive), `.20.173:3000` (pve-mcp), `.20.167:49152` |
| **v20 → v10** | 4 | Mac mini `.20.167` ↔ iPad `.10.180` udp/3722; HA → `.10.6:161` (SNMP) |
| **v30 → v20** | 3 | `.30.249` → **HA-API `.20.105:8123`**; udp/5540 (Matter) → HA; `.30.201` → `.20.167:49152` |
| **v30 → v10** | 4 | Rückrichtungen zu `.10.82`/`.10.180`/`.10.183` (ephemere Ports) |
| **v10 → v99** | 1 | `.10.82` → `core .99.1` **tcp/22 + tcp/80** (= Mgmt-Zugriff) |
| **v40 → \*** | 0 | MEDIA initiiert nichts nach außerhalb |
| **v50 / v90** | 0 | **komplett leer — Internet-only-Pinning ist hier risikofrei** |
### 2.1 Drei Funde, die vor dem Drop eine Entscheidung brauchen
1. 📱 **Ein iPhone sitzt in VLAN30 (IOT):** `10.40.30.201`, Hostname `iPhone`, und es spricht mit dem
Mac mini (`udp/3722`, Apple-Continuity-Muster). Entweder hat sich jemand bewusst ins `dirtyvader-iot`-SSID
gehängt, oder das ist ein Ausrutscher. **Ein IOT-Deny trennt dieses Gerät** — vorher klären, nicht danach.
2. ✅ **`.10.82` („Mac") pingt alle ~30 Shellys — GEKLÄRT (User 2026-08-14): das ist `lanscan.app`**, also
ein Ad-hoc-Scan vom eigenen Arbeitsplatz, kein Dauerdienst. **Konsequenz: keine permanente
MAIN→IOT-ICMP-Regel bauen** — der Scan gehört in die **JIT-Admin-Gruppe** (address-list mit
`timeout`, s. §3/D3). Beim Log-Lauf erzeugt er sonst viel Rauschen: entweder während Etappe 1
nicht scannen, oder die Treffer beim Auswerten bewusst ausfiltern.
3. 🔑 **VLAN99 ist Mitglied der `LAN`-Liste** → `TP10-seal-lan` erlaubt Mgmt-Input aus *jedem* VLAN.
„MGMT isolieren" (TP5-Ziel) heißt also: `seal-lan` verengen — das ist derselbe Griff, der die
5 mDNS-Regeln scharf schaltet. **Beides passiert zusammen oder gar nicht.**
---
## 3. Offene Entscheidungen (vor der Session klären)
| # | Frage | Vorschlag |
|---|---|---|
| **D1** | MAIN→INFRA: welche Dienste? | Beobachtet: NAS `6690`, pve-mcp `3000`, macmini `49152`, `3722`. Vorschlag: **erst mit dem Log-Lauf (Etappe 1) vervollständigen**, dann Whitelist — nicht jetzt raten. |
| **D2** | iPhone `.30.201` in IOT | Ins MAIN-SSID holen (sauber) **oder** bewusst als Ausnahme dulden. Empfehlung: umhängen. |
| **D3** | ~~ICMP-Sweep `.10.82`→IOT~~ | ✅ **ENTSCHIEDEN (2026-08-14): `lanscan.app`, Ad-hoc vom Arbeitsplatz.** Keine Dauerregel — läuft über die **JIT-Admin-Gruppe** (selbstverfallend). Deckt sich mit D4. |
| **D4** | Wer darf auf VLAN99-Mgmt? | Vorschlag: nur MAIN (`vlan10`), Rest drop. `seal-lan` entsprechend verengen. |
| **D5** | IOT→INFRA-Whitelist | Doku nennt MQTT 1883/8883, HA-API, Influx 8086. Beobachtet real: **`8123` (HA), `5540/udp` (Matter)**. Vorschlag: die beobachteten + MQTT. |
| **D6** | UNTRUSTED/GUEST | Beide tragen **null** Inter-VLAN-Verkehr → Internet-only sofort und gefahrlos pinnbar. |
---
## 4. Umsetzung in 4 Etappen
> **Governance (TP22):** alles über **Nautobot Golden Config**, `plan_type=manual`, feature-scoped —
> **kein** Direkt-Write, **kein** „full intended" (Regel 1: `<<REDACTED>>`-Sektionen nie pushen).
> Vor **jedem** Push `/system backup` auf dem Core (Regel 3). Und: **nur die Gegenprüfung am Gerät zählt**,
> Job- und Plan-Status sind kein Wirksamkeitsnachweis (zweimal belegt, TP21.1/TP22).
### Etappe 1 — Log-Lauf (blockiert nichts, Dauer: einige Tage)
Eine einzige Regel **ans Ende von `forward`**, `action=log` statt `drop`:
```
/ip firewall filter add chain=forward action=log log-prefix="TP5-WOULD-DROP" comment="TP5: log-only, Vorstufe zum deny-by-default"
```
Das protokolliert exakt die Pakete, die der spätere Drop treffen würde — inklusive der Dinge, an die
niemand denkt (Drucker-Discovery, Backup-Jobs, ein Gerät, das nur einmal pro Woche funkt). **Diese Liste
ist die Whitelist**, nicht eine am Schreibtisch ausgedachte. Danach D1/D3/D5 final beantworten.
⚠️ Log-Ziel vorher setzen (`/system logging`), sonst läuft nur der Speicher-Ringpuffer mit.
### Etappe 2 — Whitelists bauen (noch immer ohne Drop)
Die aus Etappe 1 abgeleiteten Regeln **vor** der Log-Regel einfügen: MAIN→INFRA (D1), IOT→INFRA (D5),
ggf. MAIN→IOT-ICMP (D3). Danach muss die Log-Regel **verstummen** — solange sie noch Nutzverkehr sieht,
ist die Whitelist unvollständig. **Das ist das Abbruchkriterium für Etappe 3.**
### Etappe 3 — Drop scharf schalten
`action=log` → `action=drop` (bzw. Log behalten und Drop dahinter). **Erst wenn Etappe 2 still ist.**
🛟 **Sicherung — auf dem Core möglich, anders als auf den hAPs:** `crs326-core` läuft **nicht** in
`device-mode=home`, also stehen `scheduler` und `fetch` zur Verfügung. Vor dem Drop einen Auto-Revert
scharfstellen, der die Regel nach n Minuten selbst wieder abschaltet, wenn niemand ihn abbestellt:
```
/system scheduler add name=tp5-autorevert interval=10m on-event="/ip firewall filter set [find comment~\"TP5: deny-by-default\"] disabled=yes; /system scheduler remove tp5-autorevert"
```
Läuft alles sauber → Scheduler manuell entfernen. Läuft es nicht → das Netz heilt sich in ≤10 Minuten selbst.
**Diese Absicherung gibt es auf ap1/ap2 nicht** — dort ist sie durch `device-mode=home` blockiert (TP22-Regel 2).
### Etappe 4 — UNTRUSTED/GUEST + MGMT (D4/D6)
`vlan50`/`vlan90` auf Internet-only pinnen (risikofrei, s. §2), `seal-lan` auf MAIN verengen → MGMT isoliert,
und als Nebeneffekt werden die 5 mDNS-`input`-Regeln endlich wirksam.
---
## 5. Verifikation (nach jeder Etappe, immer am Gerät)
1. `list_firewall_rules` chain=forward/input → Regel existiert, `disabled=false`, Kommentar korrekt.
2. **Funktionstest quer durchs Haus:** Sonos aus MAIN steuern · HA erreicht die Shellys (`v20→v30:80`) ·
Shelly meldet an HA (`v30→v20:8123`) · NAS-Zugriff aus MAIN (`6690`) · Drucker · AirPlay/Cast ·
Gast-WLAN kommt ins Internet und **sonst nirgendwohin**.
3. Counter der neuen Regeln lesen — eine Drop-Regel, die *gar nichts* zählt, ist genauso verdächtig wie
eine, die zu viel zählt.
4. Nach der Geräteänderung: **Backup → Intended → Compliance** in dieser Reihenfolge
(GC vergleicht gegen das letzte Backup, nicht gegen das Live-Gerät — TP22-Falle).
## 6. Rollback
- Sofort: `disabled=yes` auf der Drop-Regel (bzw. Auto-Revert greift von selbst).
- Ganz zurück: `/system backup` von vor der Session einspielen.
- 🚨 Wenn der Mgmt-Pfad weg ist: Rettung ist der **Kabelweg**, nicht WLAN. `crs326-core` steht in
Technik UG; VLAN10-Fallback `10.40.10.1` existiert zusätzlich zu `.99.1`.
- ⚠️ **WARP-Falle:** „Ping auf alles tot, TCP geht" ist **kein** Firewall-Befund, sondern ein aktiver
WARP-Client. Vor jeder Firewall-Fehlersuche zuerst WARP trennen (`ref_warp_local_icmp_trap`).
---
## 7. Anschluss
**TP5.1** (DNS-Redirect + Torch für Low-Trust) hängt am UNTRUSTED-Pinning aus Etappe 4.
Danach ist der Weg frei für **TP6 — CAKE**, das Projektziel.