bridge: factor out creation of network-level iptables rules

Create an iptablesNetwork containing all the info needed to
set up per-network iptables rules, give it methods to do
create the rules, and use it instead of per-rule-type calls
from driver.createNetwork().

Signed-off-by: Rob Murray <rob.murray@docker.com>
This commit is contained in:
Rob Murray
2025-03-14 16:52:08 +00:00
parent cea56c1d9c
commit 409707b633
4 changed files with 214 additions and 179 deletions

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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"},
}
}

View File

@@ -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