Procházet zdrojové kódy

pkg/mesh/routes.go: add flag for generic ACCEPT in FORWARD chain (#244)

* pkg/mesh/routes.go: add flag for generic ACCEPT in FORWARD chain

Some linux distros or docker will set the default policy in the FORWARD
chain in the filter table to DROP. With the new ip-tables-forward-rules
flag a generic ACCEPT for all packages going from and to the pod subnet
is added to the FORWARD chain.

Signed-off-by: leonnicolas <leonloechner@gmx.de>

* Update cmd/kg/main.go

Co-authored-by: Lucas Servén Marín <lserven@gmail.com>

* Update cmd/kg/main.go

Co-authored-by: Lucas Servén Marín <lserven@gmail.com>
leonnicolas před 4 roky
rodič
revize
9b14c227a9
3 změnil soubory, kde provedl 56 přidání a 48 odebrání
  1. 4 2
      cmd/kg/main.go
  2. 47 45
      pkg/mesh/mesh.go
  3. 5 1
      pkg/mesh/routes.go

+ 4 - 2
cmd/kg/main.go

@@ -111,6 +111,7 @@ var (
 	port                  uint
 	port                  uint
 	subnet                string
 	subnet                string
 	resyncPeriod          time.Duration
 	resyncPeriod          time.Duration
+	iptablesForwardRule   bool
 	prioritisePrivateAddr bool
 	prioritisePrivateAddr bool
 
 
 	printVersion bool
 	printVersion bool
@@ -140,7 +141,8 @@ func init() {
 	cmd.Flags().UintVar(&port, "port", mesh.DefaultKiloPort, "The port over which WireGuard peers should communicate.")
 	cmd.Flags().UintVar(&port, "port", mesh.DefaultKiloPort, "The port over which WireGuard peers should communicate.")
 	cmd.Flags().StringVar(&subnet, "subnet", mesh.DefaultKiloSubnet.String(), "CIDR from which to allocate addresses for WireGuard interfaces.")
 	cmd.Flags().StringVar(&subnet, "subnet", mesh.DefaultKiloSubnet.String(), "CIDR from which to allocate addresses for WireGuard interfaces.")
 	cmd.Flags().DurationVar(&resyncPeriod, "resync-period", 30*time.Second, "How often should the Kilo controllers reconcile?")
 	cmd.Flags().DurationVar(&resyncPeriod, "resync-period", 30*time.Second, "How often should the Kilo controllers reconcile?")
-	cmd.Flags().BoolVar(&prioritisePrivateAddr, "prioritise-private-addresses", false, "Prefer to assign a private IP address to the node's endpoint")
+	cmd.Flags().BoolVar(&iptablesForwardRule, "iptables-forward-rules", false, "Add default accept rules to the FORWARD chain in iptables. Warning: this may break firewalls with a deny all policy and is potentially insecure!")
+	cmd.Flags().BoolVar(&prioritisePrivateAddr, "prioritise-private-addresses", false, "Prefer to assign a private IP address to the node's endpoint.")
 
 
 	cmd.PersistentFlags().BoolVar(&printVersion, "version", false, "Print version and exit")
 	cmd.PersistentFlags().BoolVar(&printVersion, "version", false, "Print version and exit")
 	cmd.PersistentFlags().StringVar(&logLevel, "log-level", logLevelInfo, fmt.Sprintf("Log level to use. Possible values: %s", availableLogLevels))
 	cmd.PersistentFlags().StringVar(&logLevel, "log-level", logLevelInfo, fmt.Sprintf("Log level to use. Possible values: %s", availableLogLevels))
@@ -236,7 +238,7 @@ func runRoot(_ *cobra.Command, _ []string) error {
 		return fmt.Errorf("backend %v unknown; possible values are: %s", backend, availableBackends)
 		return fmt.Errorf("backend %v unknown; possible values are: %s", backend, availableBackends)
 	}
 	}
 
 
-	m, err := mesh.New(b, enc, gr, hostname, uint32(port), s, local, cni, cniPath, iface, cleanUpIface, createIface, mtu, resyncPeriod, prioritisePrivateAddr, log.With(logger, "component", "kilo"))
+	m, err := mesh.New(b, enc, gr, hostname, uint32(port), s, local, cni, cniPath, iface, cleanUpIface, createIface, mtu, resyncPeriod, prioritisePrivateAddr, iptablesForwardRule, log.With(logger, "component", "kilo"))
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("failed to create Kilo mesh: %v", err)
 		return fmt.Errorf("failed to create Kilo mesh: %v", err)
 	}
 	}

