network-policies: allow all ICMP types in/out of default-deny namespaces

Replaces both the per-namespace ICMP-error addition (3c517a0) and the
broad CCNP that broke kube-system (reverted in 3c517a0). Adds a single
CCNP that:

* Scopes its endpointSelector via `matchExpressions In` to the explicit
  list of namespaces that already opted into default-deny — so it only
  widens what's already enforced and CANNOT transition kube-system or
  any other unmanaged namespace into policy-enforced mode.
* Allows the full standard ICMPv4 (0-30) and ICMPv6 (1-4, 128-153) type
  set in both directions. Cilium's ICMPField requires an explicit type
  per entry; there is no wildcard, so the list is enumerated.

This covers Echo Request/Reply (ping), Destination Unreachable / Port
Unreachable, Time Exceeded (traceroute), Packet Too Big (PMTUD), and
the full ND/RA/RS set so v6 neighbour discovery works.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-20 10:50:21 +02:00
co-authored by Claude Opus 4.7
parent 3c517a0b98
commit 66dbe9ffe2
3 changed files with 206 additions and 20 deletions
@@ -0,0 +1,205 @@
# All ICMP types, in/out of every namespace that has a default-deny.
#
# Scoped via `matchExpressions In` to the explicit list of namespaces
# that already opted into policy enforcement, so this CCNP only widens
# what's already enforced — it cannot transition kube-system or any
# other unmanaged namespace into policy-enforced mode (which is what
# broke metrics-server when I previously used `Exists`).
#
# Enumerates every assigned ICMPv4 type (0-30) and ICMPv6 type
# (1-4, 128-153). Cilium's policy schema requires an explicit `type`
# per ICMPField — there is no wildcard.
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: allow-icmp-default-deny-namespaces
spec:
endpointSelector:
matchExpressions:
- key: io.kubernetes.pod.namespace
operator: In
values:
- apps
- audiobookshelf
- authentik
- crowdsec
- database
- home-assistant
- immich
- influxdb
- ingress
- monitoring
- paperless
- rook-ceph
- spegel
- velero
ingress:
- fromEndpoints:
- matchExpressions:
- key: io.kubernetes.pod.namespace
operator: Exists
icmps:
- fields:
- type: 0 # Echo Reply
family: IPv4
- type: 3 # Destination Unreachable
family: IPv4
- type: 4 # Source Quench
family: IPv4
- type: 5 # Redirect
family: IPv4
- type: 8 # Echo Request
family: IPv4
- type: 9 # Router Advertisement
family: IPv4
- type: 10 # Router Solicitation
family: IPv4
- type: 11 # Time Exceeded
family: IPv4
- type: 12 # Parameter Problem
family: IPv4
- type: 13 # Timestamp
family: IPv4
- type: 14 # Timestamp Reply
family: IPv4
- type: 15 # Information Request
family: IPv4
- type: 16 # Information Reply
family: IPv4
- type: 17 # Address Mask Request
family: IPv4
- type: 18 # Address Mask Reply
family: IPv4
- type: 30 # Traceroute
family: IPv4
- type: 1 # Destination Unreachable
family: IPv6
- type: 2 # Packet Too Big
family: IPv6
- type: 3 # Time Exceeded
family: IPv6
- type: 4 # Parameter Problem
family: IPv6
- type: 128 # Echo Request
family: IPv6
- type: 129 # Echo Reply
family: IPv6
- type: 130 # Multicast Listener Query
family: IPv6
- type: 131 # Multicast Listener Report
family: IPv6
- type: 132 # Multicast Listener Done
family: IPv6
- type: 133 # Router Solicitation
family: IPv6
- type: 134 # Router Advertisement
family: IPv6
- type: 135 # Neighbor Solicitation
family: IPv6
- type: 136 # Neighbor Advertisement
family: IPv6
- type: 137 # Redirect
family: IPv6
- type: 138 # Router Renumbering
family: IPv6
- type: 141 # Inverse Neighbor Discovery Solicitation
family: IPv6
- type: 142 # Inverse Neighbor Discovery Advertisement
family: IPv6
- type: 143 # MLDv2 Listener Report
family: IPv6
- type: 148 # Certification Path Solicitation
family: IPv6
- type: 149 # Certification Path Advertisement
family: IPv6
- type: 151 # Multicast Router Advertisement
family: IPv6
- type: 152 # Multicast Router Solicitation
family: IPv6
- type: 153 # Multicast Router Termination
family: IPv6
egress:
- 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
@@ -36,26 +36,6 @@ spec:
- fromEntities:
- host
- remote-node
# ICMP error class from any cluster pod — covers e.g. coredns sending
# `Destination Unreachable (Port)` back when an HA DNS query lands on
# a draining coredns instance via SO_REUSEPORT. Without this, HA's
# kernel never learns the destination is unreachable and just keeps
# retransmitting; Hubble shows the DU drops as
# `policy-verdict:none DENIED (ICMPv4 DestinationUnreachable(Port))`.
- fromEndpoints:
- matchExpressions:
- key: io.kubernetes.pod.namespace
operator: Exists
icmps:
- fields:
- type: 3 # IPv4 Destination Unreachable
family: IPv4
- type: 11 # IPv4 Time Exceeded
family: IPv4
- type: 1 # IPv6 Destination Unreachable
family: IPv6
- type: 3 # IPv6 Time Exceeded
family: IPv6
# IoT devices reach HA on 10.2.30.80 and mosquitto on 10.2.30.81
# via Cilium-L2 LoadBalancers (externalTrafficPolicy=Local preserves
# source IP, so they appear as world identity from the pod's
@@ -18,3 +18,4 @@ resources:
- rook-ceph-ns.yaml
- velero-ns.yaml
- allow-cilium-health.yaml
- allow-icmp.yaml