From d3eb8099a3696bb2428a2026ad91f0af89d0de66 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Sat, 18 Jul 2026 10:46:53 +0200 Subject: [PATCH] =?UTF-8?q?spike(R-6):=20S4b=20name-resolution=20finding?= =?UTF-8?q?=20=E2=80=94=20wsdd=20visible=20but=20flat=20name=20unresolvabl?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Human Explorer leg exposed the split: FELHOM-SPIKE renders (WSD PASS) but the double-click fails 0x80070035 — flat name resolves by no path (DNS/LLMNR/NetBIOS all silent; disable netbios=yes). By-IP mount works => SMB is healthy, the gap is name resolution. Fix verified live: adding nmbd (NetBIOS) => nbtstat lists FELHOM-SPIKE, ping resolves, \FELHOM-SPIKE\spike-share mounts by name. R-7 must ship smbd+wsdd+nmbd (+avahi/.local), not wsdd alone. --- .../audits/SPIKE-lan-discovery-2026-07-18.md | 105 ++++++++++++++---- documentation/backlog/ROADMAP.md | 4 +- 2 files changed, 86 insertions(+), 23 deletions(-) diff --git a/documentation/audits/SPIKE-lan-discovery-2026-07-18.md b/documentation/audits/SPIKE-lan-discovery-2026-07-18.md index 8daa408..7bca810 100644 --- a/documentation/audits/SPIKE-lan-discovery-2026-07-18.md +++ b/documentation/audits/SPIKE-lan-discovery-2026-07-18.md @@ -41,13 +41,18 @@ container). Docker's default bridge cannot receive LAN multicast at all**, so WS are dead there while a published unicast port still works. Empirically, guest-netns (S1) and host-network (S2) are byte-for-byte equivalent and pass SSDP/mDNS/WSD in **both** directions; the default bridge (S3) fails multicast RX for all three. A real **samba + wsdd** stack on host-network -is discovered by Windows 11 (ProbeMatch confirmed), answers on TCP 445, and serves an authenticated -read/write SMB round-trip. A real **SSDP `MediaServer:1`** advertisement from host-network is received -by both LAN clients. **Recommendation for R-7: run the samba/wsdd stack as a host-network infra -stack, LAN-bound.** For R-8: Jellyfin's built-in DLNA is physically viable on this topology **if it -runs host-network**. One caveat R-7/R-8 must carry: `vmbr0` runs with `multicast_snooping=1` and no -STP — it worked here because the household router (.1) is an active IGMP querier, but a customer LAN -with snooping-on-and-no-querier could prune the groups (§7d). +is discovered by Windows 11 (ProbeMatch confirmed + **FELHOM-SPIKE renders in Explorer**), answers on TCP +445, and serves an authenticated read/write SMB round-trip. A real **SSDP `MediaServer:1`** +advertisement from host-network is received by both LAN clients. **But the human leg exposed a second +requirement wsdd alone does not meet (S4b):** the Explorer *double-click* on FELHOM-SPIKE failed with +`0x80070035` because the flat name resolved by no path — WSD gives visibility, not name resolution. +Adding **nmbd (NetBIOS name service)** fixed it live (`\\FELHOM-SPIKE` then resolves and mounts). +**Recommendation for R-7: run the stack host-network, LAN-bound — `smbd` + `wsdd` (visibility) + +`nmbd` (flat-name resolution), and ideally `avahi`/`.local` for modern clients.** For R-8: Jellyfin's +built-in DLNA is physically viable on this topology **if it runs host-network**. One caveat R-7/R-8 +must carry: `vmbr0` runs with `multicast_snooping=1` and no STP — it worked here because the household +router (.1) is an active IGMP querier, but a customer LAN with snooping-on-and-no-querier could prune +the groups (§7d). --- @@ -141,7 +146,7 @@ Throwaway host-network stack in the guest: `spike-samba` (alpine + `apk add samb | 1. WS-Discovery ProbeMatch | scripted Probe (`Types=wsdp:Device`) from the workstation | **PASS** — ProbeMatch from `192.168.0.127`; wsdd logged our exact `MessageID` from `192.168.0.110` | | 2. Port 445 reachability | `Test-NetConnection 192.168.0.127 -Port 445` | **PASS** — `TcpTestSucceeded: True` | | 3. SMB round-trip | `New-SmbMapping` as `spikeuser` → write `roundtrip.txt` → read back → byte-compare | **PASS** — `BYTE-COMPARE: PASS`; dir listed `README.txt` (24B) + `roundtrip.txt` (28B) | -| 4. Explorer Network view (human) | Viktor: Explorer → Network shows **FELHOM-SPIKE**, double-click opens the share | **PENDING — human leg; stack left live** | +| 4. Explorer Network view (human) | Viktor: Explorer → Network | **SPLIT: device VISIBLE (WSD PASS), double-click FAILED `0x80070035`** — see S4b | wsdd log for leg 1: ``` @@ -151,8 +156,58 @@ wsdd log for leg 1: The scripted client's friendly-name auto-fetch reported FAIL only because python-wsdd's metadata HTTP endpoint (`:5357//`) requires the native WS-Discovery **Resolve→Transfer/Get** handshake that Windows Explorer performs itself (a direct throwaway `Get` 404s). The **objective discovery gate -is the ProbeMatch (PASS)**; the `FELHOM-SPIKE` name is what wsdd is configured to present and is the -subject of the human leg. Optional S4.5 (mDNS `.local` name + phone) was **skipped**. +is the ProbeMatch (PASS)**; the `FELHOM-SPIKE` name is what wsdd is configured to present. Optional +S4.5 (mDNS `.local` name + phone) was **skipped**. + +## S4b — the Explorer double-click failure (THE sharpest R-7 finding) + +Viktor's human leg surfaced a split result Windows-side that the by-IP scripted tests had masked: + +- **Visibility: PASS.** Explorer → Network → **Computer** renders **`FELHOM-SPIKE`** (wsdd/WSD works + as a discovery beacon — screenshot on file). +- **Double-click: FAIL** → `Windows cannot access \\FELHOM-SPIKE` · **`0x80070035` "network path + not found."** + +Diagnosis from the workstation (192.168.0.110) isolates the cause as **flat-name resolution, not +SMB**: + +| Check | Result | +|---|---| +| `Test-NetConnection 192.168.0.127 -Port 445` + `New-SmbMapping \\192.168.0.127\spike-share` | **PASS** — mounts by IP, lists files. SMB/auth/445 are fine. | +| `Resolve-DnsName FELHOM-SPIKE` (DNS) | fail — "DNS name does not exist" | +| `Resolve-DnsName FELHOM-SPIKE -LlmnrNetbiosOnly` | fail — timeout (nobody answers LLMNR) | +| `ping FELHOM-SPIKE` | "could not find host" | +| `nbtstat -A 192.168.0.127` | "Host not found" — no NetBIOS name service (`disable netbios=yes`) | + +**Root cause:** WSD hands Explorer a device *icon* named FELHOM-SPIKE, but the double-click issues a +plain UNC `\\FELHOM-SPIKE`, whose flat name Windows must resolve via DNS → LLMNR → NetBIOS. With +`disable netbios=yes` and no mDNS/LLMNR responder, **nothing answers** → `0x80070035`. Mounting by IP +bypasses all name resolution and works — proving the SMB server itself is healthy. + +**Fix verified live (S4b relaunch: samba with `disable netbios=no` + `nmbd`):** + +| Check (after nmbd) | Result | +|---|---| +| `nbtstat -A 192.168.0.127` | **`FELHOM-SPIKE <00>/<03>/<20> Registered`** | +| `ping FELHOM-SPIKE` | **`Reply from 192.168.0.127`** — flat name resolves via NetBIOS broadcast | +| `New-SmbMapping \\FELHOM-SPIKE\spike-share` | **MOUNT BY NAME: OK** — lists the share | + +**Conclusion for R-7:** `wsdd` alone makes the box *visible* but is **not sufficient** for the +one-click UX — a **flat-name resolver is required** for `\\FELHOM-SPIKE` to open. Options, in order of +how well they serve the exact WSD-shown flat name: +1. **nmbd / NetBIOS name service** (samba's `disable netbios=no` + run nmbd) — *directly resolves the + flat `\\FELHOM-SPIKE`*, proven here. The catch: NetBIOS-over-TCP is legacy (Microsoft is slowly + deprecating it) and can be off on hardened client networks; needs UDP 137/138 and + `interfaces = eth0` + `bind interfaces only = yes` in production (nmbd bound the docker 172.x + bridges too here — must be pinned to the LAN iface). +2. **mDNS / avahi** advertising `felhom-spike.local` — Windows 10/11 resolve `.local` natively and + it is the future-proof path, **but** it serves `\\felhom-spike.local\…`, not the flat name the + WSD icon double-clicks — so it's an *additional* access path, not a drop-in fix for the Explorer + double-click. (Not tested live — R-7 should.) +3. **Accept "mount by IP / by `.local`"** and treat WSD as visibility-only — the weakest UX. + +R-7 recommendation: ship **wsdd + nmbd (LAN-bound)** for the classic one-click experience *and* +**avahi/.local** for the modern clients, so both the flat name and `.local` resolve. ## S5 — SSDP / DLNA pre-check for R-8 (scripted only) @@ -185,14 +240,18 @@ future deployment must avoid host-network port collisions (§7c). | mDNS 5353 RX / TX | PASS / PASS | PASS / PASS | **FAIL / FAIL** · unicast-publish PASS | not run | | WSD 3702 RX / TX | PASS / PASS | PASS / PASS | **FAIL / FAIL** · unicast-publish PASS | not run | | SMB 445 unicast | n/a | **PASS** (S4) | publish PASS | not run | -| Explorer visibility (human) | n/a | **PENDING** (S4.4) | n/a | not run | +| Explorer visibility (human) | n/a | **PASS** — FELHOM-SPIKE renders (S4.4) | n/a | not run | +| Explorer double-click → open share | n/a | **FAIL w/ wsdd-only → PASS w/ nmbd** (S4b) | n/a | not run | -**(a) Recommended transport for the R-7 SMB stack — HOST-NETWORK, LAN-bound.** The matrix is -unambiguous: WSD (Windows Explorer's actual discovery) and mDNS require the responder in the guest -netns; the default docker bridge is categorically deaf to LAN multicast. So samba + wsdd (and any -avahi) must run `network_mode: host`. Bind SMB to the LAN interface only; **never expose 445 over the -tunnel** (the LAN-only rule R-7 already states). This is the expected outcome — and the matrix, not -the expectation, now backs it. +**(a) Recommended transport + services for the R-7 SMB stack — HOST-NETWORK, LAN-bound, THREE +daemons.** The matrix is unambiguous on transport: WSD (Explorer's actual discovery) and mDNS require +the responder in the guest netns; the default docker bridge is categorically deaf to LAN multicast. +So the stack must run `network_mode: host`, SMB bound to the LAN interface only, **never over the +tunnel**. On *services*, S4b proved wsdd is not enough: ship **`smbd` (445) + `wsdd` (WSD visibility) ++ `nmbd` (NetBIOS flat-name resolution, so the Explorer double-click on `\\FELHOM-SPIKE` actually +opens) + ideally `avahi` (`.local` for modern/Apple clients)**. Pin every daemon to the LAN iface +(`interfaces = eth0` + `bind interfaces only = yes`) — nmbd otherwise also binds the docker 172.x +bridges. Without nmbd/mDNS the box is *visible but not openable by name* (`0x80070035`). **(b) R-8 "try Jellyfin built-in DLNA first" — PLAUSIBLE on this topology.** SSDP `MediaServer:1` adverts physically reach both LAN clients (S5). The only structural requirement carried over from @@ -216,7 +275,10 @@ generalizes. ## NOT tested (explicit) -- **Explorer Network render** (S4.4) — human leg, pending Viktor; stack left live. +- **mDNS / avahi `.local`** as a flat-name/`.local` resolver alternative to nmbd (S4b option 2) — + NOT tested; R-7 should validate `\\felhom-spike.local` on Win11 + Apple/phone clients. +- **LLMNR responder** as a third name-resolution path — not tested (client LLMNR is on, but nothing + on the box answered it). - **macvlan** (S6) — not needed (host-net passed). - **Real DLNA client / TV** rendering actual media — R-8 owns. - **Phone mDNS** `.local` resolution (optional S4.5) — skipped. @@ -229,9 +291,10 @@ generalizes. ## CLEANUP Throwaway containers `spike-hostnet-*`, `spike-bridge-*`, `spike-ssdp-ms` and all guest-netns -responder processes were `docker rm -f` / `pkill`'d at the end of each leg. **Intentionally left -live for the S4.4 human leg:** `spike-samba` + `spike-wsdd` (host-network), share -`\\192.168.0.127\spike-share` as **FELHOM-SPIKE**. Teardown one-liner once Viktor confirms Explorer: +responder processes were `docker rm -f` / `pkill`'d at the end of each leg. **Left live through the +S4/S4b legs:** `spike-samba` (now with nmbd) + `spike-wsdd` (host-network), share +`\\FELHOM-SPIKE\spike-share` / `\\192.168.0.127\spike-share`. Teardown one-liner (all objective legs +done — safe to run any time): ``` ssh felhom-pve "pct exec 9201 -- docker rm -f spike-samba spike-wsdd; \ diff --git a/documentation/backlog/ROADMAP.md b/documentation/backlog/ROADMAP.md index 69a1a1c..3b87cff 100644 --- a/documentation/backlog/ROADMAP.md +++ b/documentation/backlog/ROADMAP.md @@ -30,8 +30,8 @@ | ID | Item | Size | Status | Notes | |----|------|------|--------|-------| | R-5 | Hub: offsite storage visibility — RESTIC box aggregate (v0.64.0) + PBS DR datastore (v0.65.0), each with fill + operator alert; Offsite tabs + dual dashboard gauges | M | **SHIPPED (hub v0.64.0 + v0.65.0 + tenantsync v1.2.0, 2026-07-17)** | Restic: `monitor.OffsiteBoxChecker` (throttled Hetzner GET; fill 80/90% + oversub 2.0×; scope `"pool-box"`). PBS DR (v0.65.0, Option A): read-only `usage` op on the ep0 `felhom-tenantsync` forced command (`df`, no mutation) → `monitor.PBSDRBoxChecker` (fill 80/90%, states ok/unavailable/degraded, scope `"pbsdr-box"`); `/offsite` Restic/PBS-DR tabs + two gauges; hub deploy ⟂ ep0 update (graceful "n/a"). **Both data pipelines PROVEN-LIVE** (restic `0.2% full`; PBS `19.1% full, 7.1 GB of 37.2 GB` after ep0 → v1.2.0). Thresholds pending Viktor (named keys; separate restic/PBS pairs). OPEN: UI render unit-only (password-gated), alert emails unit + red-proof only (both nominal). See hub v0.64.0 + v0.65.0 REPORTs | -| R-6 | **Spike: LAN service discovery from the guest** — SSDP multicast (UDP 1900, DLNA), WSD (Windows discovery), mDNS; host-network vs macvlan; is the customer LXC LAN-bridged in appliance deployments? | M | **spiked (2026-07-18)** | **VERDICT: appliance guest IS LAN-bridged (own DHCP lease on the household /24); multicast discovery works ONLY in the guest netns — guest-direct or Docker `--network host` (SSDP/mDNS/WSD all PASS both ways); the default docker bridge is categorically DEAF to LAN multicast (WSD/mDNS RX FAIL, unicast-publish PASS). Real samba+wsdd on host-net → Windows 11 ProbeMatch + 445 + authenticated SMB round-trip all PASS; real SSDP `MediaServer:1` advert reaches both LAN clients. → R-7 SMB stack MUST be host-network LAN-bound; R-8 Jellyfin-DLNA plausible if host-network. Caveat: `vmbr0 multicast_snooping=1` worked only because the household router is a live querier — customer LANs w/ snooping+no-querier, and Peti's BYO bridge, are UNTESTED gaps.** Doc: `audits/SPIKE-lan-discovery-2026-07-18.md`. Open sub-leg: S4.4 Explorer render (human, pending Viktor) | -| R-7 | SMB **server** share (**gate input now exists — R-6 spiked 2026-07-18: host-network, LAN-bound**): samba + wsdd, LAN-only binding (never tunnel), user model (single household user first), which roots are shared (dedicated `shares/` vs app userdata — every SMB-writable path needs a backup class), uid-1000 convention, paperless consume flow | L | idea (unblocked) | Flips map row E/MISSING. Alpha-relevant: "my box is a NAS" is a core household expectation. **R-6 settled the transport: `network_mode: host`; carry the port-collision + snooping/querier caveats from the spike into the spec** | +| R-6 | **Spike: LAN service discovery from the guest** — SSDP multicast (UDP 1900, DLNA), WSD (Windows discovery), mDNS; host-network vs macvlan; is the customer LXC LAN-bridged in appliance deployments? | M | **spiked (2026-07-18)** | **VERDICT: appliance guest IS LAN-bridged (own DHCP lease on the household /24); multicast discovery works ONLY in the guest netns — guest-direct or Docker `--network host` (SSDP/mDNS/WSD all PASS both ways); the default docker bridge is categorically DEAF to LAN multicast (WSD/mDNS RX FAIL, unicast-publish PASS). Real samba+wsdd on host-net → Windows 11 ProbeMatch + FELHOM-SPIKE renders in Explorer + 445 + authenticated SMB round-trip all PASS; real SSDP `MediaServer:1` advert reaches both LAN clients. → R-7 SMB stack MUST be host-network LAN-bound; R-8 Jellyfin-DLNA plausible if host-network. Caveat: `vmbr0 multicast_snooping=1` worked only because the household router is a live querier — customer LANs w/ snooping+no-querier, and Peti's BYO bridge, are UNTESTED gaps.** **S4b (human leg, the sharpest finding): wsdd makes the box VISIBLE but the Explorer double-click FAILS `0x80070035` — WSD gives no name resolution; the flat `\\FELHOM-SPIKE` resolved by no path. Adding `nmbd` (NetBIOS) fixed it live (flat name resolves + mounts). → R-7 needs smbd+wsdd+nmbd (+avahi/.local for modern clients), not wsdd alone.** Doc: `audits/SPIKE-lan-discovery-2026-07-18.md`. | +| R-7 | SMB **server** share (**gate input now exists — R-6 spiked 2026-07-18: host-network, LAN-bound, smbd+wsdd+nmbd**): samba + wsdd + nmbd, LAN-only binding (never tunnel), user model (single household user first), which roots are shared (dedicated `shares/` vs app userdata — every SMB-writable path needs a backup class), uid-1000 convention, paperless consume flow | L | idea (unblocked) | Flips map row E/MISSING. Alpha-relevant: "my box is a NAS" is a core household expectation. **R-6 settled the transport (`network_mode: host`) AND the service set: wsdd for WSD visibility is NOT enough — add `nmbd` so the Explorer double-click on `\\FELHOM-SPIKE` resolves (S4b proved wsdd-only fails `0x80070035`); ideally avahi/.local too. Pin daemons to eth0 (`bind interfaces only`). Carry the port-collision + snooping/querier caveats into the spec** | | R-8 | DLNA (**gate input now exists — R-6 spiked 2026-07-18: SSDP reaches LAN clients from host-net**): validate Jellyfin's built-in DLNA server first; only add minidlna to the catalog if Jellyfin-DLNA fails | S | idea (unblocked) | Don't add catalog weight before proving the cheap path. **R-6 confirmed the cheap path is physically viable — Jellyfin DLNA must run host-network (same multicast constraint as R-7)** | | R-9 | Uninstaller trio (from 07-15 Peti session): cluster-aware `felhom_guests` guard (node-local `pct list` deletes cluster-wide pveum objects); saferemove detection + time estimate + opt-in `--quick-remove` (never mutate `storage.cfg`); smarter `restore_storage` default for BYO clusters (shared storage, not local-lvm) | M | idea | Second item's rejected alternative (temp-disable-and-restore) stays rejected — crash window silently downgrades cluster wipe policy | | R-10 | T-6E-1: DB-dump dir-fsync asymmetry (LOW, confirmed in 6E) | XS | idea | One-line hardening; batch with the next controller task |