Skip to content

Commit

Permalink
Enhance Submariner to use VxLAN Overlay Tunnels for inter-cluster tra…
Browse files Browse the repository at this point in the history
…ffic

As part of supporting Network policies and for ease of debugging, this
patch implements the following.

1. Creates VxLAN tunnels in the local Cluster between the worker nodes and
   the Cluster Gateway Node.
2. Programms the necessary iptable rules on the Cluster nodes to allow
   inter-cluster traffic.
3. This patch also avoids SNAT/MASQ for inter-cluster traffic, thereby
   preserving the original source ip of the POD all the way until the
   destination POD.
4. Programs the routing rules on the workerNodes to forward the remoteCluster
   traffic over the VxLAN interface that is created between the worker node
   and Cluster GatewayNode.

This patch depends on the following other patches

Depends-On: submariner-io#135
Depends-On: submariner-io/submariner-charts#3
Depends-On: submariner-io/submariner-charts#4
  • Loading branch information
sridhargaddam committed Sep 2, 2019
1 parent 23b52e3 commit 2661f34
Show file tree
Hide file tree
Showing 9 changed files with 597 additions and 173 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ require (
github.com/vishvananda/netlink v1.0.0
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect
golang.org/x/oauth2 v0.0.0-20170412232759-a6bd8cefa181 // indirect
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d // indirect
google.golang.org/appengine v1.6.1 // indirect
gopkg.in/inf.v0 v0.0.0-20150911125757-3887ee99ecf0 // indirect
Expand Down
7 changes: 7 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415 h1:WSBJMqJbLxsn+bTCP
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v0.0.0-20160524151835-7d79101e329e h1:JHB7F/4TJCrYBW8+GZO8VkWDj1jxcWuCl6uxKODiyi4=
Expand Down Expand Up @@ -44,6 +45,8 @@ github.com/onsi/ginkgo v0.0.0-20190716150225-054541502288 h1:IrDHY8COHGFX/oYjUAS
github.com/onsi/ginkgo v0.0.0-20190716150225-054541502288/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.1 h1:PZSj/UFNaVp3KxrzHOcS7oyuWA7LoOY/77yCTEFu21U=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/peterbourgon/diskv v0.0.0-20170814173558-5f041e8faa00 h1:Eh2O8DyYbAkNbZIaLTCBoVsAtq0Pl4ocJ4fkiJschDE=
Expand All @@ -65,13 +68,16 @@ github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmF
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65 h1:+rhAzEzT3f4JtomfC371qB+0Ola2caSKcY69NUBZrRQ=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/oauth2 v0.0.0-20170412232759-a6bd8cefa181 h1:/4OaQ4bC66Oq9JDhUnxTjBGt8XBhDuwgMRXHgvfcCUY=
golang.org/x/oauth2 v0.0.0-20170412232759-a6bd8cefa181/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c h1:+EXw7AwNOKzPFXMZ1yNjO40aWCh3PIquJB2fYlv9wcs=
Expand All @@ -93,6 +99,7 @@ gopkg.in/inf.v0 v0.0.0-20150911125757-3887ee99ecf0 h1:i7QXw9V4kT12caRHrtj3yY751k
gopkg.in/inf.v0 v0.0.0-20150911125757-3887ee99ecf0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
k8s.io/api v0.0.0-20190222213804-5cb15d344471 h1:MzQGt8qWQCR+39kbYRd0uQqsvSidpYqJLFeWiJ9l4OE=
Expand Down
120 changes: 1 addition & 119 deletions pkg/cableengine/ipsec/ipsec.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@ package ipsec

import (
"fmt"
"net"
"reflect"
"strings"
"sync"

"github.com/coreos/go-iptables/iptables"
"github.com/submariner-io/submariner/pkg/cableengine"
"github.com/submariner-io/submariner/pkg/types"
"github.com/submariner-io/submariner/pkg/util"
Expand Down Expand Up @@ -39,62 +36,6 @@ func NewEngine(localSubnets []string, localCluster types.SubmarinerCluster, loca

func (i *engine) StartEngine() error {
klog.Infof("Starting IPSec Engine (Charon)")
ifi, err := util.GetDefaultGatewayInterface()
if err != nil {
return err
}

klog.V(8).Infof("Device of default gateway interface was %s", ifi.Name)
ipt, err := iptables.New()
if err != nil {
return fmt.Errorf("error while initializing iptables: %v", err)
}

klog.V(6).Infof("Installing/ensuring the SUBMARINER-POSTROUTING and SUBMARINER-FORWARD chains")
if err = ipt.NewChain("nat", "SUBMARINER-POSTROUTING"); err != nil {
klog.Errorf("Unable to create SUBMARINER-POSTROUTING chain in iptables: %v", err)
}

if err = ipt.NewChain("filter", "SUBMARINER-FORWARD"); err != nil {
klog.Errorf("Unable to create SUBMARINER-FORWARD chain in iptables: %v", err)
}

forwardToSubPostroutingRuleSpec := []string{"-j", "SUBMARINER-POSTROUTING"}
if err = ipt.AppendUnique("nat", "POSTROUTING", forwardToSubPostroutingRuleSpec...); err != nil {
klog.Errorf("Unable to append iptables rule \"%s\": %v\n", strings.Join(forwardToSubPostroutingRuleSpec, " "), err)
}

forwardToSubForwardRuleSpec := []string{"-j", "SUBMARINER-FORWARD"}
rules, err := ipt.List("filter", "FORWARD")
if err != nil {
return fmt.Errorf("error listing the rules in FORWARD chain: %v", err)
}

appendAt := len(rules) + 1
insertAt := appendAt
for i, rule := range rules {
if rule == "-A FORWARD -j SUBMARINER-FORWARD" {
insertAt = -1
break
} else if rule == "-A FORWARD -j REJECT --reject-with icmp-host-prohibited" {
insertAt = i
break
}
}

if insertAt == appendAt {
// Append the rule at the end of FORWARD Chain.
if err = ipt.Append("filter", "FORWARD", forwardToSubForwardRuleSpec...); err != nil {
klog.Errorf("Unable to append iptables rule \"%s\": %v\n", strings.Join(forwardToSubForwardRuleSpec, " "), err)
}
} else if insertAt > 0 {
// Insert the rule in the FORWARD Chain.
if err = ipt.Insert("filter", "FORWARD", insertAt, forwardToSubForwardRuleSpec...); err != nil {
klog.Errorf("Unable to insert iptables rule \"%s\" at position %d: %v\n", strings.Join(forwardToSubForwardRuleSpec, " "),
insertAt, err)
}
}

return i.driver.Init()
}

Expand Down Expand Up @@ -131,66 +72,7 @@ func (i *engine) InstallCable(endpoint types.SubmarinerEndpoint) error {
if err != nil {
return err
}

ifi, err := util.GetDefaultGatewayInterface()
if err != nil {
return err
}
klog.V(4).Infof("Device of default gateway interface was %s", ifi.Name)
ipt, err := iptables.New()
if err != nil {
return fmt.Errorf("error while initializing iptables: %v", err)
}

addresses, err := ifi.Addrs()
if err != nil {
return err
}

for _, addr := range addresses {
ipAddr, ipNet, err := net.ParseCIDR(addr.String())
if err != nil {
klog.Errorf("Error while parsing CIDR %s: %v", addr.String(), err)
continue
}

if ipAddr.To4() != nil {
for _, subnet := range endpoint.Spec.Subnets {
ruleSpec := []string{"-s", ipNet.String(), "-d", subnet, "-i", ifi.Name, "-j", "ACCEPT"}
klog.V(8).Infof("Installing iptables rule: %s", strings.Join(ruleSpec, " "))
if err = ipt.AppendUnique("filter", "SUBMARINER-FORWARD", ruleSpec...); err != nil {
klog.Errorf("error appending iptables rule \"%s\": %v\n", strings.Join(ruleSpec, " "), err)
}

ruleSpec = []string{"-d", ipNet.String(), "-s", subnet, "-i", ifi.Name, "-j", "ACCEPT"}
klog.V(8).Infof("Installing iptables rule: %v", ruleSpec)
if err = ipt.AppendUnique("filter", "SUBMARINER-FORWARD", ruleSpec...); err != nil {
klog.Errorf("error appending iptables rule \"%s\": %v\n", strings.Join(ruleSpec, " "), err)
}

// -t nat -I POSTROUTING -s <local-network-cidr> -d <remote-cidr> -j SNAT --to-source <this-local-ip>
ruleSpec = []string{"-s", ipNet.String(), "-d", subnet, "-j", "SNAT", "--to-source", ipAddr.String()}
klog.V(8).Infof("Installing iptables rule: %s", strings.Join(ruleSpec, " "))
if err = ipt.AppendUnique("nat", "SUBMARINER-POSTROUTING", ruleSpec...); err != nil {
klog.Errorf("error appending iptables rule \"%s\": %v\n", strings.Join(ruleSpec, " "), err)
}
}
} else {
klog.V(6).Infof("Skipping adding rule because IPv6 network %s found", ipNet.String())
}
}

// MASQUERADE (on the GatewayNode) the incoming traffic from the remote cluster (i.e, remoteEndpointIP)
// and destined to the local PODs (i.e., localSubnet) scheduled on the non-gateway node.
// This will make the return traffic from the POD to go via the GatewayNode.
for _, localSubnet := range i.localSubnets {
ruleSpec := []string{"-s", remoteEndpointIP, "-d", localSubnet, "-j", "MASQUERADE"}
klog.V(8).Infof("Installing iptables rule for MASQ incoming traffic: %v", ruleSpec)
if err = ipt.AppendUnique("nat", "SUBMARINER-POSTROUTING", ruleSpec...); err != nil {
klog.Errorf("error appending iptables MASQ rule \"%s\": %v\n", strings.Join(ruleSpec, " "), err)
}
}

klog.V(4).Infof("Connected to remoteEndpointIP %s", remoteEndpointIP)
return nil
}

Expand Down
91 changes: 91 additions & 0 deletions pkg/routeagent/controllers/route/iptables.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package route

import (
"fmt"
"strings"

"github.com/coreos/go-iptables/iptables"
"k8s.io/klog"
)

func (r *Controller) createIPTableChains() error {
ipt, err := iptables.New()
if err != nil {
klog.Errorf("Error while initializing iptables: %v", err)
return err
}

klog.V(4).Infof("Install/ensure %s chain exists", SM_POSTROUTING_CHAIN)
if err = ipt.NewChain("nat", SM_POSTROUTING_CHAIN); err != nil {
klog.Errorf("Unable to create %s chain in iptables: %v", SM_POSTROUTING_CHAIN, err)
}

klog.V(4).Infof("Insert %s rule that has rules for inter-cluster traffic", SM_POSTROUTING_CHAIN)
forwardToSubPostroutingRuleSpec := []string{"-j", SM_POSTROUTING_CHAIN}
if err = r.insertUnique(ipt, "nat", "POSTROUTING", 1, forwardToSubPostroutingRuleSpec); err != nil {
klog.Errorf("Unable to insert iptable rule in NAT table, POSTROUTING chain: %v", err)
}

klog.V(4).Infof("Install/ensure SUBMARINER-INPUT chain exists")
if err = ipt.NewChain("filter", "SUBMARINER-INPUT"); err != nil {
klog.Errorf("Unable to create SUBMARINER-INPUT chain in iptables: %v", err)
}

forwardToSubInputRuleSpec := []string{"-p", "udp", "-m", "udp", "-j", "SUBMARINER-INPUT"}
if err = ipt.AppendUnique("filter", "INPUT", forwardToSubInputRuleSpec...); err != nil {
klog.Errorf("Unable to append iptables rule \"%s\": %v\n", strings.Join(forwardToSubInputRuleSpec, " "), err)
}

klog.V(4).Infof("Allow VxLAN incoming traffic in SUBMARINER-INPUT Chain")
ruleSpec := []string{"-p", "udp", "-m", "udp", "--dport", VXLAN_PORT, "-j", "ACCEPT"}
if err = ipt.AppendUnique("filter", "SUBMARINER-INPUT", ruleSpec...); err != nil {
klog.Errorf("Unable to append iptables rule \"%s\": %v\n", strings.Join(ruleSpec, " "), err)
}

klog.V(4).Infof("Insert rule to allow traffic over %s interface in FORWARDing Chain", VXLAN_IFACE)
ruleSpec = []string{"-o", VXLAN_IFACE, "-j", "ACCEPT"}
if err = r.insertUnique(ipt, "filter", "FORWARD", 1, ruleSpec); err != nil {
klog.Errorf("Unable to insert iptable rule in filter table to allow vxlan traffic: %v", err)
}

return nil
}

func (r *Controller) programIptableRulesForInterClusterTraffic(remoteCidrBlock string) {
ipt, err := iptables.New()
if err != nil {
klog.Errorf("error while initializing iptables: %v", err)
}

for _, localClusterCidr := range r.localClusterCidr {
ruleSpec := []string{"-s", localClusterCidr, "-d", remoteCidrBlock, "-j", "ACCEPT"}
klog.V(4).Infof("Installing iptables rule for outgoing traffic: %s", strings.Join(ruleSpec, " "))
if err = ipt.AppendUnique("nat", SM_POSTROUTING_CHAIN, ruleSpec...); err != nil {
klog.Errorf("error appending iptables rule \"%s\": %v\n", strings.Join(ruleSpec, " "), err)
}

// Todo: revisit we only have to program to the PODCidr
ruleSpec = []string{"-s", remoteCidrBlock, "-d", localClusterCidr, "-j", "ACCEPT"}
klog.V(4).Infof("Installing iptables rule for incoming traffic: %s", strings.Join(ruleSpec, " "))
if err = ipt.AppendUnique("nat", SM_POSTROUTING_CHAIN, ruleSpec...); err != nil {
klog.Errorf("error appending iptables rule \"%s\": %v\n", strings.Join(ruleSpec, " "), err)
}
}
}

func (r *Controller) insertUnique(ipt *iptables.IPTables, table string, chain string, position int, ruleSpec []string) error {
rules, err := ipt.List(table, chain)
if err != nil {
return fmt.Errorf("error listing the rules in %s chain: %v", chain, err)
}

if strings.Contains(rules[position], strings.Join(ruleSpec, " ")) {
klog.V(4).Infof("In %s table, iptables rule \"%s\", already exists.", table, strings.Join(ruleSpec, " "))
return nil
} else {
if err = ipt.Insert(table, chain, position, ruleSpec...); err != nil {
klog.Errorf("In %s table, unable to insert iptables rule \"%s\": %v\n", table, strings.Join(ruleSpec, " "), err)
}
}
return nil
}
Loading

0 comments on commit 2661f34

Please sign in to comment.