Skip to content

Commit cadba6c

Browse files
jimmy-zhmurali-reddy
authored andcommitted
Use ipset to manage multiple CIDRs in a network policy rule (#529)
* using ipset to manage multiple src CIDRs * using ipset to manage multiple dst CIDRs * soft-code the prefix of iptables chain name and ipset name * gofmt
1 parent cd4ad6f commit cadba6c

File tree

1 file changed

+59
-25
lines changed

1 file changed

+59
-25
lines changed

pkg/controllers/netpol/network_policy_controller.go

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ import (
3030
)
3131

3232
const (
33-
networkPolicyAnnotation = "net.beta.kubernetes.io/network-policy"
33+
networkPolicyAnnotation = "net.beta.kubernetes.io/network-policy"
34+
kubePodFirewallChainPrefix = "KUBE-POD-FW-"
35+
kubeNetworkPolicyChainPrefix = "KUBE-NWPLCY-"
36+
kubeSourceIpSetPrefix = "KUBE-SRC-"
37+
kubeDestinationIpSetPrefix = "KUBE-DST-"
3438
)
3539

3640
// Network policy controller provides both ingress and egress filtering for the pods as per the defined network
@@ -425,16 +429,26 @@ func (npc *NetworkPolicyController) processIngressRules(policy networkPolicyInfo
425429
}
426430
}
427431

