Files
homelab-infra/docs/NETWORK_INVENTORY.md
T

267 lines
15 KiB
Markdown

# Network Inventory - KalliLab CORE
Status: Host-Audit erfasst; Router-Baseline und Portfreigaben-UI bereinigt; FRITZ!Box-Remote-Dienste aus; IPv6-Exposure technisch und per UI entschaerft; Tailscale-Inventar am 2026-06-05 real gemessen.
Letzte Pruefung: 2026-06-05 (Tailscale-Inventar), 2026-06-01 (Router/Ports)
## Zweck
Dieses Dokument beschreibt Router, DNS, Tailscale, Portfreigaben und Netztrennung. Es ergaenzt das Architektur-Zielbild in `HOMELAB_ARCHITECTURE_MASTER_V2.md` um konkrete Hardware- und Betriebswerte.
## Internet und Router
| Feld | Wert |
|---|---|
| Anschluss / Provider | DSL, Telekom |
| Bandbreite (FRITZ!Box-UI) | ca. 87,3 Mbit/s Download, ca. 36 Mbit/s Upload |
| Router-Modell | FRITZ!Box 7590 |
| Firmware | FRITZ!OS 8.25 (`154.08.25` per TR-064 am 2026-06-01) |
| Router-IP | 192.168.178.1 |
| DHCP-Server | FRITZ!Box (Standardannahme, Override durch Operator nicht dokumentiert) |
| Lokales Subnetz | 192.168.178.0/24 |
| IPv6 aktiv | Windows-Client hat Provider-IPv6; Host hat keine globale Provider-IPv6, nur Tailscale-ULA |
| DynDNS / DDNS | Cloudflare via `ddns-updater` (kein FRITZ!Box-DynDNS in Nutzung) |
| Heimnetz-Geraete (FRITZ!Box-UI) | 35 aktive Geraete |
| LAN-Ports belegt | LAN 1-4 verbunden |
| Telefonie / DECT | aktiv |
| USB an FRITZ!Box | nicht verbunden |
| Ausfallschutz (FRITZ!Box) | nicht eingerichtet (Mobilfunk-Stick-Failover nicht aktiv) |
### Beobachtungen
- Telekom-DSL ist Single-WAN; ohne Ausfallschutz ist Internet-Ausfall = kein DDNS-Update, keine ACME-Erneuerung, keine externen Push-Quellen.
- Upload 36 Mbit/s ist die effektive Obergrenze fuer Off-site-Backup-Geschwindigkeit nach Hetzner und fuer Plex-Remote-Streaming.
- FRITZ!OS ist am 2026-06-01 per TR-064 auf `154.08.25` beobachtet; FRITZ!Box-Konfig-Backup `Einstellungen_FRITZ.Box_7590_154.08.25_01.06.26_1318.export` wurde extern/off-system in Vaultwarden abgelegt.
- `Internet -> Freigaben -> FRITZ!Box-Dienste` ist am 2026-06-01 geprueft: Internetzugriff auf die FRITZ!Box per HTTPS ist aus, FTP/FTPS-Zugriff auf Speichermedien ist aus.
## DNS
| Komponente | Rolle | Adresse | Bemerkung |
|---|---|---|---|
| AdGuard Home | LAN DNS / Filter | Host `192.168.178.58`, Docker `172.23.0.3` | DNS auf Port 53; Admin soll nur via Tailscale-IP `100.80.98.33:8082` erreichbar sein |
| Unbound | Rekursiver Resolver | Docker `dns_net` | Upstream fuer AdGuard |
| Cloudflare | Authoritative DNS | extern | DNS-Challenge fuer TLS |
| Router | DHCP DNS-Verteilung | TBD | Muss auf AdGuard zeigen, falls so betrieben |
## Tailscale
Gemessen am 2026-06-05 per read-only SSH auf den Host (`tailscale status`,
`tailscale status --json`, `tailscale ip -4/-6`).
| Feld | Wert / Status |
|---|---|
| Node-Name | Kallilabcore |
| Tailnet / MagicDNS | `taild9fcf2.ts.net`; DNSName `kallilabcore.taild9fcf2.ts.net` |
| Tailscale IPv4 | `100.80.98.33` |
| Tailscale IPv6 | `fd7a:115c:a1e0::2c01:62b2` (gemessen 2026-06-05) |
| Exit Node | **Nein.** `Self.ExitNodeOption: false` und `Self.ExitNode: false` — Host bietet keinen Exit Node an und nutzt keinen. Entspricht dem Ziel (Operator-Zugang ist eingehend, nicht als Internet-Ausgang). |
| Subnet Router | **Ja, aktiv.** Host advertised und ist Primary fuer `192.168.178.0/24` (`Self.PrimaryRoutes: ["192.168.178.0/24"]`, ebenfalls in `AllowedIPs`). Das LAN ist also fuer das gesamte Tailnet ueber diesen Subnet-Router erreichbar — bewusst gemessener Ist-Zustand, **kein** "keine Route" wie zuvor vermutet. |
| ACL-Policy extern dokumentiert | **Operator-Entscheidung offen** — siehe eigener Block unten; durch den aktiven Subnet-Router ist die ACL-Frage sicherheitsrelevanter als zuvor angenommen. |
### Tailnet-Geraete (Snapshot 2026-06-05)
| Tailscale-IP | Node | OS | Status |
|---|---|---|---|
| `100.80.98.33` | kallilabcore | linux | aktiv (Host, Subnet-Router) |
| `100.78.133.37` | baerchen-1 | windows | aktiv (aktuelle Operator-Workstation, direct) |
| `100.105.203.21` | baerchen | windows | offline, zuletzt vor ~1 Tag gesehen (Alt-Node) |
| `100.73.83.55` | iphone-14 | iOS | bekannt |
| `100.112.0.90` | kallilab-core | linux | gelistet, kein aktiver Verkehr — **moeglicher Alt-/Dubletten-Node**, separat pruefen |
> Hygiene-Hinweis (kein Secret): Es existieren zwei linux-Nodes mit aehnlichem
> Namen (`kallilabcore` und `kallilab-core`) sowie zwei `baerchen`-Nodes
> (`baerchen-1` aktiv, `baerchen` offline). Bei Gelegenheit in der
> Tailscale-Admin-Konsole pruefen, ob die inaktiven Eintraege stillgelegt werden
> koennen. Das ist Aufraeumarbeit, kein akutes Risiko.
### Subnet-Router-Konsequenz
Weil `Kallilabcore` das LAN `192.168.178.0/24` als Subnet-Route anbietet, kann
**jedes** Tailnet-Geraet mit Zugriff auf diese Route potenziell LAN-Dienste auf
`192.168.178.0/24` erreichen — auch die Admin-Ports, die im LAN bewusst nur auf
die Tailscale-IP gebunden sind, sind ueber die Subnet-Route adressierbar. Genau
deshalb ist die ACL-Policy (unten) der eigentliche Schutzmechanismus und nicht
nur der LAN-Bind.
Pruefkommando (auf dem Unraid-Host, read-only):
```bash
tailscale status
tailscale status --json | jq '{exitNode: .Self.ExitNodeOption, primaryRoutes: .Self.PrimaryRoutes, allowedIPs: .Self.AllowedIPs}'
tailscale ip -4
tailscale ip -6
```
### ACL-Policy — Entwurf und Rollout-Plan (Stand 2026-06-05, NICHT angewendet)
Die Tailnet-ACL wird in der Tailscale-Admin-Konsole unter `Access controls`
verwaltet (kein Wert/Secret gehoert ins Repo). Aktueller Live-Stand ist
Default-Allow (`src: ["*"] -> dst: ["*:*"]`), d. h. jedes Tailnet-Geraet darf
alles inklusive der LAN-Subnet-Route.
**Abgestimmte Richtung (Operator-Entscheidungen 2026-06-05):**
- Ziel ist eine restriktivere, Tag-basierte ACL.
- Single-User-Realitaet: aktuell gehoeren alle Nodes demselben User
`michaelkaleschke@`. Eine Differenzierung Operator/Familie ist nur ueber
**Tags** moeglich. Tagging aendert Ownership/Key-Expiry und erfordert je Geraet
Re-Auth — deshalb bewusst ein eigener, spaeterer Schritt.
- **Heute bewusst nur Sichtung + Entwurf, kein Tagging, keine Anwendung.**
- Familiengeraete brauchen Tailnet-Zugriff auf **bestimmte** Dienste (welche
genau, ist noch zu konkretisieren) — `tag:family` bekommt gezielte `dst`-Regeln.
- `iphone-14` ist ein Operator-Geraet und faellt unter `tag:operator`.
**Geraete -> Tag (fuer den spaeteren Tagging-Schritt):**
| Tag | Geraete |
|---|---|
| `tag:server` | `kallilabcore` (Host, Subnet-Router) |
| `tag:operator` | `baerchen-1`, `iphone-14` |
| `tag:family` | kuenftige Familiengeraete |
**Entwurf (Vorschlag, noch nicht in der Konsole gespeichert):**
```json
{
"tagOwners": {
"tag:server": ["autogroup:admin"],
"tag:operator": ["autogroup:admin"],
"tag:family": ["autogroup:admin"]
},
"autoApprovers": {
"routes": { "192.168.178.0/24": ["tag:server"] }
},
"acls": [
{ "action": "accept", "src": ["tag:operator"], "dst": ["*:*"] },
{ "action": "accept", "src": ["tag:server"], "dst": ["tag:operator:*"] },
{ "action": "accept", "src": ["tag:family"], "dst": ["100.80.98.33:443"] }
],
"ssh": [
{ "action": "accept", "src": ["tag:operator"], "dst": ["tag:server"],
"users": ["root", "autogroup:nonroot"] }
]
}
```
> Die `tag:family`-`dst` `100.80.98.33:443` ist ein **Platzhalter** und wird
> durch die real benoetigten Familien-Dienste ersetzt, sobald diese feststehen.
**Lockout-sichere Reihenfolge (wenn die Umsetzung freigegeben wird):**
1. `tagOwners` + `autoApprovers` + neue ACL-Regeln speichern, **Allow-all-Regel
zunaechst behalten**.
2. Geraete taggen (`baerchen-1`, `iphone-14` -> operator; `kallilabcore` ->
server) und je Geraet die Verbindung verifizieren.
3. Subnet-Route bleibt approved (jetzt via `autoApprovers`/`tag:server`).
4. **Erst zuletzt** die Allow-all-Regel entfernen -> restriktiv schalten.
5. Sofort Smoke-Tests fahren (siehe unten).
**Smoke-Tests nach Anwendung:**
- `baerchen-1` erreicht Host: `ping 100.80.98.33`, `ssh kallilabcore hostname` (read-only).
- `baerchen-1` erreicht LAN ueber Route: z. B. AdGuard-Admin `http://100.80.98.33:8082`, `curl -kI https://192.168.178.58`.
- Falls testbar: ein nicht-Operator-Geraet erreicht Route/Admin-Ports **nicht** mehr.
- Host-Gegencheck: `tailscale status` zeigt alle Soll-Peers weiter verbunden.
**Noch offene Eingaben vor Finalisierung:**
1. Aktueller ACL-JSON aus der Admin-Konsole (read-only gesichtet, nur Struktur dokumentiert).
2. Konkrete Liste der Dienste/Ports, die Familiengeraete ueber Tailscale brauchen.
## Portfreigaben und Exposure
### FRITZ!Box (WAN -> Host)
Aktiver Soll-Stand nach Operator-Bereinigung und UI-Gegencheck 2026-06-01:
| Aktive Freigabe | Ziel | Zweck | Bemerkung |
|---|---|---|---|
| `443/tcp` -> `192.168.178.58:443` | Traefik HTTPS | einziger Public-HTTPS-Einstieg, Wildcard-Cert via Cloudflare-DNS-Challenge | bleibt |
Bewusst **nicht** freigegeben:
| Port | Begruendung |
|---|---|
| `80/tcp` | Cloudflare-DNS-Challenge ersetzt HTTP-01; Traefik macht HTTP->HTTPS-Redirect nur LAN-seitig; WAN-`80` waere zusaetzliche Angriffsflaeche ohne Funktionsnutzen. **2026-05-28 in FRITZ!Box-UI entfernt**, Validierung: Mobilfunk-Test ergibt Timeout auf `http://vault.kaleschke.info`, `https://...` weiter erreichbar. |
| `222/tcp` (Gitea SSH) | bewusst Tailscale-only: Operator-Pfad ist Tailscale, GitHub-Mirror deckt DR-Bootstrap ab, Gitea-Bundles sind off-host. Externe SSH-Brute-Force-Vektoren vermeiden. |
### UPnP / Selbstständige Portfreigaben
| Geraet | UPnP-Selbstfreigabe-Recht | Begruendung |
|---|---|---|
| `Kallilabcore` (192.168.178.58) | nicht erlaubt | Repo-managed; alle benoetigten Public-Ports sind explizite Freigaben |
| `PC-192-168-178-71` / VONETS-Adapter (192.168.178.71, MAC 00:17:13:2F:61:96) | **2026-06-01 erneut geprueft und deaktiviert** | wahrscheinlich VONETS-WiFi-Bridge fuer SolarEdge-Wechselrichter; SolarEdge-Cloud-Sync ist ausschliesslich outbound, eingehende Ports sind nicht erforderlich |
Sollten neue Geraete UPnP-Selbstfreigaben anfordern, wird das hier als bewusste Ausnahme dokumentiert oder pro Geraet wieder deaktiviert.
Historischer UI-Befund vor Bereinigung vom 2026-05-27 (`Internet -> Freigaben -> Kallilabcore`):
| Beobachtung | Bewertung |
|---|---|
| `HTTP-Server`, TCP, extern `80/tcp` auf `192.168.178.58` | war Abweichung; **2026-05-28 entfernt** |
| `HTTPS-Server`, TCP, extern `443/tcp` auf `192.168.178.58` | entspricht Repo-Soll |
| Keine `222/tcp`-Freigabe sichtbar | entspricht seit 2026-05-28 dem Soll: Gitea-SSH bleibt Tailscale-only |
| Kallilabcore: keine selbststaendige Portfreigabe, kein IPv4-/IPv6-Exposed-Host sichtbar | entspricht Sicherheitsziel |
| `PC-192-168-178-71`: selbststaendige Portfreigabe erlaubt, `0 aktiv` | **2026-06-01 deaktiviert**; danach nur noch `Kallilabcore` in der Portfreigabenliste sichtbar |
### Host (lokal beobachtbar)
| Port | Ziel | Zweck | Bewertung |
|---:|---|---|---|
| 80/tcp | Traefik | HTTP->HTTPS / ACME | nur LAN, keine WAN-Freigabe noetig |
| 443/tcp | Traefik | HTTPS | WAN-Freigabe in FRITZ!Box erwartet |
| 222/tcp | Gitea SSH | Git SSH | nur LAN/Tailscale; keine WAN-Freigabe |
| 53/tcp+udp | AdGuard | DNS | LAN-only, dokumentierte Ausnahme |
| 8082/tcp | AdGuard Admin | Admin UI | Bind nur `100.80.98.33:8082` (Tailscale), nicht im LAN exponiert |
| 8181/tcp | InfluxDB 3 Core | Home Assistant / Ecowitt Writer | 2026-05-31 effektiv nur `127.0.0.1:8181`, nicht LAN-exponiert |
Pruefkommando:
```bash
ss -ltnp | sort -k4
docker ps --format "{{.Names}}: {{.Ports}}" | sort
```
## Netztrennung
| Netz | Status | Bemerkung |
|---|---|---|
| LAN | 192.168.178.0/24 | Hauptnetz, Host `192.168.178.58`, FRITZ!Box meldet 35 aktive Geraete |
| WLAN 2,4 / 5 GHz | aktiv, SSID `Fritzi` | Standard-WLAN, im LAN-Adressbereich, kein eigener Adressraum |
| Gast-WLAN | **inaktiv** (FRITZ!Box-UI) | Solange inaktiv: kein Gast-Pfad zu LAN-Diensten; AdGuard-Admin-Trennung primaer ueber Tailscale-Bind statt Netzsegmentierung |
| IoT-Netz | nicht existent | Keine VLAN-Trennung dokumentiert |
| Tailscale | aktiv | Operator-Zugang, Host-IP `100.80.98.33` |
| VLANs | nicht in Nutzung | FRITZ!Box 7590 kann VLAN-Tagging an einzelnen LAN-Ports; aktuell nicht konfiguriert |
## Docker-Netze
Authoritativ ist `HOMELAB_ARCHITECTURE_MASTER_V2.md`. Dieses Inventar haelt nur den Laufzeit-Snapshot fest.
| Docker-Netz | Zweck | Erwartung |
|---|---|---|
| frontend_net | Traefik/Web | external bridge |
| backend_net | DB/Cache intern | internal bridge |
| dns_net | AdGuard/Unbound | bridge |
| monitoring_net | Observability | compose-intern |
| app-interne Netze | Stack-isoliert | nur wenn technisch noetig |
Pruefkommando:
```bash
docker network ls
docker network inspect frontend_net | jq '.[0].Containers | keys'
docker network inspect backend_net | jq '.[0].Internal'
```
## Offene Entscheidungen
| Thema | Status | Naechster Schritt |
|---|---|---|
| AdGuard Admin nur via Tailscale | live validiert 2026-05-26 | Compose bindet Admin-Port auf `100.80.98.33:8082`; DNS auf Port 53 funktioniert, LAN-Zugriff auf `192.168.178.58:8082` schlaegt fehl |
| FRITZ!Box-Portfreigaben mit Repo-Soll abgleichen | **erledigt 2026-06-01** | Bereinigt: `80/tcp` entfernt (Cloudflare-DNS-Challenge ersetzt HTTP-01; Mobilfunk-Test bestaetigt Timeout auf `http://`, `https://` weiter ok). `222/tcp` bleibt bewusst nicht eingerichtet (Tailscale-only-Linie). UPnP-Selbstfreigaben sind aus. Aktiver Soll-Stand: ausschliesslich `443/tcp -> 192.168.178.58`. |
| FRITZ!Box-Dienste aus dem Internet | **erledigt 2026-06-01** | `Internet -> Freigaben -> FRITZ!Box-Dienste`: HTTPS-Zugriff auf die FRITZ!Box aus dem Internet aus; FTP/FTPS auf Speichermedien aus. |
| FRITZ!OS Update und Konfig-Backup | **erledigt 2026-06-01** | TR-064 meldet `154.08.25`; Konfig-Export liegt extern/off-system in Vaultwarden, Kennwort und Datei bleiben ausserhalb des Repos. |
| Gast-/IoT-Zugriff auf Admin-Ports | **Entscheidungspunkt: kein Gast-/IoT-Netz aktivieren, solange nicht gebraucht** | Aktuell entschaerft, weil Gast-WLAN inaktiv ist und kein IoT-VLAN existiert. Risiko entsteht erst bei Aktivierung. Harte Vorbedingung fuer eine spaetere Aktivierung: **vor** dem Einschalten von Gast-WLAN/IoT muessen `192.168.178.58:8082` (AdGuard-Admin, ohnehin Tailscale-gebunden), `192.168.178.58:8181` (InfluxDB, bereits `127.0.0.1`-bound) und alle weiteren LAN-Admin-Ports per FRITZ!Box-Netzwerkfilter/Kindersicherung gegen das Gastsegment gesperrt sein. Bis dahin bewusst kein Gastnetz. |
| IPv6 Exposure | technisch und per UI entschaerft | Public DNS liefert keine AAAA-Records fuer `*.kaleschke.info`; Host hat keine globale Provider-IPv6. TR-064 meldet IPv6-Firewall aktiv und Pinholes grundsaetzlich erlaubt; FRITZ!Box-UI zeigt keine aktiven IPv6-Freigaben, keine Admin-/SSH-Freigaben. |
| WAN-Ausfallschutz | **geparkt: spaeter evaluieren** (Operator-Entscheidung 2026-06-05) | Mobilfunk-Stick-Failover an FRITZ!Box bleibt vorerst inaktiv. Folgen sind bewusst akzeptiert: Internet-Ausfall = ACME/DDNS pausieren, lokale Apps laufen weiter. Review-Trigger: haeufigere oder laengere DSL-Ausfaelle, oder wenn externer Remote-Zugang (statt nur lokalem Betrieb) geschaeftskritisch wird. Erst dann Mobilfunk-Failover technisch bewerten. |
| Home Assistant InfluxDB Bind | validiert 2026-05-31 | `docker-proxy` bindet `127.0.0.1:8181`; keine LAN-Exposure. Wenn Home Assistant nicht lokal auf dem Host schreibt, braucht das eine bewusste Bind-Aenderung. |