Browse Source

Factor out installing IP masquerading out of backends

This is an attempt to have the same IP masquerading rules
across all backends. They work purely on address ranges and
without interface names.

Practically, VXLAN now has IP masquerade support.

Fixes #101
Eugene Yakubovich 10 years ago
parent
commit
9d8c330ea4
7 changed files with 67 additions and 92 deletions
  1. 1 1
      backend/alloc/alloc.go
  2. 1 1
      backend/common.go
  3. 1 37
      backend/hostgw/hostgw.go
  4. 3 44
      backend/udp/udp.go
  5. 5 2
      backend/vxlan/vxlan.go
  6. 42 0
      ipmasq.go
  7. 14 7
      main.go

+ 1 - 1
backend/alloc/alloc.go

@@ -23,7 +23,7 @@ func New(sm *subnet.SubnetManager) backend.Backend {
 	}
 }
 
-func (m *AllocBackend) Init(extIface *net.Interface, extIP net.IP, ipMasq bool) (*backend.SubnetDef, error) {
+func (m *AllocBackend) Init(extIface *net.Interface, extIP net.IP) (*backend.SubnetDef, error) {
 	attrs := subnet.LeaseAttrs{
 		PublicIP: ip.FromIP(extIP),
 	}

+ 1 - 1
backend/common.go

@@ -12,7 +12,7 @@ type SubnetDef struct {
 }
 
 type Backend interface {
-	Init(extIface *net.Interface, extIP net.IP, ipMasq bool) (*SubnetDef, error)
+	Init(extIface *net.Interface, extIP net.IP) (*SubnetDef, error)
 	Run()
 	Stop()
 	Name() string

+ 1 - 37
backend/hostgw/hostgw.go

@@ -3,7 +3,6 @@ package hostgw
 import (
 	"fmt"
 	"net"
-	"strings"
 	"sync"
 
 	log "github.com/coreos/flannel/Godeps/_workspace/src/github.com/golang/glog"
@@ -31,7 +30,7 @@ func New(sm *subnet.SubnetManager) backend.Backend {
 	return b
 }
 
-func (rb *HostgwBackend) Init(extIface *net.Interface, extIP net.IP, ipMasq bool) (*backend.SubnetDef, error) {
+func (rb *HostgwBackend) Init(extIface *net.Interface, extIP net.IP) (*backend.SubnetDef, error) {
 	rb.extIface = extIface
 	rb.extIP = extIP
 
@@ -49,13 +48,6 @@ func (rb *HostgwBackend) Init(extIface *net.Interface, extIP net.IP, ipMasq bool
 		}
 	}
 
-	if ipMasq {
-		if err := setupIpMasq(sn, rb.sm.GetConfig().Network); err != nil {
-			return nil, fmt.Errorf("Failed to configure ip-masq: %v", err)
-		}
-
-	}
-
 	/* NB: docker will create the local route to `sn` */
 
 	return &backend.SubnetDef{
@@ -144,31 +136,3 @@ func (rb *HostgwBackend) handleSubnetEvents(batch subnet.EventBatch) {
 		}
 	}
 }
-
-func setupIpMasq(localNet ip.IP4Net, overlayNet ip.IP4Net) error {
-	ipt, err := ip.NewIPTables()
-	if err != nil {
-		return err
-	}
-
-	err = ipt.ClearChain("nat", "FLANNEL")
-	if err != nil {
-		return fmt.Errorf("Failed to create/clear FLANNEL chain in NAT table: %v", err)
-	}
-
-	rules := [][]string{
-		[]string{"FLANNEL", "-s", localNet.String(), "-o", "lo", "-j", "ACCEPT"},
-		[]string{"FLANNEL", "-s", localNet.String(), "!", "-d", overlayNet.String(), "-j", "MASQUERADE"},
-		[]string{"POSTROUTING", "-s", localNet.String(), "-j", "FLANNEL"},
-	}
-
-	for _, args := range rules {
-		log.Info("Adding iptables rule: ", strings.Join(args, " "))
-
-		if err := ipt.AppendUnique("nat", args...); err != nil {
-			return fmt.Errorf("Failed to insert IP masquerade rule: %v", err)
-		}
-	}
-
-	return nil
-}

+ 3 - 44
backend/udp/udp.go

@@ -5,7 +5,6 @@ import (
 	"encoding/json"
 	"net"
 	"os"
-	"strings"
 	"sync"
 	"syscall"
 
@@ -49,7 +48,7 @@ func New(sm *subnet.SubnetManager, config json.RawMessage) backend.Backend {
 	return &be
 }
 
-func (m *UdpBackend) Init(extIface *net.Interface, extIP net.IP, ipMasq bool) (*backend.SubnetDef, error) {
+func (m *UdpBackend) Init(extIface *net.Interface, extIP net.IP) (*backend.SubnetDef, error) {
 	// Parse our configuration
 	if len(m.rawCfg) > 0 {
 		if err := json.Unmarshal(m.rawCfg, &m.cfg); err != nil {
@@ -81,7 +80,7 @@ func (m *UdpBackend) Init(extIface *net.Interface, extIP net.IP, ipMasq bool) (*
 	// TUN MTU will be smaller b/c of encap (IP+UDP hdrs)
 	m.mtu = extIface.MTU - encapOverhead
 
-	if err = m.initTun(ipMasq); err != nil {
+	if err = m.initTun(); err != nil {
 		return nil, err
 	}
 
@@ -143,7 +142,7 @@ func newCtlSockets() (*os.File, *os.File, error) {
 	return f1, f2, nil
 }
 
-func (m *UdpBackend) initTun(ipMasq bool) error {
+func (m *UdpBackend) initTun() error {
 	var tunName string
 	var err error
 
@@ -157,13 +156,6 @@ func (m *UdpBackend) initTun(ipMasq bool) error {
 		return err
 	}
 
-	if ipMasq {
-		err = setupIpMasq(m.tunNet.Network(), tunName)
-		if err != nil {
-			return err
-		}
-	}
-
 	return nil
 }
 
@@ -202,39 +194,6 @@ func configureIface(ifname string, ipn ip.IP4Net, mtu int) error {
 	return nil
 }
 
-func setupIpMasq(ipn ip.IP4Net, iface string) error {
-	ipt, err := ip.NewIPTables()
-	if err != nil {
-		return fmt.Errorf("failed to setup IP Masquerade. iptables was not found")
-	}
-
-	err = ipt.ClearChain("nat", "FLANNEL")
-	if err != nil {
-		return fmt.Errorf("Failed to create/clear FLANNEL chain in NAT table: %v", err)
-	}
-
-	rules := [][]string{
-		// This rule makes sure we don't NAT traffic within overlay network (e.g. coming out of docker0)
-		[]string{"FLANNEL", "-d", ipn.String(), "-j", "ACCEPT"},
-		// This rule makes sure we don't NAT multicast traffic within overlay network
-		[]string{"FLANNEL", "-d", "224.0.0.0/4", "-j", "ACCEPT"}, // This rule will NAT everything originating from our overlay network and
-		[]string{"FLANNEL", "!", "-o", iface, "-j", "MASQUERADE"},
-		// This rule will take everything coming from overlay and sent it to FLANNEL chain
-		[]string{"POSTROUTING", "-s", ipn.String(), "-j", "FLANNEL"},
-	}
-
-	for _, args := range rules {
-		log.Info("Adding iptables rule: ", strings.Join(args, " "))
-
-		err = ipt.AppendUnique("nat", args...)
-		if err != nil {
-			return fmt.Errorf("Failed to insert IP masquerade rule: %v", err)
-		}
-	}
-
-	return nil
-}
-
 func (m *UdpBackend) monitorEvents() {
 	log.Info("Watching for new subnet leases")
 

+ 5 - 2
backend/vxlan/vxlan.go

@@ -56,7 +56,7 @@ func newSubnetAttrs(pubIP net.IP, mac net.HardwareAddr) (*subnet.LeaseAttrs, err
 	}, nil
 }
 
-func (vb *VXLANBackend) Init(extIface *net.Interface, extIP net.IP, ipMasq bool) (*backend.SubnetDef, error) {
+func (vb *VXLANBackend) Init(extIface *net.Interface, extIP net.IP) (*backend.SubnetDef, error) {
 	// Parse our configuration
 	if len(vb.rawCfg) > 0 {
 		if err := json.Unmarshal(vb.rawCfg, &vb.cfg); err != nil {
@@ -102,7 +102,10 @@ func (vb *VXLANBackend) Init(extIface *net.Interface, extIP net.IP, ipMasq bool)
 		return nil, err
 	}
 
-	return &backend.SubnetDef{sn, vb.dev.MTU()}, nil
+	return &backend.SubnetDef{
+		Net: sn,
+		MTU: vb.dev.MTU(),
+	}, nil
 }
 
 func (vb *VXLANBackend) Run() {

+ 42 - 0
ipmasq.go

@@ -0,0 +1,42 @@
+package main
+
+import (
+	"fmt"
+	"strings"
+
+	log "github.com/coreos/flannel/Godeps/_workspace/src/github.com/golang/glog"
+
+	"github.com/coreos/flannel/pkg/ip"
+)
+
+func setupIPMasq(ipn ip.IP4Net) error {
+	ipt, err := ip.NewIPTables()
+	if err != nil {
+		return fmt.Errorf("failed to setup IP Masquerade. iptables was not found")
+	}
+
+	err = ipt.ClearChain("nat", "FLANNEL")
+	if err != nil {
+		return fmt.Errorf("Failed to create/clear FLANNEL chain in NAT table: %v", err)
+	}
+
+	rules := [][]string{
+		// This rule makes sure we don't NAT traffic within overlay network (e.g. coming out of docker0)
+		{"FLANNEL", "-d", ipn.String(), "-j", "ACCEPT"},
+		// NAT if it's not multicast traffic
+		{"FLANNEL", "!", "-d", "224.0.0.0/4", "-j", "MASQUERADE"},
+		// This rule will take everything coming from overlay and sent it to FLANNEL chain
+		{"POSTROUTING", "-s", ipn.String(), "-j", "FLANNEL"},
+	}
+
+	for _, args := range rules {
+		log.Info("Adding iptables rule: ", strings.Join(args, " "))
+
+		err = ipt.AppendUnique("nat", args...)
+		if err != nil {
+			return fmt.Errorf("Failed to insert IP masquerade rule: %v", err)
+		}
+	}
+
+	return nil
+}

+ 14 - 7
main.go

@@ -135,7 +135,7 @@ func lookupIface() (*net.Interface, net.IP, error) {
 	return iface, ipaddr, nil
 }
 
-func makeSubnetManager() *subnet.SubnetManager {
+func newSubnetManager() *subnet.SubnetManager {
 	peers := strings.Split(opts.etcdEndpoints, ",")
 
 	cfg := &subnet.EtcdConfig{
@@ -157,8 +157,7 @@ func makeSubnetManager() *subnet.SubnetManager {
 	}
 }
 
-func newBackend() (backend.Backend, error) {
-	sm := makeSubnetManager()
+func newBackend(sm *subnet.SubnetManager) (backend.Backend, error) {
 	config := sm.GetConfig()
 
 	var bt struct {
@@ -187,7 +186,7 @@ func newBackend() (backend.Backend, error) {
 	}
 }
 
-func run(be backend.Backend, exit chan int) {
+func run(sm *subnet.SubnetManager, be backend.Backend, exit chan int) {
 	var err error
 	defer func() {
 		if err == nil || err == task.ErrCanceled {
@@ -210,11 +209,18 @@ func run(be backend.Backend, exit chan int) {
 
 	log.Infof("Using %s as external interface", ipaddr)
 
-	sn, err := be.Init(iface, ipaddr, opts.ipMasq)
+	sn, err := be.Init(iface, ipaddr)
 	if err != nil {
 		return
 	}
 
+	if opts.ipMasq {
+		flannelNet := sm.GetConfig().Network
+		if err = setupIPMasq(flannelNet); err != nil {
+			return
+		}
+	}
+
 	writeSubnetFile(sn)
 	daemon.SdNotify("READY=1")
 
@@ -243,7 +249,8 @@ func main() {
 
 	flagsFromEnv("FLANNELD", flag.CommandLine)
 
-	be, err := newBackend()
+	sm := newSubnetManager()
+	be, err := newBackend(sm)
 	if err != nil {
 		log.Info(err)
 		os.Exit(1)
@@ -255,7 +262,7 @@ func main() {
 	signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)
 
 	exit := make(chan int)
-	go run(be, exit)
+	go run(sm, be, exit)
 
 	for {
 		select {