428-
for _, cidr := range ingressRule.cidrs {
432+
if len(ingressRule.cidrs) != 0 {
433+
srcIpBlockIpSetName := policyIndexedSourceIpBlockIpSetName(policy.namespace, policy.name, i)
434+
srcIpBlockIpSet, err := npc.ipSetHandler.Create(srcIpBlockIpSetName, utils.TypeHashNet, utils.OptionTimeout, "0")
435+
if err != nil {
436+
return fmt.Errorf("failed to create ipset: %s", err.Error())
437+
}
438+
activePolicyIpSets[srcIpBlockIpSet.Name] = true
439+
err = srcIpBlockIpSet.Refresh(ingressRule.cidrs, utils.OptionTimeout, "0")
440+
if err != nil {
441+
glog.Errorf("failed to refresh srcIpBlockIpSet: " + err.Error())
442+
}
429443
if !ingressRule.matchAllPorts {
430444
for _, portProtocol := range ingressRule.ports {
431445
comment := "rule to ACCEPT traffic from specified CIDR to dest pods selected by policy name: " +
432446
policy.name + " namespace " + policy.namespace
433447
args := []string{"-m", "comment", "--comment", comment,
448+
"-m", "set", "--set", srcIpBlockIpSetName, "src",
434449
"-m", "set", "--set", targetDestPodIpSetName, "dst",
435450
"-p", portProtocol.protocol,
436451
"--dport", portProtocol.port,
437-
"-s", cidr,
438452
"-j", "ACCEPT"}
439453
err := iptablesCmdHandler.AppendUnique("filter", policyChainName, args...)
440454
if err != nil {
@@ -446,8 +460,8 @@ func (npc *NetworkPolicyController) processIngressRules(policy networkPolicyInfo
446460
comment := "rule to ACCEPT traffic from specified CIDR to dest pods selected by policy name: " +
447461
policy.name + " namespace " + policy.namespace
448462
args := []string{"-m", "comment", "--comment", comment,
463+
"-m", "set", "--set", srcIpBlockIpSetName, "src",
449464
"-m", "set", "--set", targetDestPodIpSetName, "dst",
450-
"-s", cidr,
451465
"-j", "ACCEPT"}
452466
err := iptablesCmdHandler.AppendUnique("filter", policyChainName, args...)
453467
if err != nil {
@@ -559,17 +573,26 @@ func (npc *NetworkPolicyController) processEgressRules(policy networkPolicyInfo,
559573
return fmt.Errorf("Failed to run iptables command: %s", err.Error())
560574
}
561575
}
562-
563-
for _, cidr := range egressRule.cidrs {
576+
if len(egressRule.cidrs) != 0 {
577+
dstIpBlockIpSetName := policyIndexedDestinationIpBlockIpSetName(policy.namespace, policy.name, i)
578+
dstIpBlockIpSet, err := npc.ipSetHandler.Create(dstIpBlockIpSetName, utils.TypeHashNet, utils.OptionTimeout, "0")
579+
if err != nil {
580+
return fmt.Errorf("failed to create ipset: %s", err.Error())
581+
}
582+
activePolicyIpSets[dstIpBlockIpSet.Name] = true
583+
err = dstIpBlockIpSet.Refresh(egressRule.cidrs, utils.OptionTimeout, "0")
584+
if err != nil {
585+
glog.Errorf("failed to refresh dstIpBlockIpSet: " + err.Error())
586+
}
564587
if !egressRule.matchAllPorts {
565588
for _, portProtocol := range egressRule.ports {
566589
comment := "rule to ACCEPT traffic from source pods to specified CIDR selected by policy name: " +
567590
policy.name + " namespace " + policy.namespace
568591
args := []string{"-m", "comment", "--comment", comment,
569592
"-m", "set", "--set", targetSourcePodIpSetName, "src",
593+
"-m", "set", "--set", dstIpBlockIpSetName, "dst",
570594
"-p", portProtocol.protocol,
571595
"--dport", portProtocol.port,
572-
"-d", cidr,
573596
"-j", "ACCEPT"}
574597
err := iptablesCmdHandler.AppendUnique("filter", policyChainName, args...)
575598
if err != nil {
@@ -582,7 +605,7 @@ func (npc *NetworkPolicyController) processEgressRules(policy networkPolicyInfo,
582605
policy.name + " namespace " + policy.namespace
583606
args := []string{"-m", "comment", "--comment", comment,
584607
"-m", "set", "--set", targetSourcePodIpSetName, "src",
585-
"-d", cidr,
608+
"-m", "set", "--set", dstIpBlockIpSetName, "dst",
586609
"-j", "ACCEPT"}
587610
err := iptablesCmdHandler.AppendUnique("filter", policyChainName, args...)
588611
if err != nil {
@@ -591,7 +614,6 @@ func (npc *NetworkPolicyController) processEgressRules(policy networkPolicyInfo,
591614
}
592615
}
593616
}
594-
595617
return nil
596618
}
597619

@@ -851,20 +873,20 @@ func cleanupStaleRules(activePolicyChains, activePodFwChains, activePolicyIPSets
851873
// get the list of chains created for pod firewall and network policies
852874
chains, err := iptablesCmdHandler.ListChains("filter")
853875
for _, chain := range chains {
854-
if strings.HasPrefix(chain, "KUBE-NWPLCY-") {
876+
if strings.HasPrefix(chain, kubeNetworkPolicyChainPrefix) {
855877
if _, ok := activePolicyChains[chain]; !ok {
856878
cleanupPolicyChains = append(cleanupPolicyChains, chain)
857879
}
858880
}
859-
if strings.HasPrefix(chain, "KUBE-POD-FW-") {
881+
if strings.HasPrefix(chain, kubePodFirewallChainPrefix) {
860882
if _, ok := activePodFwChains[chain]; !ok {
861883
cleanupPodFwChains = append(cleanupPodFwChains, chain)
862884
}
863885
}
864886
}
865887
for _, set := range ipsets.Sets {
866-
if strings.HasPrefix(set.Name, "KUBE-SRC-") ||
867-
strings.HasPrefix(set.Name, "KUBE-DST-") {
888+
if strings.HasPrefix(set.Name, kubeSourceIpSetPrefix) ||
889+
strings.HasPrefix(set.Name, kubeDestinationIpSetPrefix) {
868890
if _, ok := activePolicyIPSets[set.Name]; !ok {
869891
cleanupPolicyIPSets = append(cleanupPolicyIPSets, set)
870892
}
@@ -1300,37 +1322,49 @@ func (npc *NetworkPolicyController) buildBetaNetworkPoliciesInfo() (*[]networkPo
13001322
func podFirewallChainName(namespace, podName string, version string) string {
13011323
hash := sha256.Sum256([]byte(namespace + podName + version))
13021324
encoded := base32.StdEncoding.EncodeToString(hash[:])
1303-
return "KUBE-POD-FW-" + encoded[:16]
1325+
return kubePodFirewallChainPrefix + encoded[:16]
13041326
}
13051327

13061328
func networkPolicyChainName(namespace, policyName string, version string) string {
13071329
hash := sha256.Sum256([]byte(namespace + policyName + version))
13081330
encoded := base32.StdEncoding.EncodeToString(hash[:])
1309-
return "KUBE-NWPLCY-" + encoded[:16]
1331+
return kubeNetworkPolicyChainPrefix + encoded[:16]
13101332
}
13111333

13121334
func policySourcePodIpSetName(namespace, policyName string) string {
13131335
hash := sha256.Sum256([]byte(namespace + policyName))
13141336
encoded := base32.StdEncoding.EncodeToString(hash[:])
1315-
return "KUBE-SRC-" + encoded[:16]
1337+
return kubeSourceIpSetPrefix + encoded[:16]
13161338
}
13171339

13181340
func policyDestinationPodIpSetName(namespace, policyName string) string {
13191341
hash := sha256.Sum256([]byte(namespace + policyName))
13201342
encoded := base32.StdEncoding.EncodeToString(hash[:])
1321-
return "KUBE-DST-" + encoded[:16]
1343+
return kubeDestinationIpSetPrefix + encoded[:16]
13221344
}
13231345

13241346
func policyIndexedSourcePodIpSetName(namespace, policyName string, ingressRuleNo int) string {
1325-
hash := sha256.Sum256([]byte(namespace + policyName + "ingressrule" + strconv.Itoa(ingressRuleNo)))
1347+
hash := sha256.Sum256([]byte(namespace + policyName + "ingressrule" + strconv.Itoa(ingressRuleNo) + "pod"))
13261348
encoded := base32.StdEncoding.EncodeToString(hash[:])
1327-
return "KUBE-SRC-" + encoded[:16]
1349+
return kubeSourceIpSetPrefix + encoded[:16]
13281350
}
13291351

13301352
func policyIndexedDestinationPodIpSetName(namespace, policyName string, egressRuleNo int) string {
1331-
hash := sha256.Sum256([]byte(namespace + policyName + "egressrule" + strconv.Itoa(egressRuleNo)))
1353+
hash := sha256.Sum256([]byte(namespace + policyName + "egressrule" + strconv.Itoa(egressRuleNo) + "pod"))
1354+
encoded := base32.StdEncoding.EncodeToString(hash[:])
1355+
return kubeDestinationIpSetPrefix + encoded[:16]
1356+
}
1357+
1358+
func policyIndexedSourceIpBlockIpSetName(namespace, policyName string, ingressRuleNo int) string {
1359+
hash := sha256.Sum256([]byte(namespace + policyName + "ingressrule" + strconv.Itoa(ingressRuleNo) + "ipblock"))
1360+
encoded := base32.StdEncoding.EncodeToString(hash[:])
1361+
return kubeSourceIpSetPrefix + encoded[:16]
1362+
}
1363+
1364+
func policyIndexedDestinationIpBlockIpSetName(namespace, policyName string, egressRuleNo int) string {
1365+
hash := sha256.Sum256([]byte(namespace + policyName + "egressrule" + strconv.Itoa(egressRuleNo) + "ipblock"))
13321366
encoded := base32.StdEncoding.EncodeToString(hash[:])
1333-
return "KUBE-DST-" + encoded[:16]
1367+
return kubeDestinationIpSetPrefix + encoded[:16]
13341368
}
13351369

13361370
// Cleanup cleanup configurations done
@@ -1353,7 +1387,7 @@ func (npc *NetworkPolicyController) Cleanup() {
13531387
// TODO: need a better way to delte rule with out using number
13541388
var realRuleNo int
13551389
for i, rule := range forwardChainRules {
1356-
if strings.Contains(rule, "KUBE-POD-FW-") {
1390+
if strings.Contains(rule, kubePodFirewallChainPrefix) {
13571391
err = iptablesCmdHandler.Delete("filter", "FORWARD", strconv.Itoa(i-realRuleNo))
13581392
realRuleNo++
13591393
}
@@ -1369,7 +1403,7 @@ func (npc *NetworkPolicyController) Cleanup() {
13691403
// TODO: need a better way to delte rule with out using number
13701404
realRuleNo = 0
13711405
for i, rule := range forwardChainRules {
1372-
if strings.Contains(rule, "KUBE-POD-FW-") {
1406+
if strings.Contains(rule, kubePodFirewallChainPrefix) {
13731407
err = iptablesCmdHandler.Delete("filter", "OUTPUT", strconv.Itoa(i-realRuleNo))
13741408
realRuleNo++
13751409
}
@@ -1378,7 +1412,7 @@ func (npc *NetworkPolicyController) Cleanup() {
13781412
// flush and delete pod specific firewall chain
13791413
chains, err := iptablesCmdHandler.ListChains("filter")
13801414
for _, chain := range chains {
1381-
if strings.HasPrefix(chain, "KUBE-POD-FW-") {
1415+
if strings.HasPrefix(chain, kubePodFirewallChainPrefix) {
13821416
err = iptablesCmdHandler.ClearChain("filter", chain)
13831417
if err != nil {
13841418
glog.Errorf("Failed to cleanup iptable rules: " + err.Error())
@@ -1395,7 +1429,7 @@ func (npc *NetworkPolicyController) Cleanup() {
13951429
// flush and delete per network policy specific chain
13961430
chains, err = iptablesCmdHandler.ListChains("filter")
13971431
for _, chain := range chains {
1398-
if strings.HasPrefix(chain, "KUBE-NWPLCY-") {
1432+
if strings.HasPrefix(chain, kubeNetworkPolicyChainPrefix) {
13991433
err = iptablesCmdHandler.ClearChain("filter", chain)
14001434
if err != nil {
14011435
glog.Errorf("Failed to cleanup iptable rules: " + err.Error())

0 commit comments

Comments
 (0)