k8snetworkplumbingwg / multi-networkpolicy-iptables

MultiNetworkPolicy iptable based implementation
Apache License 2.0
13 stars 19 forks source link

Stacked policies should be linked with logical `OR` #17

Closed zeeke closed 1 year ago

zeeke commented 2 years ago

Hi,

I think I found a behavior that differs from regular NetworkPolicies when creating multiple MultiNetworkPolicies with the same pod selector.

The scenario can be reproduced in a Kind (with Calico as default CNI network plugin) using this fork (branch multinetpolicy-bugs):

$ cd e2e
$ ./get_tools.sh
$ ./setup_cluster.sh
$ kubectl apply -f stacked.yml
$ ./stacked-test.sh

The scenario creates

stacked-test.sh verifies the behavior (1 error connecting, 0 connection ok)

$ ./stacked-test.sh                                                                                                                                                        10:32:52
pod/pod-a condition met
MULTI: pod-a <-- pod-b 1
MULTI: pod-a <-- pod-c 1
MULTI: pod-a <-- pod-d 1
REGULAR: pod-a <-- pod-b 0
REGULAR: pod-a <-- pod-c 0
REGULAR: pod-a <-- pod-d 1

test-stacked-multi/pod-a iptables

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   15   900 MULTI-INGRESS  all  --  net1   *       0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MULTI-EGRESS  all  --  *      net1    0.0.0.0/0            0.0.0.0/0           

Chain MULTI-0-INGRESS (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    6   360 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            MARK and 0xfffcffff
    6   360 MULTI-0-INGRESS-0-PORTS  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    6   360 MULTI-0-INGRESS-0-FROM  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    2   120 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            mark match 0x30000/0x30000
    4   240 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain MULTI-0-INGRESS-0-FROM (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    2   120 MARK       all  --  net1   *       2.2.5.10             0.0.0.0/0            MARK or 0x20000

Chain MULTI-0-INGRESS-0-PORTS (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    6   360 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* no ingress ports, skipped */ MARK or 0x10000

Chain MULTI-1-INGRESS (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    2   120 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            MARK and 0xfffcffff
    2   120 MULTI-1-INGRESS-0-PORTS  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    2   120 MULTI-1-INGRESS-0-FROM  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            mark match 0x30000/0x30000
    2   120 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain MULTI-1-INGRESS-0-FROM (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MARK       all  --  net1   *       2.2.5.9              0.0.0.0/0            MARK or 0x20000

Chain MULTI-1-INGRESS-0-PORTS (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    2   120 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* no ingress ports, skipped */ MARK or 0x10000

Chain MULTI-EGRESS (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain MULTI-INGRESS (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    6   360 MULTI-0-INGRESS  all  --  net1   *       0.0.0.0/0            0.0.0.0/0            /* policy:test-multinetwork-policy-stacked-1 net-attach-def:default/macvlan1-stacked */
    2   120 MULTI-1-INGRESS  all  --  net1   *       0.0.0.0/0            0.0.0.0/0            /* policy:test-multinetwork-policy-stacked-2 net-attach-def:default/macvlan1-stacked */

It seems that MultiNetworkPolicies are linked with an AND operator (from pod-b AND pod-c), while with regular network policies work with an OR operator, as stated in the documentation:

Network policies do not conflict; they are additive. If any policy or policies apply to a given pod for a given direction, the connections allowed in that direction from that pod is the union of what the applicable policies allow. Thus, order of evaluation does not affect the policy result.

Is it the intended behavior or it can be flagged as a bug? in the letter case I can work on a PR with some clues.