mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
DOCKER-USER chain not created when IPTableEnable=false.
This fix addresses https://docker.atlassian.net/browse/ENGCORE-1115 Expected behaviors upon docker engine restarts: 1. IPTableEnable=true, DOCKER-USER chain present -- no change to DOCKER-USER chain 2. IPTableEnable=true, DOCKER-USER chain not present -- DOCKER-USER chain created and inserted top of FORWARD chain. 3. IPTableEnable=false, DOCKER-USER chain present -- no change to DOCKER-USER chain the rational is that DOCKER-USER is populated and may be used by end-user for purpose other than filtering docker container traffic. Thus even if IPTableEnable=false, docker engine does not touch pre-existing DOCKER-USER chain. 4. IPTableEnable=false, DOCKER-USER chain not present -- DOCKER-USER chain is not created. Signed-off-by: Su Wang <su.wang@docker.com>
This commit is contained in:
parent
aa1016e702
commit
fcb70a0e86
4 changed files with 139 additions and 13 deletions
|
@ -67,6 +67,7 @@ import (
|
||||||
"github.com/docker/libnetwork/hostdiscovery"
|
"github.com/docker/libnetwork/hostdiscovery"
|
||||||
"github.com/docker/libnetwork/ipamapi"
|
"github.com/docker/libnetwork/ipamapi"
|
||||||
"github.com/docker/libnetwork/netlabel"
|
"github.com/docker/libnetwork/netlabel"
|
||||||
|
"github.com/docker/libnetwork/options"
|
||||||
"github.com/docker/libnetwork/osl"
|
"github.com/docker/libnetwork/osl"
|
||||||
"github.com/docker/libnetwork/types"
|
"github.com/docker/libnetwork/types"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -252,6 +253,7 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setupArrangeUserFilterRule(c)
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -909,8 +911,7 @@ addToStore:
|
||||||
arrangeIngressFilterRule()
|
arrangeIngressFilterRule()
|
||||||
c.Unlock()
|
c.Unlock()
|
||||||
}
|
}
|
||||||
|
arrangeUserFilterRule()
|
||||||
c.arrangeUserFilterRule()
|
|
||||||
|
|
||||||
return network, nil
|
return network, nil
|
||||||
}
|
}
|
||||||
|
@ -1363,3 +1364,27 @@ func (c *controller) IsDiagnosticEnabled() bool {
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
return c.DiagnosticServer.IsDiagnosticEnabled()
|
return c.DiagnosticServer.IsDiagnosticEnabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *controller) iptablesEnabled() bool {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
|
|
||||||
|
if c.cfg == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// parse map cfg["bridge"]["generic"]["EnableIPTable"]
|
||||||
|
cfgBridge, ok := c.cfg.Daemon.DriverCfg["bridge"].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
cfgGeneric, ok := cfgBridge[netlabel.GenericData].(options.Generic)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
enabled, ok := cfgGeneric["EnableIPTables"].(bool)
|
||||||
|
if !ok {
|
||||||
|
// unless user explicitly stated, assume iptable is enabled
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
return enabled
|
||||||
|
}
|
||||||
|
|
|
@ -7,21 +7,25 @@ import (
|
||||||
|
|
||||||
const userChain = "DOCKER-USER"
|
const userChain = "DOCKER-USER"
|
||||||
|
|
||||||
func (c *controller) arrangeUserFilterRule() {
|
var (
|
||||||
c.Lock()
|
ctrl *controller = nil
|
||||||
arrangeUserFilterRule()
|
)
|
||||||
c.Unlock()
|
|
||||||
iptables.OnReloaded(func() {
|
func setupArrangeUserFilterRule(c *controller) {
|
||||||
c.Lock()
|
ctrl = c
|
||||||
arrangeUserFilterRule()
|
iptables.OnReloaded(arrangeUserFilterRule)
|
||||||
c.Unlock()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This chain allow users to configure firewall policies in a way that persists
|
// 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
|
// docker operations/restarts. Docker will not delete or modify any pre-existing
|
||||||
// rules from the DOCKER-USER filter chain.
|
// rules from the DOCKER-USER filter chain.
|
||||||
|
// Note once DOCKER-USER chain is created, docker engine does not remove it when
|
||||||
|
// IPTableForwarding is disabled, because it contains rules configured by user that
|
||||||
|
// are beyond docker engine's control.
|
||||||
func arrangeUserFilterRule() {
|
func arrangeUserFilterRule() {
|
||||||
|
if ctrl == nil || !ctrl.iptablesEnabled() {
|
||||||
|
return
|
||||||
|
}
|
||||||
_, err := iptables.NewChain(userChain, iptables.Filter, false)
|
_, err := iptables.NewChain(userChain, iptables.Filter, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Warnf("Failed to create %s chain: %v", userChain, err)
|
logrus.Warnf("Failed to create %s chain: %v", userChain, err)
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
|
|
||||||
package libnetwork
|
package libnetwork
|
||||||
|
|
||||||
func (c *controller) arrangeUserFilterRule() {
|
func setupArrangeUserFilterRule(c *controller) {}
|
||||||
}
|
func arrangeUserFilterRule() {}
|
||||||
|
|
97
libnetwork/firewall_test.go
Normal file
97
libnetwork/firewall_test.go
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
package libnetwork
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"gotest.tools/assert"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/libnetwork/iptables"
|
||||||
|
"github.com/docker/libnetwork/netlabel"
|
||||||
|
"github.com/docker/libnetwork/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
fwdChainName = "FORWARD"
|
||||||
|
usrChainName = userChain
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUserChain(t *testing.T) {
|
||||||
|
nc, err := New()
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
iptables bool
|
||||||
|
insert bool // insert other rules to FORWARD
|
||||||
|
fwdChain []string
|
||||||
|
userChain []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
iptables: false,
|
||||||
|
insert: false,
|
||||||
|
fwdChain: []string{"-P FORWARD ACCEPT"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
iptables: true,
|
||||||
|
insert: false,
|
||||||
|
fwdChain: []string{"-P FORWARD ACCEPT", "-A FORWARD -j DOCKER-USER"},
|
||||||
|
userChain: []string{"-N DOCKER-USER", "-A DOCKER-USER -j RETURN"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
iptables: true,
|
||||||
|
insert: true,
|
||||||
|
fwdChain: []string{"-P FORWARD ACCEPT", "-A FORWARD -j DOCKER-USER", "-A FORWARD -j DROP"},
|
||||||
|
userChain: []string{"-N DOCKER-USER", "-A DOCKER-USER -j RETURN"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
resetIptables(t)
|
||||||
|
for _, tc := range tests {
|
||||||
|
tc := tc
|
||||||
|
t.Run(fmt.Sprintf("iptables=%v,insert=%v", tc.iptables, tc.insert), func(t *testing.T) {
|
||||||
|
c := nc.(*controller)
|
||||||
|
c.cfg.Daemon.DriverCfg["bridge"] = map[string]interface{}{
|
||||||
|
netlabel.GenericData: options.Generic{
|
||||||
|
"EnableIPTables": tc.iptables,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// init. condition, FORWARD chain empty DOCKER-USER not exist
|
||||||
|
assert.DeepEqual(t, getRules(t, fwdChainName), []string{"-P FORWARD ACCEPT"})
|
||||||
|
|
||||||
|
if tc.insert {
|
||||||
|
_, err = iptables.Raw("-A", fwdChainName, "-j", "DROP")
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
arrangeUserFilterRule()
|
||||||
|
|
||||||
|
assert.DeepEqual(t, getRules(t, fwdChainName), tc.fwdChain)
|
||||||
|
if tc.userChain != nil {
|
||||||
|
assert.DeepEqual(t, getRules(t, usrChainName), tc.userChain)
|
||||||
|
} else {
|
||||||
|
_, err := iptables.Raw("-S", usrChainName)
|
||||||
|
assert.Assert(t, err != nil, "chain %v: created unexpectedly", usrChainName)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
resetIptables(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRules(t *testing.T, chain string) []string {
|
||||||
|
t.Helper()
|
||||||
|
output, err := iptables.Raw("-S", chain)
|
||||||
|
assert.NilError(t, err, "chain %s: failed to get rules", chain)
|
||||||
|
|
||||||
|
rules := strings.Split(string(output), "\n")
|
||||||
|
if len(rules) > 0 {
|
||||||
|
rules = rules[:len(rules)-1]
|
||||||
|
}
|
||||||
|
return rules
|
||||||
|
}
|
||||||
|
|
||||||
|
func resetIptables(t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
_, err := iptables.Raw("-F", fwdChainName)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
_ = iptables.RemoveExistingChain(usrChainName, "")
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue