netpol: anchor base-chain jump on veth only, not pod IP
Build flock Image / build (push) Has been cancelled
Build flock Image / build (push) Has been cancelled
The previous base-chain jump matched iifname/oifname AND saddr/daddr == pod eth0 IP. Anycast traffic has the anycast IP as daddr, not the pod's eth0 unicast — so anycast packets skipped the policy chain entirely and fell through to the forward chain's policy=accept. The veth uniquely belongs to one pod. Anything traversing it is to or from that pod by definition (anycast, unicast, future overlay routes). Match on iifname/oifname alone; let the pod-side chain's accept lines + trailing drop be the policy. Validated end-to-end on host001: anycast nginx pod with default-deny ingress NetPol now correctly drops traffic from any peer; adding an allow-from-podSelector rule unblocks only the matched peer. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+13
-26
@@ -247,35 +247,22 @@ func writePortMatch(sb *strings.Builder, p PortMatch) {
|
||||
}
|
||||
|
||||
// writeBaseJump emits one line per (pod, direction) chain in the base
|
||||
// `forward` chain. The match is anchored on the host-side veth name so
|
||||
// the rule only fires for traffic that genuinely crosses this pod's veth.
|
||||
// `forward` chain. The match is anchored on the host-side veth name —
|
||||
// the veth uniquely belongs to one pod, so anything traversing it is
|
||||
// to/from that pod by definition.
|
||||
//
|
||||
// We additionally constrain on the pod's address (saddr for egress, daddr
|
||||
// for ingress) so a packet that somehow hits the wrong veth — e.g. during
|
||||
// a CNI ADD race — won't be policy-evaluated against the wrong pod.
|
||||
// We deliberately don't filter on the pod's eth0 address: the pod can
|
||||
// also receive traffic addressed to its anycast IP (or any other host
|
||||
// route the operator has installed via flock-agent), and policy must
|
||||
// apply uniformly to all of it.
|
||||
func writeBaseJump(sb *strings.Builder, c chain) {
|
||||
v6, v4 := splitIPFamily(c.podIPs)
|
||||
emit := func(family string, ip net.IP) {
|
||||
if ip == nil {
|
||||
return
|
||||
}
|
||||
var iface, addrField, addrStr string
|
||||
if c.direction == DirEgress {
|
||||
iface = "iifname"
|
||||
addrField = family + " saddr"
|
||||
} else {
|
||||
iface = "oifname"
|
||||
addrField = family + " daddr"
|
||||
}
|
||||
if family == "ip" {
|
||||
addrStr = ip.To4().String()
|
||||
} else {
|
||||
addrStr = ip.To16().String()
|
||||
}
|
||||
fmt.Fprintf(sb, "\t\t%s \"%s\" %s %s jump %s\n", iface, c.hostIface, addrField, addrStr, c.name)
|
||||
var iface string
|
||||
if c.direction == DirEgress {
|
||||
iface = "iifname"
|
||||
} else {
|
||||
iface = "oifname"
|
||||
}
|
||||
emit("ip6", v6)
|
||||
emit("ip", v4)
|
||||
fmt.Fprintf(sb, "\t\t%s \"%s\" jump %s\n", iface, c.hostIface, c.name)
|
||||
}
|
||||
|
||||
// splitFamily partitions CIDRs into (v6, v4) lists, preserving order
|
||||
|
||||
Reference in New Issue
Block a user