fix(netpol): allow shelly-manager mDNS queries #1436

Merged
k.renner merged 1 commits from claude/shelly-manager-mdns into main 2026-10-25 22:16:39 +00:00
Member

shelly-manager resolves Shelly *.local names over mDNS. The queries leave on the pod's default interface eth0 to 224.0.0.251:5353, which the egress lockdown (#1432) does not allow. Hubble shows them as Policy denied (home-assistant/shelly-manager → 224.0.0.251:5353 world-ipv4), and since 15:07Z shelly-manager logs HttpRequestException: Name or service not known (shellyplug-s-4382e5.local:80) and similar.

Adds 224.0.0.251/32 UDP 5353 to shelly-manager-egress. IPv4 only: the mDNS library (Zeroconf) never uses ff02::fb (shelly-manager-mdns-library-replacement-decision), and the IPv6 drops Hubble shows are Invalid source ip, not policy.

Validation: kubectl apply --dry-run=server passes. After merge: the Hubble drops stop and the .local errors in the shelly-manager log stop.

🤖 Generated with Claude Code

shelly-manager resolves Shelly `*.local` names over mDNS. The queries leave on the pod's default interface `eth0` to `224.0.0.251:5353`, which the egress lockdown (#1432) does not allow. Hubble shows them as `Policy denied` (`home-assistant/shelly-manager → 224.0.0.251:5353 world-ipv4`), and since 15:07Z shelly-manager logs `HttpRequestException: Name or service not known (shellyplug-s-4382e5.local:80)` and similar. Adds `224.0.0.251/32` UDP 5353 to `shelly-manager-egress`. IPv4 only: the mDNS library (Zeroconf) never uses `ff02::fb` ([[shelly-manager-mdns-library-replacement-decision]]), and the IPv6 drops Hubble shows are `Invalid source ip`, not policy. Validation: `kubectl apply --dry-run=server` passes. After merge: the Hubble drops stop and the `.local` errors in the shelly-manager log stop. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
claude-bot added 1 commit 2026-10-25 15:11:07 +00:00
fix(netpol): allow shelly-manager mDNS queries
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
9bcc1cb420
shelly-manager resolves device *.local names via mDNS; the queries leave on
eth0 to 224.0.0.251:5353 and have been dropped since the egress lockdown
(#1432), failing with 'Name or service not known' since 15:07Z.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
review-bot left a comment
Member

🤖 Automated review — model claude-opus-5-5, commit 9bcc1cb420335f5ab7a404f18e781707d75c7112.

Automated review by the review-bot: it approves only when it found nothing red or yellow, and a human still merges. Push new commits to get a fresh review.


Summary

This PR adds 224.0.0.251/32 UDP 5353 egress to shelly-manager-egress so the mDNS queries that #1432 now drops can leave on eth0. The PR is mergeable against main at b10b50f. The file on main is the post-#1432 version (merged at 14:50Z as b341b26), and no other open PR touches it. The rule itself is small and well scoped, but the repo's own manifests indicate that mDNS sent on eth0 cannot reach the IoT VLAN. So this will probably silence the Hubble drops without fixing the .local errors it is meant to fix.

⚪ Unverified

  • The diagnosis probably does not explain the outage. These rules in the repo all suggest the new rule at kubernetes/infrastructure/network-policies/home-assistant-ns.yaml:381-386 will not restore resolution:
    • Multicast on eth0 reaches nothing. kubernetes/apps/home-assistant-iot/mdns-relay-deployment.yaml:5-7 says Cilium runs "in tunnel mode without enable-multicast, so re-emitted multicast is dropped by the CNI". Lines 12-13 say "HA-initiated browsing still dies on eth0".
    • net1 exists to work around exactly that. shelly-manager-deployment.yaml:28-32 and shelly-manager-network-attachment.yaml:2-8 give shelly-manager a macvlan net1 on v30iot because "multicast doesn't cross the L3 boundary" from the pod CIDR. shelly-manager-deployment.yaml:38-40 adds that "macvlan traffic bypasses Cilium policy entirely", so the queries that can actually reach Shellies were never affected by this CNP.
    • The eth0 copies were always dead traffic. Before #1432, the namespace-wide world allow just let them die later instead of showing as Policy denied.
    • The error points elsewhere. In shelly-manager's src/ShellyManager.Web/Shelly/MdnsConnectCallback.cs (ConnectAsync, read on main), .local hosts are resolved first as <id>.iot.renner.uno through the system resolver (ShellyManager__DnsSuffix, shelly-manager-deployment.yaml:88-89). Only then does it fall back to the mDNS cache. It throws SocketException(HostNotFound) ("Name or service not known") only when neither path produced a single candidate. A blocked TCP connect would surface as a timeout instead.
    • Where to look instead. It is worth checking the suffix lookup (e.g. getent hosts shellyplug-s-4382e5.iot.renner.uno from the pod) and whether net1 is attached with a DHCP lease. I could not observe the cluster. This rests on the repo's own documentation of Cilium's multicast mode, not on live behaviour.
  • The IPv4-only reasoning cites the wrong library. The PR body says the mDNS library is Zeroconf and "never uses ff02::fb". But shelly-manager replaced Zeroconf with dual-stack MeaMod.DNS on 2026-07-25 (commit ac64514, "Zeroconf … never joined FF02::FB … Replace it with MeaMod.DNS"). ShellyManager.Web.csproj references MeaMod.DNS 1.0.71. The deployed tag build.1792387459 decodes as a Unix time to about mid-October 2026, well after that change. I could not map the tag to a commit. If the eth0 path mattered, the v6 group would matter too. The Hubble "Invalid source ip" note in the body may still be accurate.

🟡 Suggestions

  • home-assistant-ns.yaml:381-386: before merging, check that this rule actually fixes the symptom, not just the Hubble drop count. The body's own post-merge check ("the .local errors … stop") is the right test. If the errors continue, the cause is the suffix lookup or net1, and this rule only reduces drop noise. If keeping it for noise reduction is the intent, say so in the PR and the comment.

🟢 Nits

  • home-assistant-ns.yaml:363-364: "mDNS queries for their *.local names (sent out the default interface eth0)" reads as though the eth0 path is how resolution works. That contradicts mdns-relay-deployment.yaml:12-13. If the rule stays, a wording like "suppresses drops of the eth0 copy; resolution uses net1, which bypasses Cilium" would keep the next reader from relying on it.

Tests

Manifest-only change. The repo has no policy tests, and the server-side dry-run in the body covers syntax. The real check is the runtime one described above.

Recommendation

Looks reasonable — no blocking issues. The rule is narrow and harmless, but please confirm it actually fixes the .local failures before relying on it as the fix.

🤖 **Automated review** — model `claude-opus-5-5`, commit `9bcc1cb420335f5ab7a404f18e781707d75c7112`. > Automated review by the `review-bot`: it approves only when it found nothing red or yellow, and a human still merges. Push new commits to get a fresh review. --- ## Summary This PR adds `224.0.0.251/32` UDP 5353 egress to `shelly-manager-egress` so the mDNS queries that #1432 now drops can leave on `eth0`. The PR is mergeable against `main` at `b10b50f`. The file on `main` is the post-#1432 version (merged at 14:50Z as `b341b26`), and no other open PR touches it. The rule itself is small and well scoped, but the repo's own manifests indicate that mDNS sent on `eth0` cannot reach the IoT VLAN. So this will probably silence the Hubble drops without fixing the `.local` errors it is meant to fix. ## ⚪ Unverified - **The diagnosis probably does not explain the outage.** These rules in the repo all suggest the new rule at `kubernetes/infrastructure/network-policies/home-assistant-ns.yaml:381-386` will not restore resolution: - **Multicast on `eth0` reaches nothing.** `kubernetes/apps/home-assistant-iot/mdns-relay-deployment.yaml:5-7` says Cilium runs "in tunnel mode without enable-multicast, so re-emitted multicast is dropped by the CNI". Lines 12-13 say "HA-initiated browsing still dies on eth0". - **`net1` exists to work around exactly that.** `shelly-manager-deployment.yaml:28-32` and `shelly-manager-network-attachment.yaml:2-8` give shelly-manager a macvlan `net1` on v30iot because "multicast doesn't cross the L3 boundary" from the pod CIDR. `shelly-manager-deployment.yaml:38-40` adds that "macvlan traffic bypasses Cilium policy entirely", so the queries that can actually reach Shellies were never affected by this CNP. - **The `eth0` copies were always dead traffic.** Before #1432, the namespace-wide `world` allow just let them die later instead of showing as `Policy denied`. - **The error points elsewhere.** In shelly-manager's `src/ShellyManager.Web/Shelly/MdnsConnectCallback.cs` (`ConnectAsync`, read on `main`), `.local` hosts are resolved first as `<id>.iot.renner.uno` through the system resolver (`ShellyManager__DnsSuffix`, `shelly-manager-deployment.yaml:88-89`). Only then does it fall back to the mDNS cache. It throws `SocketException(HostNotFound)` ("Name or service not known") only when neither path produced a single candidate. A blocked TCP connect would surface as a timeout instead. - **Where to look instead.** It is worth checking the suffix lookup (e.g. `getent hosts shellyplug-s-4382e5.iot.renner.uno` from the pod) and whether `net1` is attached with a DHCP lease. I could not observe the cluster. This rests on the repo's own documentation of Cilium's multicast mode, not on live behaviour. - **The IPv4-only reasoning cites the wrong library.** The PR body says the mDNS library is Zeroconf and "never uses ff02::fb". But shelly-manager replaced Zeroconf with dual-stack MeaMod.DNS on 2026-07-25 (commit `ac64514`, "Zeroconf … never joined FF02::FB … Replace it with MeaMod.DNS"). `ShellyManager.Web.csproj` references `MeaMod.DNS` 1.0.71. The deployed tag `build.1792387459` decodes as a Unix time to about mid-October 2026, well after that change. I could not map the tag to a commit. If the `eth0` path mattered, the v6 group would matter too. The Hubble "Invalid source ip" note in the body may still be accurate. ## 🟡 Suggestions - `home-assistant-ns.yaml:381-386`: before merging, check that this rule actually fixes the symptom, not just the Hubble drop count. The body's own post-merge check ("the `.local` errors … stop") is the right test. If the errors continue, the cause is the suffix lookup or `net1`, and this rule only reduces drop noise. If keeping it for noise reduction is the intent, say so in the PR and the comment. ## 🟢 Nits - `home-assistant-ns.yaml:363-364`: "mDNS queries for their *.local names (sent out the default interface eth0)" reads as though the `eth0` path is how resolution works. That contradicts `mdns-relay-deployment.yaml:12-13`. If the rule stays, a wording like "suppresses drops of the eth0 copy; resolution uses net1, which bypasses Cilium" would keep the next reader from relying on it. ## Tests Manifest-only change. The repo has no policy tests, and the server-side dry-run in the body covers syntax. The real check is the runtime one described above. ## Recommendation Looks reasonable — no blocking issues. The rule is narrow and harmless, but please confirm it actually fixes the `.local` failures before relying on it as the fix. <!-- pr-review:sha=9bcc1cb420335f5ab7a404f18e781707d75c7112 -->
k.renner merged commit 0904f73721 into main 2026-10-25 22:16:39 +00:00
Sign in to join this conversation.