diff --git a/libnetwork/drivers/bridge/bridge_linux.go b/libnetwork/drivers/bridge/bridge_linux.go index 4af11e326e..108ceb5a59 100644 --- a/libnetwork/drivers/bridge/bridge_linux.go +++ b/libnetwork/drivers/bridge/bridge_linux.go @@ -130,12 +130,12 @@ type bridgeEndpoint struct { } type bridgeNetwork struct { - id string - bridge *bridgeInterface // The bridge's L3 interface - config *networkConfiguration - endpoints map[string]*bridgeEndpoint // key: endpoint id - driver *driver // The network's driver - iptCleanFuncs iptablesCleanFuncs + id string + bridge *bridgeInterface // The bridge's L3 interface + config *networkConfiguration + endpoints map[string]*bridgeEndpoint // key: endpoint id + driver *driver // The network's driver + iptablesNetwork *iptablesNetwork sync.Mutex } @@ -391,10 +391,6 @@ func parseErr(label, value, errString string) error { return types.InvalidParameterErrorf("failed to parse %s value: %v (%s)", label, value, errString) } -func (n *bridgeNetwork) registerIptCleanFunc(clean iptableCleanFunc) { - n.iptCleanFuncs = append(n.iptCleanFuncs, clean) -} - func (n *bridgeNetwork) iptablesEnabled(version iptables.IPVersion) (bool, error) { n.Lock() defer n.Unlock() @@ -410,6 +406,51 @@ func (n *bridgeNetwork) iptablesEnabled(version iptables.IPVersion) (bool, error return n.driver.config.EnableIPTables, nil } +func (n *bridgeNetwork) newIptablesNetwork() (*iptablesNetwork, error) { + config4, err := makeNetworkConfigFam(n.config.HostIPv4, n.bridge.bridgeIPv4, n.gwMode(iptables.IPv4)) + if err != nil { + return nil, err + } + config6, err := makeNetworkConfigFam(n.config.HostIPv6, n.bridge.bridgeIPv6, n.gwMode(iptables.IPv6)) + if err != nil { + return nil, err + } + return newIptablesNetwork(networkConfig{ + IfName: n.config.BridgeName, + Internal: n.config.Internal, + ICC: n.config.EnableICC, + Masquerade: n.config.EnableIPMasquerade, + Config4: config4, + Config6: config6, + Hairpin: !n.driver.config.EnableUserlandProxy || n.driver.config.UserlandProxyPath == "", + Enable4: n.driver.config.EnableIPTables, + Enable6: n.driver.config.EnableIP6Tables, + }) +} + +func makeNetworkConfigFam(hostIP net.IP, bridgePrefix *net.IPNet, gwm gwMode) (networkConfigFam, error) { + c := networkConfigFam{ + Routed: gwm.routed(), + Unprotected: gwm.unprotected(), + } + if hostIP != nil { + var ok bool + c.HostIP, ok = netip.AddrFromSlice(hostIP) + if !ok { + return networkConfigFam{}, fmt.Errorf("invalid host address %q", hostIP) + } + c.HostIP = c.HostIP.Unmap() + } + if bridgePrefix != nil { + p, ok := netiputil.ToPrefix(bridgePrefix) + if !ok { + return networkConfigFam{}, fmt.Errorf("invalid bridge prefix %s", bridgePrefix) + } + c.Prefix = p.Masked() + } + return c, nil +} + func (n *bridgeNetwork) getNetworkBridgeName() string { n.Lock() config := n.config @@ -465,41 +506,6 @@ func (n *bridgeNetwork) getEndpoint(eid string) (*bridgeEndpoint, error) { return nil, nil } -// Install (enable=true) or remove (enable=false) the iptables rules needed to isolate this network -// from each of the other bridge networks -func (n *bridgeNetwork) isolateNetwork(enable bool) error { - n.Lock() - thisConfig := n.config - n.Unlock() - - if thisConfig.Internal { - return nil - } - - if n.driver.config.EnableIPTables { - // Only create the rules if the network has IPv4 enabled. But, always delete - // rules, in case they were set up by an older daemon that didn't check whether - // the network has IPv4. - if !enable || thisConfig.EnableIPv4 { - if err := setINC(iptables.IPv4, thisConfig.BridgeName, thisConfig.GwModeIPv4, enable); err != nil { - return err - } - } - } - if n.driver.config.EnableIP6Tables { - // Only create the rules if the network has IPv6 enabled. But, always delete - // rules, in case they were set up by an older daemon that didn't check whether - // the network has IPv6. - if !enable || thisConfig.EnableIPv6 { - if err := setINC(iptables.IPv6, thisConfig.BridgeName, thisConfig.GwModeIPv6, enable); err != nil { - return err - } - } - } - - return nil -} - func (d *driver) configure(option map[string]interface{}) error { var config configuration switch opt := option[netlabel.GenericData].(type) { @@ -853,21 +859,6 @@ func (d *driver) createNetwork(config *networkConfiguration) (err error) { } }() - // Add inter-network communication rules. - setupNetworkIsolationRules := func(config *networkConfiguration, i *bridgeInterface) error { - if err := network.isolateNetwork(true); err != nil { - if errRollback := network.isolateNetwork(false); errRollback != nil { - log.G(context.TODO()).WithError(errRollback).Warnf("Failed on removing the inter-network iptables rules on cleanup") - } - return errdefs.System(err) - } - // register the cleanup function - network.registerIptCleanFunc(func() error { - return network.isolateNetwork(false) - }) - return nil - } - // Prepare the bridge setup configuration bridgeSetup := newBridgeSetup(config, bridgeIface) @@ -931,12 +922,6 @@ func (d *driver) createNetwork(config *networkConfiguration) (err error) { // Setup Loopback Addresses Routing {!d.config.EnableUserlandProxy, setupLoopbackAddressesRouting}, - // Setup IPTables. - {config.EnableIPv4 && d.config.EnableIPTables, network.setupIP4Tables}, - - // Setup IP6Tables. - {config.EnableIPv6 && d.config.EnableIP6Tables, network.setupIP6Tables}, - // We want to track firewalld configuration so that // if it is started/reloaded, the rules can be applied correctly { @@ -950,9 +935,6 @@ func (d *driver) createNetwork(config *networkConfiguration) (err error) { // Setup DefaultGatewayIPv6 {config.DefaultGatewayIPv6 != nil, setupGatewayIPv6}, - // Add inter-network communication rules. - {d.config.EnableIPTables || d.config.EnableIP6Tables, setupNetworkIsolationRules}, - // Configure bridge networking filtering if needed and IP tables are enabled {enableBrNfCallIptables && d.config.EnableIPTables, setupIPv4BridgeNetFiltering}, {enableBrNfCallIptables && d.config.EnableIP6Tables, setupIPv6BridgeNetFiltering}, @@ -962,6 +944,15 @@ func (d *driver) createNetwork(config *networkConfiguration) (err error) { } } + bridgeSetup.queueStep(func(*networkConfiguration, *bridgeInterface) error { + n, err := network.newIptablesNetwork() + if err != nil { + return err + } + network.iptablesNetwork = n + return nil + }) + // Apply the prepared list of steps, and abort at the first error. bridgeSetup.queueStep(setupDeviceUp) @@ -1054,12 +1045,10 @@ func (d *driver) deleteNetwork(nid string) error { // Don't delete the bridge interface if it was not created by libnetwork. } - // clean all relevant iptables rules - for _, cleanFunc := range n.iptCleanFuncs { - if errClean := cleanFunc(); errClean != nil { - log.G(context.TODO()).Warnf("Failed to clean iptables rules for bridge network: %v", errClean) - } + if err := n.iptablesNetwork.delNetworkLevelRules(); err != nil { + log.G(context.TODO()).WithError(err).Warnf("Failed to clean iptables rules for bridge network") } + return d.storeDelete(config) } diff --git a/libnetwork/drivers/bridge/setup_firewalld.go b/libnetwork/drivers/bridge/setup_firewalld.go index 17877e2478..f17a23d465 100644 --- a/libnetwork/drivers/bridge/setup_firewalld.go +++ b/libnetwork/drivers/bridge/setup_firewalld.go @@ -9,12 +9,7 @@ import ( func (n *bridgeNetwork) setupFirewalld(config *networkConfiguration, i *bridgeInterface) error { // FIXME(robmry) - these reload functions aren't deleted when the network is deleted. // So, a firewalld reload leads to creation of zombie rules belonging to those networks. - if n.driver.config.EnableIPTables && config.EnableIPv4 { - iptables.OnReloaded(func() { n.setupIP4Tables(config, i) }) - } - if n.driver.config.EnableIP6Tables && config.EnableIPv6 { - iptables.OnReloaded(func() { n.setupIP6Tables(config, i) }) - } + iptables.OnReloaded(func() { n.iptablesNetwork.reapplyNetworkLevelRules() }) iptables.OnReloaded(n.reapplyPerPortIptables) return nil } diff --git a/libnetwork/drivers/bridge/setup_ip_tables_linux.go b/libnetwork/drivers/bridge/setup_ip_tables_linux.go index a52d448232..9e414c3965 100644 --- a/libnetwork/drivers/bridge/setup_ip_tables_linux.go +++ b/libnetwork/drivers/bridge/setup_ip_tables_linux.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net" + "net/netip" "os" "github.com/containerd/log" @@ -191,88 +192,156 @@ func setupIPChains(config configuration, version iptables.IPVersion) (retErr err return nil } -func (n *bridgeNetwork) setupIP4Tables(config *networkConfiguration, i *bridgeInterface) error { - maskedAddrv4 := &net.IPNet{ - IP: i.bridgeIPv4.IP.Mask(i.bridgeIPv4.Mask), - Mask: i.bridgeIPv4.Mask, - } - return n.setupIPTables(iptables.IPv4, maskedAddrv4, config, i) +type networkConfigFam struct { + HostIP netip.Addr + Prefix netip.Prefix + Routed bool + Unprotected bool } -func (n *bridgeNetwork) setupIP6Tables(config *networkConfiguration, i *bridgeInterface) error { - maskedAddrv6 := &net.IPNet{ - IP: i.bridgeIPv6.IP.Mask(i.bridgeIPv6.Mask), - Mask: i.bridgeIPv6.Mask, - } - return n.setupIPTables(iptables.IPv6, maskedAddrv6, config, i) +type networkConfig struct { + IfName string + Internal bool + ICC bool + Masquerade bool + Config4 networkConfigFam + Config6 networkConfigFam + Hairpin bool + Enable4 bool + Enable6 bool } -func (n *bridgeNetwork) setupIPTables(ipVersion iptables.IPVersion, maskedAddr *net.IPNet, config *networkConfiguration, i *bridgeInterface) error { - var err error +type iptablesNetwork struct { + networkConfig + cleanFuncs iptablesCleanFuncs +} - d := n.driver - d.Lock() - driverConfig := d.config - d.Unlock() - - // Pickup this configuration option from driver - hairpinMode := !driverConfig.EnableUserlandProxy - - if config.Internal { - if err = setupInternalNetworkRules(config.BridgeName, maskedAddr, config.EnableICC, true); err != nil { - return fmt.Errorf("Failed to Setup IP tables: %w", err) +func newIptablesNetwork(nc networkConfig) (_ *iptablesNetwork, retErr error) { + n := &iptablesNetwork{ + networkConfig: nc, + } + defer func() { + if retErr != nil { + n.delNetworkLevelRules() } - n.registerIptCleanFunc(func() error { - return setupInternalNetworkRules(config.BridgeName, maskedAddr, config.EnableICC, false) - }) - } else { - if err = setupNonInternalNetworkRules(ipVersion, config, maskedAddr, hairpinMode, true); err != nil { - return fmt.Errorf("Failed to Setup IP tables: %w", err) - } - n.registerIptCleanFunc(func() error { - return setupNonInternalNetworkRules(ipVersion, config, maskedAddr, hairpinMode, false) - }) + }() - if err := iptables.AddInterfaceFirewalld(config.BridgeName); err != nil { + if err := n.reapplyNetworkLevelRules(); err != nil { + return nil, err + } + return n, nil +} + +func (n *iptablesNetwork) reapplyNetworkLevelRules() error { + if n.Enable4 { + if err := n.configure(iptables.IPv4, n.Config4); err != nil { return err } - n.registerIptCleanFunc(func() error { - if err := iptables.DelInterfaceFirewalld(config.BridgeName); err != nil && !errdefs.IsNotFound(err) { + } + if n.Enable6 { + if err := n.configure(iptables.IPv6, n.Config6); err != nil { + return err + } + } + return nil +} + +func (n *iptablesNetwork) delNetworkLevelRules() error { + var errs []error + for _, cleanFunc := range n.cleanFuncs { + if err := cleanFunc(); err != nil { + errs = append(errs, err) + } + } + n.cleanFuncs = nil + return errors.Join(errs...) +} + +func (n *iptablesNetwork) configure(ipv iptables.IPVersion, conf networkConfigFam) error { + if !conf.Prefix.IsValid() { + // Delete INC rules, in case they were created by a 28.0.0 daemon that didn't check + // whether the network had iptables/ip6tables enabled. + // This preserves https://github.com/moby/moby/commit/8cc4d1d4a2b6408232041f9ba4dff966eba80cc0 + return setINC(ipv, n.IfName, conf.Routed, false) + } + if err := n.setupIPTables(ipv, conf); err != nil { + return err + } + return nil +} + +func (n *iptablesNetwork) registerCleanFunc(clean iptableCleanFunc) { + n.cleanFuncs = append(n.cleanFuncs, clean) +} + +func (n *iptablesNetwork) setupIPTables(ipVersion iptables.IPVersion, config networkConfigFam) error { + if n.Internal { + if err := setupInternalNetworkRules(n.IfName, config.Prefix, n.ICC, true); err != nil { + return fmt.Errorf("Failed to Setup IP tables: %w", err) + } + n.registerCleanFunc(func() error { + return setupInternalNetworkRules(n.IfName, config.Prefix, n.ICC, false) + }) + } else { + if err := n.setupNonInternalNetworkRules(ipVersion, config, true); err != nil { + return fmt.Errorf("Failed to Setup IP tables: %w", err) + } + n.registerCleanFunc(func() error { + return n.setupNonInternalNetworkRules(ipVersion, config, false) + }) + + if err := iptables.AddInterfaceFirewalld(n.IfName); err != nil { + return err + } + n.registerCleanFunc(func() error { + if err := iptables.DelInterfaceFirewalld(n.IfName); err != nil && !errdefs.IsNotFound(err) { return err } return nil }) - err = deleteLegacyFilterRules(ipVersion, config.BridgeName) - if err != nil { + if err := deleteLegacyFilterRules(ipVersion, n.IfName); err != nil { return fmt.Errorf("failed to delete legacy rules in filter-FORWARD: %w", err) } - if err := n.setDefaultForwardRule(ipVersion, config.BridgeName); err != nil { + err := setDefaultForwardRule(ipVersion, n.IfName, config.Unprotected, true) + if err != nil { return err } + n.registerCleanFunc(func() error { + return setDefaultForwardRule(ipVersion, n.IfName, config.Unprotected, false) + }) ctRule := iptables.Rule{IPVer: ipVersion, Table: iptables.Filter, Chain: DockerCTChain, Args: []string{ - "-o", config.BridgeName, + "-o", n.IfName, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT", }} if err := appendOrDelChainRule(ctRule, "bridge ct related", true); err != nil { return err } - n.registerIptCleanFunc(func() error { + n.registerCleanFunc(func() error { return appendOrDelChainRule(ctRule, "bridge ct related", false) }) jumpToDockerRule := iptables.Rule{IPVer: ipVersion, Table: iptables.Filter, Chain: DockerBridgeChain, Args: []string{ - "-o", config.BridgeName, + "-o", n.IfName, "-j", DockerChain, }} if err := appendOrDelChainRule(jumpToDockerRule, "jump to docker", true); err != nil { return err } - n.registerIptCleanFunc(func() error { + n.registerCleanFunc(func() error { return appendOrDelChainRule(jumpToDockerRule, "jump to docker", false) }) + + // Register the cleanup function first. Then, if setINC fails after creating + // some rules, they will be deleted. + n.registerCleanFunc(func() error { + return setINC(ipVersion, n.IfName, config.Routed, false) + }) + if err := setINC(ipVersion, n.IfName, config.Routed, true); err != nil { + return err + } } return nil } @@ -380,16 +449,13 @@ func loopbackAddress(version iptables.IPVersion) string { } } -func (n *bridgeNetwork) setDefaultForwardRule( - ipVersion iptables.IPVersion, - bridgeName string, -) error { +func setDefaultForwardRule(ipVersion iptables.IPVersion, ifName string, unprotected bool, enable bool) error { // Normally, DROP anything that hasn't been ACCEPTed by a per-port/protocol // rule. This prevents direct access to un-mapped ports from remote hosts // that can route directly to the container's address (by setting up a // route via the host's address). action := "DROP" - if n.gwMode(ipVersion).unprotected() { + if unprotected { // If the user really wants to allow all access from the wider network, // explicitly ACCEPT anything so that the filter-FORWARD chain's // default policy can't interfere. @@ -397,46 +463,37 @@ func (n *bridgeNetwork) setDefaultForwardRule( } rule := iptables.Rule{IPVer: ipVersion, Table: iptables.Filter, Chain: DockerChain, Args: []string{ - "!", "-i", bridgeName, - "-o", bridgeName, + "!", "-i", ifName, + "-o", ifName, "-j", action, }} // Append to the filter table's DOCKER chain (the default rule must follow // per-port ACCEPT rules, which will be inserted at the top of the chain). - if err := appendOrDelChainRule(rule, "DEFAULT FWD", true); err != nil { + if err := appendOrDelChainRule(rule, "DEFAULT FWD", enable); err != nil { return fmt.Errorf("failed to add default-drop rule: %w", err) } - n.registerIptCleanFunc(func() error { - return appendOrDelChainRule(rule, "DEFAULT FWD", false) - }) return nil } -func setupNonInternalNetworkRules(ipVer iptables.IPVersion, config *networkConfiguration, addr *net.IPNet, hairpin, enable bool) error { - hostIP := config.HostIPv4 - nat := !config.GwModeIPv4.routed() - if ipVer == iptables.IPv6 { - hostIP = config.HostIPv6 - nat = !config.GwModeIPv6.routed() - } - +func (n *iptablesNetwork) setupNonInternalNetworkRules(ipVer iptables.IPVersion, config networkConfigFam, enable bool) error { var natArgs, hpNatArgs []string - if hostIP != nil { + if config.HostIP.IsValid() { // The user wants IPv4/IPv6 SNAT with the given address. - hostAddr := hostIP.String() - natArgs = []string{"-s", addr.String(), "!", "-o", config.BridgeName, "-j", "SNAT", "--to-source", hostAddr} - hpNatArgs = []string{"-m", "addrtype", "--src-type", "LOCAL", "-o", config.BridgeName, "-j", "SNAT", "--to-source", hostAddr} + hostAddr := config.HostIP.String() + natArgs = []string{"-s", config.Prefix.String(), "!", "-o", n.IfName, "-j", "SNAT", "--to-source", hostAddr} + hpNatArgs = []string{"-m", "addrtype", "--src-type", "LOCAL", "-o", n.IfName, "-j", "SNAT", "--to-source", hostAddr} } else { // Use MASQUERADE, which picks the src-ip based on next-hop from the route table - natArgs = []string{"-s", addr.String(), "!", "-o", config.BridgeName, "-j", "MASQUERADE"} - hpNatArgs = []string{"-m", "addrtype", "--src-type", "LOCAL", "-o", config.BridgeName, "-j", "MASQUERADE"} + natArgs = []string{"-s", config.Prefix.String(), "!", "-o", n.IfName, "-j", "MASQUERADE"} + hpNatArgs = []string{"-m", "addrtype", "--src-type", "LOCAL", "-o", n.IfName, "-j", "MASQUERADE"} } natRule := iptables.Rule{IPVer: ipVer, Table: iptables.Nat, Chain: "POSTROUTING", Args: natArgs} hpNatRule := iptables.Rule{IPVer: ipVer, Table: iptables.Nat, Chain: "POSTROUTING", Args: hpNatArgs} // Set NAT. - if config.EnableIPMasquerade { + nat := !config.Routed + if n.Masquerade { if nat { if err := programChainRule(natRule, "NAT", enable); err != nil { return err @@ -453,9 +510,9 @@ func setupNonInternalNetworkRules(ipVer iptables.IPVersion, config *networkConfi // enable access to ports published by containers in the same network. But, the INC rules // will block access to that published port from containers in other networks. (However, // users may add a rule to DOCKER-USER to work around the INC rules if needed.) - if !hairpin { + if !n.Hairpin { skipDNAT := iptables.Rule{IPVer: ipVer, Table: iptables.Nat, Chain: DockerChain, Args: []string{ - "-i", config.BridgeName, + "-i", n.IfName, "-j", "RETURN", }} if err := programChainRule(skipDNAT, "SKIP DNAT", enable); err != nil { @@ -466,18 +523,18 @@ func setupNonInternalNetworkRules(ipVer iptables.IPVersion, config *networkConfi // In hairpin mode, masquerade traffic from localhost. If hairpin is disabled or if we're tearing down // that bridge, make sure the iptables rule isn't lying around. - if err := programChainRule(hpNatRule, "MASQ LOCAL HOST", enable && hairpin); err != nil { + if err := programChainRule(hpNatRule, "MASQ LOCAL HOST", enable && n.Hairpin); err != nil { return err } // Set Inter Container Communication. - if err := setIcc(ipVer, config.BridgeName, config.EnableICC, false, enable); err != nil { + if err := setIcc(ipVer, n.IfName, n.ICC, false, enable); err != nil { return err } // Allow ICMP in routed mode. if !nat { - if err := setICMP(ipVer, config.BridgeName, enable); err != nil { + if err := setICMP(ipVer, n.IfName, enable); err != nil { return err } } @@ -487,8 +544,8 @@ func setupNonInternalNetworkRules(ipVer iptables.IPVersion, config *networkConfi // ICC if needed. Those rules are now combined. So, outRuleNoICC is only // needed for ICC=false, along with the DROP rule for ICC added by setIcc. outRuleNoICC := iptables.Rule{IPVer: ipVer, Table: iptables.Filter, Chain: DockerForwardChain, Args: []string{ - "-i", config.BridgeName, - "!", "-o", config.BridgeName, + "-i", n.IfName, + "!", "-o", n.IfName, "-j", "ACCEPT", }} // If there's a version of outRuleNoICC in the FORWARD chain, created by moby 28.0.0 or older, delete it. @@ -497,10 +554,10 @@ func setupNonInternalNetworkRules(ipVer iptables.IPVersion, config *networkConfi return fmt.Errorf("deleting FORWARD chain outRuleNoICC: %w", err) } } - if config.EnableICC { + if n.ICC { // Accept outgoing traffic to anywhere, including other containers on this bridge. outRuleICC := iptables.Rule{IPVer: ipVer, Table: iptables.Filter, Chain: DockerForwardChain, Args: []string{ - "-i", config.BridgeName, + "-i", n.IfName, "-j", "ACCEPT", }} if err := appendOrDelChainRule(outRuleICC, "ACCEPT OUTGOING", enable); err != nil { @@ -595,7 +652,7 @@ func setIcc(version iptables.IPVersion, bridgeIface string, iccEnable, internal, // Install rules only if they aren't present, remove only if they are. // If this method returns an error, it doesn't roll back any rules it has added. // No error is returned if rules cannot be removed (errors are just logged). -func setINC(version iptables.IPVersion, iface string, gwm gwMode, enable bool) (retErr error) { +func setINC(version iptables.IPVersion, iface string, routed, enable bool) (retErr error) { iptable := iptables.GetIptable(version) actionI, actionA := iptables.Insert, iptables.Append actionMsg := "add" @@ -604,7 +661,7 @@ func setINC(version iptables.IPVersion, iface string, gwm gwMode, enable bool) ( actionMsg = "remove" } - if gwm.routed() { + if routed { // Anything is allowed into a routed network at this stage, so RETURN. Port // filtering rules in the DOCKER chain will drop anything that's not destined // for an open port. @@ -681,7 +738,7 @@ func removeIPChains(version iptables.IPVersion) { } } -func setupInternalNetworkRules(bridgeIface string, addr *net.IPNet, icc, insert bool) error { +func setupInternalNetworkRules(bridgeIface string, prefix netip.Prefix, icc, insert bool) error { var version iptables.IPVersion var inDropRule, outDropRule iptables.Rule @@ -696,19 +753,19 @@ func setupInternalNetworkRules(bridgeIface string, addr *net.IPNet, icc, insert } } - if addr.IP.To4() != nil { + if prefix.Addr().Is4() { version = iptables.IPv4 inDropRule = iptables.Rule{ IPVer: version, Table: iptables.Filter, Chain: IsolationChain1, - Args: []string{"-i", bridgeIface, "!", "-d", addr.String(), "-j", "DROP"}, + Args: []string{"-i", bridgeIface, "!", "-d", prefix.String(), "-j", "DROP"}, } outDropRule = iptables.Rule{ IPVer: version, Table: iptables.Filter, Chain: IsolationChain1, - Args: []string{"-o", bridgeIface, "!", "-s", addr.String(), "-j", "DROP"}, + Args: []string{"-o", bridgeIface, "!", "-s", prefix.String(), "-j", "DROP"}, } } else { version = iptables.IPv6 @@ -716,13 +773,13 @@ func setupInternalNetworkRules(bridgeIface string, addr *net.IPNet, icc, insert IPVer: version, Table: iptables.Filter, Chain: IsolationChain1, - Args: []string{"-i", bridgeIface, "!", "-o", bridgeIface, "!", "-d", addr.String(), "-j", "DROP"}, + Args: []string{"-i", bridgeIface, "!", "-o", bridgeIface, "!", "-d", prefix.String(), "-j", "DROP"}, } outDropRule = iptables.Rule{ IPVer: version, Table: iptables.Filter, Chain: IsolationChain1, - Args: []string{"!", "-i", bridgeIface, "-o", bridgeIface, "!", "-s", addr.String(), "-j", "DROP"}, + Args: []string{"!", "-i", bridgeIface, "-o", bridgeIface, "!", "-s", prefix.String(), "-j", "DROP"}, } } diff --git a/libnetwork/drivers/bridge/setup_ip_tables_linux_test.go b/libnetwork/drivers/bridge/setup_ip_tables_linux_test.go index 0827378576..3c82a4ba25 100644 --- a/libnetwork/drivers/bridge/setup_ip_tables_linux_test.go +++ b/libnetwork/drivers/bridge/setup_ip_tables_linux_test.go @@ -170,19 +170,13 @@ func assertChainConfig(d *driver, t *testing.T) { func assertBridgeConfig(config *networkConfiguration, br *bridgeInterface, d *driver, t *testing.T) { nw := bridgeNetwork{ config: config, + driver: d, + bridge: br, } - nw.driver = d - // Attempt programming of ip tables. - err := nw.setupIP4Tables(config, br) - if err != nil { - t.Fatalf("%v", err) - } - if d.config.EnableIP6Tables { - if err := nw.setupIP6Tables(config, br); err != nil { - t.Fatalf("%v", err) - } - } + fwn, err := nw.newIptablesNetwork() + assert.NilError(t, err) + assert.Check(t, fwn != nil, "no firewaller network") } // Regression test for https://github.com/moby/moby/issues/46445