Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -904,14 +904,6 @@ addToStore:
}
}

if !c.isDistributedControl() {
c.Lock()
arrangeIngressFilterRule()
c.Unlock()
}

c.arrangeUserFilterRule()

return network, nil
}

Expand Down
51 changes: 51 additions & 0 deletions drivers/bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ const (
vethLen = 7
defaultContainerVethPrefix = "eth"
maxAllocatePortAttempts = 10
userChain = "DOCKER-USER"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have similar questions as Elango, why move to bridge.go, may be the real problem is that controller.hasIPTableEnabled() isn't the correct value?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by moving arrangeUserFilterRule to bridge only network, it means unless a bridge network is created, there won't be DOCKER_USER chain. It will work as dockerd always creates docker9 bridge, but for me the original approach is cleaner.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ingressChain = "DOCKER-INGRESS"
)

const (
Expand Down Expand Up @@ -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()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now arrangeUserFIlterRule is called on all systems, linux/windows/bsd etc, is this by intention?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK bridge is for linux only

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose for any *nix, we expect to create bridge. I see somewhere there are _bsd specific imple. So I am guessing at some point before at least bsd is supported?

iptables.OnReloaded(func() {
logrus.Debugf("Recreating DOCKER-INGRESS and DOCKER-USER iptables chain on firewall reload")
arrangeIngressFilterRule()
arrangeUserFilterRule()
})
}

if config.EnableIPForwarding {
Expand Down Expand Up @@ -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)
}
}
}
35 changes: 35 additions & 0 deletions drivers/bridge/bridge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
70 changes: 0 additions & 70 deletions firewall_linux.go

This file was deleted.

6 changes: 0 additions & 6 deletions firewall_others.go

This file was deleted.

19 changes: 0 additions & 19 deletions service_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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()

Expand Down
3 changes: 0 additions & 3 deletions service_unsupported.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
}
3 changes: 0 additions & 3 deletions service_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,3 @@ func numEnabledBackends(lb *loadBalancer) int {

func (sb *sandbox) populateLoadBalancers(ep *endpoint) {
}

func arrangeIngressFilterRule() {
}