Explorar o código

Add a filter chain to allow persistent rules

Allow users to configure firewall policies in a way that persists
docker operations/restarts. Docker will not delete or modify any
pre-existing rules from the DOCKER-USER filter chain. This allows
the user to create in advance any rules required to further
restrict access from/to the containers.

Fixes docker/docker#29184
Fixes docker/docker#23987
Related to docker/docker#24848

Signed-off-by: Jacob Wen <jian.w.wen@oracle.com>
Jacob Wen %!s(int64=8) %!d(string=hai) anos
pai
achega
c348cebe99

+ 4 - 0
libnetwork/controller.go

@@ -844,6 +844,10 @@ addToStore:
 		c.Unlock()
 	}
 
+	c.Lock()
+	arrangeUserFilterRule()
+	c.Unlock()
+
 	return network, nil
 }
 

+ 2 - 42
libnetwork/drivers/bridge/setup_ip_tables.go

@@ -53,7 +53,7 @@ func setupIPChains(config *configuration) (*iptables.ChainInfo, *iptables.ChainI
 		return nil, nil, nil, fmt.Errorf("failed to create FILTER isolation chain: %v", err)
 	}
 
-	if err := addReturnRule(IsolationChain); err != nil {
+	if err := iptables.AddReturnRule(IsolationChain); err != nil {
 		return nil, nil, nil, err
 	}
 
@@ -117,7 +117,7 @@ func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInt
 	}
 
 	d.Lock()
-	err = ensureJumpRule("FORWARD", IsolationChain)
+	err = iptables.EnsureJumpRule("FORWARD", IsolationChain)
 	d.Unlock()
 	if err != nil {
 		return err
@@ -280,46 +280,6 @@ func setINC(iface1, iface2 string, enable bool) error {
 	return nil
 }
 
-func addReturnRule(chain string) error {
-	var (
-		table = iptables.Filter
-		args  = []string{"-j", "RETURN"}
-	)
-
-	if iptables.Exists(table, chain, args...) {
-		return nil
-	}
-
-	err := iptables.RawCombinedOutput(append([]string{"-I", chain}, args...)...)
-	if err != nil {
-		return fmt.Errorf("unable to add return rule in %s chain: %s", chain, err.Error())
-	}
-
-	return nil
-}
-
-// Ensure the jump rule is on top
-func ensureJumpRule(fromChain, toChain string) error {
-	var (
-		table = iptables.Filter
-		args  = []string{"-j", toChain}
-	)
-
-	if iptables.Exists(table, fromChain, args...) {
-		err := iptables.RawCombinedOutput(append([]string{"-D", fromChain}, args...)...)
-		if err != nil {
-			return fmt.Errorf("unable to remove jump to %s rule in %s chain: %s", toChain, fromChain, err.Error())
-		}
-	}
-
-	err := iptables.RawCombinedOutput(append([]string{"-I", fromChain}, args...)...)
-	if err != nil {
-		return fmt.Errorf("unable to insert jump to %s rule in %s chain: %s", toChain, fromChain, err.Error())
-	}
-
-	return nil
-}
-
 func removeIPChains() {
 	for _, chainInfo := range []iptables.ChainInfo{
 		{Name: DockerChain, Table: iptables.Nat},

+ 29 - 0
libnetwork/firewall_linux.go

@@ -0,0 +1,29 @@
+package libnetwork
+
+import (
+	"github.com/Sirupsen/logrus"
+	"github.com/docker/libnetwork/iptables"
+)
+
+const userChain = "DOCKER-USER"
+
+// This chain allow users to configure firewall policies in a way that persists
+// docker operations/restarts. Docker will not delete or modify any pre-existing
+// rules from the DOCKER-USER filter chain.
+func arrangeUserFilterRule() {
+	_, err := iptables.NewChain(userChain, iptables.Filter, false)
+	if err != nil {
+		logrus.Warnf("Failed to create %s chain: %v", userChain, err)
+		return
+	}
+
+	if err = iptables.AddReturnRule(userChain); err != nil {
+		logrus.Warnf("Failed to add the RETURN rule for %s: %v", userChain, err)
+		return
+	}
+
+	err = iptables.EnsureJumpRule("FORWARD", userChain)
+	if err != nil {
+		logrus.Warnf("Failed to ensure the jump rule for %s: %v", userChain, err)
+	}
+}

+ 6 - 0
libnetwork/firewall_others.go

@@ -0,0 +1,6 @@
+// +build !linux
+
+package libnetwork
+
+func arrangeUserFilterRule() {
+}

+ 41 - 0
libnetwork/iptables/iptables.go

@@ -498,3 +498,44 @@ func parseVersionNumbers(input string) (major, minor, micro int) {
 func supportsCOption(mj, mn, mc int) bool {
 	return mj > 1 || (mj == 1 && (mn > 4 || (mn == 4 && mc >= 11)))
 }
+
+// AddReturnRule adds a return rule for the chain in the filter table
+func AddReturnRule(chain string) error {
+	var (
+		table = Filter
+		args  = []string{"-j", "RETURN"}
+	)
+
+	if Exists(table, chain, args...) {
+		return nil
+	}
+
+	err := RawCombinedOutput(append([]string{"-A", chain}, args...)...)
+	if err != nil {
+		return fmt.Errorf("unable to add return rule in %s chain: %s", chain, err.Error())
+	}
+
+	return nil
+}
+
+// EnsureJumpRule ensures the jump rule is on top
+func EnsureJumpRule(fromChain, toChain string) error {
+	var (
+		table = Filter
+		args  = []string{"-j", toChain}
+	)
+
+	if Exists(table, fromChain, args...) {
+		err := RawCombinedOutput(append([]string{"-D", fromChain}, args...)...)
+		if err != nil {
+			return fmt.Errorf("unable to remove jump to %s rule in %s chain: %s", toChain, fromChain, err.Error())
+		}
+	}
+
+	err := RawCombinedOutput(append([]string{"-I", fromChain}, args...)...)
+	if err != nil {
+		return fmt.Errorf("unable to insert jump to %s rule in %s chain: %s", toChain, fromChain, err.Error())
+	}
+
+	return nil
+}