Code Monkey home page Code Monkey logo

kube-router's People

Stargazers

 avatar  avatar

Watchers

 avatar

kube-router's Issues

Typo: currnetPodIps

In pkg/controllers/netpol/policy.go you have the variable currnetPodIps but I guess you mean currentPodIps ;)

IPsets not being correctly created

This code was removed from line 131 of pkg/controllers/netpol/policy.go:

                err := ipset.Restore()
                if err != nil {
                        return nil, nil, fmt.Errorf("failed to perform ipset restore: %s", err.Error())
                }

That means, inside the for ipFamily, ipset := range npc.ipSetHandlers { loop but outside the for _, policy := range networkPoliciesInfo { loop

Without this code, the ipsets are not created and iptables complains

Different ipsets for ipv6 and ipv4 addresses

ipv4 ipsets require family inet and ipv6 ipsets require family inet6. Therefore, we need to create different ipsets for each type of addresses.

For example, in function syncNetworkPolicyChains of pkg/controllers/netpol/policy.go we should do something like this for the ingress part of the policy:

                        // ensure there is a unique chain per network policy in filter table
                        policyChainName := networkPolicyChainName(policy.namespace, policy.name, version, ipFamily)
                        npc.filterTableRules[ipFamily].WriteString(":" + policyChainName + "\n")

                        activePolicyChains[policyChainName] = true

                        var currentPodIps []api.PodIP
                        for _, pod := range policy.targetPods {
                                for _, ip := range pod.ips {
                                        currentPodIps = append(currentPodIps, ip)
                                }
                        }

                        if policy.policyType == "both" || policy.policyType == "ingress" {
                                // create a ipset for all destination pod ip's matched by the policy spec PodSelector
                                targetDestPodIPSetName := policyDestinationPodIPSetName(policy.namespace, policy.name, ipFamily)
                                setEntries := make([][]string, 0)
                                for _, podIP := range currentPodIps {
                                        if ipFamily == api.IPv4Protocol {
                                                if utilsnet.IsIPv4String(podIP.IP) {
                                                        setEntries = append(setEntries, []string{podIP.IP, utils.OptionTimeout, "0"})
                                                }
                                        }
                                        if ipFamily == api.IPv6Protocol {
                                                if utilsnet.IsIPv6String(podIP.IP) {
                                                        setEntries = append(setEntries, []string{podIP.IP, utils.OptionTimeout, "0", "family", "inet6"})
                                                }
                                        }
                                }
                                ipset.RefreshSet(targetDestPodIPSetName, setEntries, utils.TypeHashIP)
                                if err := npc.processIngressRules(policy, targetDestPodIPSetName, activePolicyIPSets, version, ipFamily); err != nil {
                                        return nil, nil, err
                                }
                                activePolicyIPSets[targetDestPodIPSetName] = true
                        }

In other words, loop over the currenPodIps and verify if they are ipv4 or ipv6. And if we are in the matching ipset handler IPFamily, create an ipset with the special option for ipv6 "family", "inet6".

This should be executed in several places where we call the RefreshSet

network policy type: ipBlock not working

Creating ipBlock of type ipv4 or ipv6 does not work because it tries to create an ipset of both ip address.

When creating an ipBlock with an ipv4 range, the error is:

Aborting sync. Failed to sync network policy chains: failed to perform ipset restore: ipset v7.6: Error in line 9: Syntax error: cannot parse 10.42.0.8: resolving to IPv6 address failed

When creating an ipBlock of an ipv6 range (/126), the error is:

Aborting sync. Failed to sync network policy chains: failed to perform ipset restore: ipset v7.6: Error in line 10: Syntax error: '126' is out of range 0-32

Wrong loop collecting the ips

In "pkg/controllers/netpol/policy.go" you have this loop:

                for ip := range policy.targetPods {
                        if utilsnet.IsIPv4String(ip) {
                                currnetPodIps[v1core.IPv4Protocol] = append(currnetPodIps[v1core.IPv4Protocol], ip)
                        }
                        if utilsnet.IsIPv6String(ip) {
                                currnetPodIps[v1core.IPv6Protocol] = append(currnetPodIps[v1core.IPv6Protocol], ip)
                        }
                }

However, policy.targetPods is a map, e.g. map[10.42.0.11:{[{10.42.0.11} {2001:cafe:42::b}]. Therefore, ip is always the ipv4 address (in the example 10.42.0.11) becuase it is the key of the map. We should do for _, pod := range policy.targetPods

Then, we get podInfo structs:

type podInfo struct {
        ips       []v1core.PodIP
        name      string
        namespace string
        labels    map[string]string
}

So we need an extra loop for the ips field. And then, we should use the IP field to get the string value. In summary:

                currnetPodIps := make(map[v1core.IPFamily][]string)
                for _, pod := range policy.targetPods {
                        for _, ip := range pod.ips {
                                if utilsnet.IsIPv4String(ip.IP) {
                                        currnetPodIps[v1core.IPv4Protocol] = append(currnetPodIps[v1core.IPv4Protocol], ip.IP)
                                }
                                if utilsnet.IsIPv6String(ip.IP) {
                                        currnetPodIps[v1core.IPv6Protocol] = append(currnetPodIps[v1core.IPv6Protocol], ip.IP)
                                }
                        }
                }

ipset names must be different for ipv6 and ipv4 ipsets

ipv4 ipsets require family inet and ipv6 ipsets require family inet6

Therefore, we need to create different ipsets for each type of address. To do so, the SHA that is part of the ipset name needs to be different and thus, we should include the ipFamily to it.

At the end of pkg/controllers/netpol/policy.go, we should add the ipFamily parameter to the SHA calculation to the first three functions:

func networkPolicyChainName(namespace, policyName string, version string, ipFamily api.IPFamily) string {
        hash := sha256.Sum256([]byte(namespace + policyName + version + string(ipFamily)))
        encoded := base32.StdEncoding.EncodeToString(hash[:])
        return kubeNetworkPolicyChainPrefix + encoded[:16]
}

func policySourcePodIPSetName(namespace, policyName string, ipFamily api.IPFamily) string {
        hash := sha256.Sum256([]byte(namespace + policyName + string(ipFamily)))
        encoded := base32.StdEncoding.EncodeToString(hash[:])
        return kubeSourceIPSetPrefix + encoded[:16]
}

func policyDestinationPodIPSetName(namespace, policyName string, ipFamily api.IPFamily) string {
        hash := sha256.Sum256([]byte(namespace + policyName + string(ipFamily)))
        encoded := base32.StdEncoding.EncodeToString(hash[:])
        return kubeDestinationIPSetPrefix + encoded[:16]

Of course, the places where we are calling these functions must be changed to include ipFamily (it's pretty easy as all calls to those functions have access to ipFamily)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.