Skip to content

Commit

Permalink
Add a filter chain to allow persistent rules
Browse files Browse the repository at this point in the history
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 moby/moby#29184
Fixes moby/moby#23987
Related to moby/moby#24848

Signed-off-by: Jacob Wen <jian.w.wen@oracle.com>
  • Loading branch information
Jacob Wen committed Mar 14, 2017
1 parent bdc9dce commit c13d4f9
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 42 deletions.
29 changes: 29 additions & 0 deletions controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import (
"github.com/docker/libnetwork/drvregistry"
"github.com/docker/libnetwork/hostdiscovery"
"github.com/docker/libnetwork/ipamapi"
"github.com/docker/libnetwork/iptables"
"github.com/docker/libnetwork/netlabel"
"github.com/docker/libnetwork/osl"
"github.com/docker/libnetwork/types"
Expand Down Expand Up @@ -719,6 +720,10 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ...
}
}()

c.Lock()
arrangeUserFilterRule()
c.Unlock()

// First store the endpoint count, then the network. To avoid to
// end up with a datastore containing a network and not an epCnt,
// in case of an ungraceful shutdown during this function call.
Expand All @@ -743,6 +748,7 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ...
if !c.isDistributedControl() {
c.Lock()
arrangeIngressFilterRule()
arrangeUserFilterRule()
c.Unlock()
}

Expand Down Expand Up @@ -1178,3 +1184,26 @@ func (c *controller) clearIngress(clusterLeave bool) {
}
}
}

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)
}
}
44 changes: 2 additions & 42 deletions drivers/bridge/setup_ip_tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,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
}

Expand Down Expand Up @@ -116,7 +116,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
Expand Down Expand Up @@ -285,46 +285,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},
Expand Down
41 changes: 41 additions & 0 deletions iptables/iptables.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,3 +465,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
}

0 comments on commit c13d4f9

Please sign in to comment.