network-policies(home-assistant): allow all ICMP types in/out

Adds an explicit ICMP allow (all standard ICMPv4 + ICMPv6 types, both
directions) inside HA's existing default-deny CNP. Hubble was showing
~115 ICMPv6 DestinationUnreachable POLICY_DENIED drops per 2 minutes
from HA to coredns, despite the Cilium docs claiming "ICMP related to
a connection otherwise allowed by the policy" should pass automatically.
The CT-RELATED path isn't working empirically.

Per-namespace shape (proven safe in 3c517a0); type enumeration from
66dbe9f. NOT a CCNP — prior CCNP attempts (7f95486 / 66dbe9f / 7da87bf
/ 4fc52db) all broke unrelated traffic in this cluster.

Starting with home-assistant only as a smoke-test for the wider
roll-out across other default-deny namespaces.
This commit is contained in:
2026-05-20 16:00:54 +02:00
parent ab72a1f2f8
commit d61b24d951
@@ -44,6 +44,60 @@ spec:
# bypassing Cilium policy entirely; this CNP rule does not gate it.
- fromEntities:
- world
# ICMP — all standard ICMPv4 and ICMPv6 types from any cluster pod.
# Per Cilium docs, "If any layer 4 policy is specified, then ICMP
# will be blocked unless it's related to a connection that is
# otherwise allowed by the policy." The CT-RELATED path is not
# passing these in practice (Hubble shows ICMPv6 DestinationUnreachable
# being POLICY_DENIED on the egress side of established DNS flows),
# so allow ICMP explicitly. Same shape as commit 3c517a0 — widened
# from the error class to the full standard type set. Cilium's
# ICMPField requires an explicit type per entry; no wildcard.
- fromEndpoints:
- matchExpressions:
- key: io.kubernetes.pod.namespace
operator: Exists
icmps:
- fields:
- { type: 0, family: IPv4 } # Echo Reply
- { type: 3, family: IPv4 } # Destination Unreachable
- { type: 4, family: IPv4 } # Source Quench
- { type: 5, family: IPv4 } # Redirect
- { type: 8, family: IPv4 } # Echo Request
- { type: 9, family: IPv4 } # Router Advertisement
- { type: 10, family: IPv4 } # Router Solicitation
- { type: 11, family: IPv4 } # Time Exceeded
- { type: 12, family: IPv4 } # Parameter Problem
- { type: 13, family: IPv4 } # Timestamp
- { type: 14, family: IPv4 } # Timestamp Reply
- { type: 15, family: IPv4 } # Information Request
- { type: 16, family: IPv4 } # Information Reply
- { type: 17, family: IPv4 } # Address Mask Request
- { type: 18, family: IPv4 } # Address Mask Reply
- { type: 30, family: IPv4 } # Traceroute
- { type: 1, family: IPv6 } # Destination Unreachable
- { type: 2, family: IPv6 } # Packet Too Big
- { type: 3, family: IPv6 } # Time Exceeded
- { type: 4, family: IPv6 } # Parameter Problem
- { type: 128, family: IPv6 } # Echo Request
- { type: 129, family: IPv6 } # Echo Reply
- { type: 130, family: IPv6 } # Multicast Listener Query
- { type: 131, family: IPv6 } # Multicast Listener Report
- { type: 132, family: IPv6 } # Multicast Listener Done
- { type: 133, family: IPv6 } # Router Solicitation
- { type: 134, family: IPv6 } # Router Advertisement
- { type: 135, family: IPv6 } # Neighbor Solicitation
- { type: 136, family: IPv6 } # Neighbor Advertisement
- { type: 137, family: IPv6 } # Redirect
- { type: 138, family: IPv6 } # Router Renumbering
- { type: 141, family: IPv6 } # Inverse ND Solicitation
- { type: 142, family: IPv6 } # Inverse ND Advertisement
- { type: 143, family: IPv6 } # MLDv2 Listener Report
- { type: 148, family: IPv6 } # Certification Path Solicitation
- { type: 149, family: IPv6 } # Certification Path Advertisement
- { type: 151, family: IPv6 } # Multicast Router Advertisement
- { type: 152, family: IPv6 } # Multicast Router Solicitation
- { type: 153, family: IPv6 } # Multicast Router Termination
egress:
# Cluster-internal callers HA initiates connections to: mosquitto,
# whisper, matter-server, etc.
@@ -90,3 +144,52 @@ spec:
# endpoints (Hue, Roomba, Philips, Brother IPP, …).
- toEntities:
- world
# ICMP — egress mirror of the ingress ICMP allow above. Lets HA
# send ICMP to any cluster pod (covers the kernel's ICMPv6
# Destination Unreachable when CoreDNS responses land on a
# closed source port, plus ping etc).
- toEndpoints:
- matchExpressions:
- key: io.kubernetes.pod.namespace
operator: Exists
icmps:
- fields:
- { type: 0, family: IPv4 }
- { type: 3, family: IPv4 }
- { type: 4, family: IPv4 }
- { type: 5, family: IPv4 }
- { type: 8, family: IPv4 }
- { type: 9, family: IPv4 }
- { type: 10, family: IPv4 }
- { type: 11, family: IPv4 }
- { type: 12, family: IPv4 }
- { type: 13, family: IPv4 }
- { type: 14, family: IPv4 }
- { type: 15, family: IPv4 }
- { type: 16, family: IPv4 }
- { type: 17, family: IPv4 }
- { type: 18, family: IPv4 }
- { type: 30, family: IPv4 }
- { type: 1, family: IPv6 }
- { type: 2, family: IPv6 }
- { type: 3, family: IPv6 }
- { type: 4, family: IPv6 }
- { type: 128, family: IPv6 }
- { type: 129, family: IPv6 }
- { type: 130, family: IPv6 }
- { type: 131, family: IPv6 }
- { type: 132, family: IPv6 }
- { type: 133, family: IPv6 }
- { type: 134, family: IPv6 }
- { type: 135, family: IPv6 }
- { type: 136, family: IPv6 }
- { type: 137, family: IPv6 }
- { type: 138, family: IPv6 }
- { type: 141, family: IPv6 }
- { type: 142, family: IPv6 }
- { type: 143, family: IPv6 }
- { type: 148, family: IPv6 }
- { type: 149, family: IPv6 }
- { type: 151, family: IPv6 }
- { type: 152, family: IPv6 }
- { type: 153, family: IPv6 }