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>
This commit is contained in:
Jacob Wen 2017-03-13 15:46:46 +08:00
parent 37e20af882
commit 0067b3a8ec
5 changed files with 82 additions and 42 deletions

View File

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

View File

@ -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
firewall_linux.go Normal file
View File

@ -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
firewall_others.go Normal file
View File

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

View File

@ -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
}