diff --git a/controller.go b/controller.go index 5a499aa428..6126490c7a 100644 --- a/controller.go +++ b/controller.go @@ -904,14 +904,6 @@ addToStore: } } - if !c.isDistributedControl() { - c.Lock() - arrangeIngressFilterRule() - c.Unlock() - } - - c.arrangeUserFilterRule() - return network, nil } diff --git a/drivers/bridge/bridge.go b/drivers/bridge/bridge.go index b617ea7bc4..ff758e9541 100644 --- a/drivers/bridge/bridge.go +++ b/drivers/bridge/bridge.go @@ -33,6 +33,8 @@ const ( vethLen = 7 defaultContainerVethPrefix = "eth" maxAllocatePortAttempts = 10 + userChain = "DOCKER-USER" + ingressChain = "DOCKER-INGRESS" ) const ( @@ -357,6 +359,16 @@ func (d *driver) configure(option map[string]interface{}) error { } // Make sure on firewall reload, first thing being re-played is chains creation iptables.OnReloaded(func() { logrus.Debugf("Recreating iptables chains on firewall reload"); setupIPChains(config) }) + + // Add DOCKER-INGRESS chain + arrangeIngressFilterRule() + // Add DOCKER-USER chain + arrangeUserFilterRule() + iptables.OnReloaded(func() { + logrus.Debugf("Recreating DOCKER-INGRESS and DOCKER-USER iptables chain on firewall reload") + arrangeIngressFilterRule() + arrangeUserFilterRule() + }) } if config.EnableIPForwarding { @@ -1504,3 +1516,42 @@ func electMacAddress(epConfig *endpointConfiguration, ip net.IP) net.HardwareAdd } return netutils.GenerateMACFromIP(ip) } + +// 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) + } +} + +// In the filter table FORWARD chain the first rule should be to jump to +// DOCKER-USER so the user is able to filter packet first. +// The second rule should be jump to INGRESS-CHAIN. +// This chain has the rules to allow access to the published ports for swarm tasks +// from local bridge networks and docker_gwbridge (ie:taks on other swarm networks) +func arrangeIngressFilterRule() { + if iptables.ExistChain(ingressChain, iptables.Filter) { + if iptables.Exists(iptables.Filter, "FORWARD", "-j", ingressChain) { + if err := iptables.RawCombinedOutput("-D", "FORWARD", "-j", ingressChain); err != nil { + logrus.Warnf("failed to delete jump rule to ingressChain in filter table: %v", err) + } + } + if err := iptables.RawCombinedOutput("-I", "FORWARD", "-j", ingressChain); err != nil { + logrus.Warnf("failed to add jump rule to ingressChain in filter table: %v", err) + } + } +} diff --git a/drivers/bridge/bridge_test.go b/drivers/bridge/bridge_test.go index 945e2bd2ec..94d1c1d50d 100644 --- a/drivers/bridge/bridge_test.go +++ b/drivers/bridge/bridge_test.go @@ -19,6 +19,41 @@ import ( "github.com/vishvananda/netlink" ) +// TestEnableIPTables enables EnableIPTables and checks if +// the DOCKER-USER chain is created or not +func TestEnableIPTables(t *testing.T) { + if !testutils.IsRunningInContainer() { + defer testutils.SetupTestOSContext(t)() + } + + d := newDriver() + + config := &configuration{ + EnableIPTables: true, + } + genericOption := make(map[string]interface{}) + genericOption[netlabel.GenericData] = config + + if err := d.configure(genericOption); err != nil { + t.Fatalf("Failed to setup driver config: %v", err) + } + + userRule1 := []string{ + "-j", "DOCKER-USER"} + + if !iptables.Exists(iptables.Filter, "FORWARD", userRule1...) { + t.Fatal("rule does not exist") + } + + userRule2 := []string{ + "-j", "RETURN"} + + if !iptables.Exists(iptables.Filter, "DOCKER-USER", userRule2...) { + t.Fatal("rule does not exist") + } + +} + func TestEndpointMarshalling(t *testing.T) { ip1, _ := types.ParseCIDR("172.22.0.9/16") ip2, _ := types.ParseCIDR("2001:db8::9") diff --git a/firewall_linux.go b/firewall_linux.go deleted file mode 100644 index d27f60ca0c..0000000000 --- a/firewall_linux.go +++ /dev/null @@ -1,70 +0,0 @@ -package libnetwork - -import ( - "github.com/docker/libnetwork/iptables" - "github.com/docker/libnetwork/netlabel" - "github.com/sirupsen/logrus" -) - -const userChain = "DOCKER-USER" - -func (c *controller) arrangeUserFilterRule() { - c.Lock() - - if c.hasIPTablesEnabled() { - arrangeUserFilterRule() - } - - c.Unlock() - - iptables.OnReloaded(func() { - c.Lock() - - if c.hasIPTablesEnabled() { - arrangeUserFilterRule() - } - - c.Unlock() - }) -} - -func (c *controller) hasIPTablesEnabled() bool { - // Locking c should be handled in the calling method. - if c.cfg == nil || c.cfg.Daemon.DriverCfg[netlabel.GenericData] == nil { - return false - } - - genericData, ok := c.cfg.Daemon.DriverCfg[netlabel.GenericData] - if !ok { - return false - } - - optMap := genericData.(map[string]interface{}) - enabled, ok := optMap["EnableIPTables"].(bool) - if !ok { - return false - } - - return enabled -} - -// 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) - } -} diff --git a/firewall_others.go b/firewall_others.go deleted file mode 100644 index 901f568fed..0000000000 --- a/firewall_others.go +++ /dev/null @@ -1,6 +0,0 @@ -// +build !linux - -package libnetwork - -func (c *controller) arrangeUserFilterRule() { -} diff --git a/service_linux.go b/service_linux.go index 451f760b61..531b8f6d2a 100644 --- a/service_linux.go +++ b/service_linux.go @@ -366,7 +366,6 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro if err := iptables.RawCombinedOutput("-I", "FORWARD", "-j", ingressChain); err != nil { return fmt.Errorf("failed to add jump rule to %s in filter table forward chain: %v", ingressChain, err) } - arrangeUserFilterRule() } oifName, err := findOIFName(gwIP) @@ -455,24 +454,6 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro return nil } -// In the filter table FORWARD chain the first rule should be to jump to -// DOCKER-USER so the user is able to filter packet first. -// The second rule should be jump to INGRESS-CHAIN. -// This chain has the rules to allow access to the published ports for swarm tasks -// from local bridge networks and docker_gwbridge (ie:taks on other swarm networks) -func arrangeIngressFilterRule() { - if iptables.ExistChain(ingressChain, iptables.Filter) { - if iptables.Exists(iptables.Filter, "FORWARD", "-j", ingressChain) { - if err := iptables.RawCombinedOutput("-D", "FORWARD", "-j", ingressChain); err != nil { - logrus.Warnf("failed to delete jump rule to ingressChain in filter table: %v", err) - } - } - if err := iptables.RawCombinedOutput("-I", "FORWARD", "-j", ingressChain); err != nil { - logrus.Warnf("failed to add jump rule to ingressChain in filter table: %v", err) - } - } -} - func findOIFName(ip net.IP) (string, error) { nlh := ns.NlHandle() diff --git a/service_unsupported.go b/service_unsupported.go index ee9750600c..95cc081633 100644 --- a/service_unsupported.go +++ b/service_unsupported.go @@ -20,6 +20,3 @@ func (c *controller) rmServiceBinding(name, sid, nid, eid string, vip net.IP, in func (sb *sandbox) populateLoadBalancers(ep *endpoint) { } - -func arrangeIngressFilterRule() { -} diff --git a/service_windows.go b/service_windows.go index 944f3d30ca..b8b7a21991 100644 --- a/service_windows.go +++ b/service_windows.go @@ -168,6 +168,3 @@ func numEnabledBackends(lb *loadBalancer) int { func (sb *sandbox) populateLoadBalancers(ep *endpoint) { } - -func arrangeIngressFilterRule() { -}