+ 47 - 45
pkg/mesh/mesh.go

@@ -49,27 +49,28 @@ const (
 // Mesh is able to create Kilo network meshes.
 // Mesh is able to create Kilo network meshes.
 type Mesh struct {
 type Mesh struct {
 	Backend
 	Backend
-	cleanUpIface bool
-	cni          bool
-	cniPath      string
-	enc          encapsulation.Encapsulator
-	externalIP   *net.IPNet
-	granularity  Granularity
-	hostname     string
-	internalIP   *net.IPNet
-	ipTables     *iptables.Controller
-	kiloIface    int
-	key          []byte
-	local        bool
-	port         uint32
-	priv         []byte
-	privIface    int
-	pub          []byte
-	resyncPeriod time.Duration
-	stop         chan struct{}
-	subnet       *net.IPNet
-	table        *route.Table
-	wireGuardIP  *net.IPNet
+	cleanUpIface        bool
+	cni                 bool
+	cniPath             string
+	enc                 encapsulation.Encapsulator
+	externalIP          *net.IPNet
+	granularity         Granularity
+	hostname            string
+	internalIP          *net.IPNet
+	ipTables            *iptables.Controller
+	kiloIface           int
+	key                 []byte
+	local               bool
+	port                uint32
+	priv                []byte
+	privIface           int
+	pub                 []byte
+	resyncPeriod        time.Duration
+	iptablesForwardRule bool
+	stop                chan struct{}
+	subnet              *net.IPNet
+	table               *route.Table
+	wireGuardIP         *net.IPNet
 
 
 	// nodes and peers are mutable fields in the struct
 	// nodes and peers are mutable fields in the struct
 	// and need to be guarded.
 	// and need to be guarded.
@@ -86,7 +87,7 @@ type Mesh struct {
 }
 }
 
 
 // New returns a new Mesh instance.
 // New returns a new Mesh instance.
-func New(backend Backend, enc encapsulation.Encapsulator, granularity Granularity, hostname string, port uint32, subnet *net.IPNet, local, cni bool, cniPath, iface string, cleanUpIface bool, createIface bool, mtu uint, resyncPeriod time.Duration, prioritisePrivateAddr bool, logger log.Logger) (*Mesh, error) {
+func New(backend Backend, enc encapsulation.Encapsulator, granularity Granularity, hostname string, port uint32, subnet *net.IPNet, local, cni bool, cniPath, iface string, cleanUpIface bool, createIface bool, mtu uint, resyncPeriod time.Duration, prioritisePrivateAddr, iptablesForwardRule bool, logger log.Logger) (*Mesh, error) {
 	if err := os.MkdirAll(kiloPath, 0700); err != nil {
 	if err := os.MkdirAll(kiloPath, 0700); err != nil {
 		return nil, fmt.Errorf("failed to create directory to store configuration: %v", err)
 		return nil, fmt.Errorf("failed to create directory to store configuration: %v", err)
 	}
 	}
@@ -155,28 +156,29 @@ func New(backend Backend, enc encapsulation.Encapsulator, granularity Granularit
 		return nil, fmt.Errorf("failed to IP tables controller: %v", err)
 		return nil, fmt.Errorf("failed to IP tables controller: %v", err)
 	}
 	}
 	return &Mesh{
 	return &Mesh{
-		Backend:      backend,
-		cleanUpIface: cleanUpIface,
-		cni:          cni,
-		cniPath:      cniPath,
-		enc:          enc,
-		externalIP:   externalIP,
-		granularity:  granularity,
-		hostname:     hostname,
-		internalIP:   privateIP,
-		ipTables:     ipTables,
-		kiloIface:    kiloIface,
-		nodes:        make(map[string]*Node),
-		peers:        make(map[string]*Peer),
-		port:         port,
-		priv:         private,
-		privIface:    privIface,
-		pub:          public,
-		resyncPeriod: resyncPeriod,
-		local:        local,
-		stop:         make(chan struct{}),
-		subnet:       subnet,
-		table:        route.NewTable(),
+		Backend:             backend,
+		cleanUpIface:        cleanUpIface,
+		cni:                 cni,
+		cniPath:             cniPath,
+		enc:                 enc,
+		externalIP:          externalIP,
+		granularity:         granularity,
+		hostname:            hostname,
+		internalIP:          privateIP,
+		ipTables:            ipTables,
+		kiloIface:           kiloIface,
+		nodes:               make(map[string]*Node),
+		peers:               make(map[string]*Peer),
+		port:                port,
+		priv:                private,
+		privIface:           privIface,
+		pub:                 public,
+		resyncPeriod:        resyncPeriod,
+		iptablesForwardRule: iptablesForwardRule,
+		local:               local,
+		stop:                make(chan struct{}),
+		subnet:              subnet,
+		table:               route.NewTable(),
 		errorCounter: prometheus.NewCounterVec(prometheus.CounterOpts{
 		errorCounter: prometheus.NewCounterVec(prometheus.CounterOpts{
 			Name: "kilo_errors_total",
 			Name: "kilo_errors_total",
 			Help: "Number of errors that occurred while administering the mesh.",
 			Help: "Number of errors that occurred while administering the mesh.",
@@ -498,7 +500,7 @@ func (m *Mesh) applyTopology() {
 		m.errorCounter.WithLabelValues("apply").Inc()
 		m.errorCounter.WithLabelValues("apply").Inc()
 		return
 		return
 	}
 	}
-	ipRules := t.Rules(m.cni)
+	ipRules := t.Rules(m.cni, m.iptablesForwardRule)
 	// If we are handling local routes, ensure the local
 	// If we are handling local routes, ensure the local
 	// tunnel has an IP address and IPIP traffic is allowed.
 	// tunnel has an IP address and IPIP traffic is allowed.
 	if m.enc.Strategy() != encapsulation.Never && m.local {
 	if m.enc.Strategy() != encapsulation.Never && m.local {

+ 5 - 1
pkg/mesh/routes.go

@@ -242,12 +242,16 @@ func encapsulateRoute(route *netlink.Route, encapsulate encapsulation.Strategy,
 }
 }
 
 
 // Rules returns the iptables rules required by the local node.
 // Rules returns the iptables rules required by the local node.
-func (t *Topology) Rules(cni bool) []iptables.Rule {
+func (t *Topology) Rules(cni, iptablesForwardRule bool) []iptables.Rule {
 	var rules []iptables.Rule
 	var rules []iptables.Rule
 	rules = append(rules, iptables.NewIPv4Chain("nat", "KILO-NAT"))
 	rules = append(rules, iptables.NewIPv4Chain("nat", "KILO-NAT"))
 	rules = append(rules, iptables.NewIPv6Chain("nat", "KILO-NAT"))
 	rules = append(rules, iptables.NewIPv6Chain("nat", "KILO-NAT"))
 	if cni {
 	if cni {
 		rules = append(rules, iptables.NewRule(iptables.GetProtocol(len(t.subnet.IP)), "nat", "POSTROUTING", "-s", t.subnet.String(), "-m", "comment", "--comment", "Kilo: jump to KILO-NAT chain", "-j", "KILO-NAT"))
 		rules = append(rules, iptables.NewRule(iptables.GetProtocol(len(t.subnet.IP)), "nat", "POSTROUTING", "-s", t.subnet.String(), "-m", "comment", "--comment", "Kilo: jump to KILO-NAT chain", "-j", "KILO-NAT"))
+		if iptablesForwardRule {
+			rules = append(rules, iptables.NewRule(iptables.GetProtocol(len(t.subnet.IP)), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets from the pod subnet", "-s", t.subnet.String(), "-j", "ACCEPT"))
+			rules = append(rules, iptables.NewRule(iptables.GetProtocol(len(t.subnet.IP)), "filter", "FORWARD", "-m", "comment", "--comment", "Kilo: forward packets to the pod subnet", "-d", t.subnet.String(), "-j", "ACCEPT"))
+		}
 	}
 	}
 	for _, s := range t.segments {
 	for _, s := range t.segments {
 		rules = append(rules, iptables.NewRule(iptables.GetProtocol(len(s.wireGuardIP)), "nat", "KILO-NAT", "-d", oneAddressCIDR(s.wireGuardIP).String(), "-m", "comment", "--comment", "Kilo: do not NAT packets destined for WireGuared IPs", "-j", "RETURN"))
 		rules = append(rules, iptables.NewRule(iptables.GetProtocol(len(s.wireGuardIP)), "nat", "KILO-NAT", "-d", oneAddressCIDR(s.wireGuardIP).String(), "-m", "comment", "--comment", "Kilo: do not NAT packets destined for WireGuared IPs", "-j", "RETURN"))