diff --git a/daemon/libnetwork/drivers/bridge/bridge_linux.go b/daemon/libnetwork/drivers/bridge/bridge_linux.go index 1ac1affed1..8af622e318 100644 --- a/daemon/libnetwork/drivers/bridge/bridge_linux.go +++ b/daemon/libnetwork/drivers/bridge/bridge_linux.go @@ -880,14 +880,28 @@ func (d *driver) createNetwork(ctx context.Context, config *networkConfiguration config.EnableIPv4 && d.config.EnableIPForwarding, "setupIPv4Forwarding", func(*networkConfiguration, *bridgeInterface) error { - return setupIPv4Forwarding(d.firewaller, d.config.EnableIPTables && !d.config.DisableFilterForwardDrop) + ffd, ok := d.firewaller.(filterForwardDropper) + if !ok { + // The firewaller can't drop non-Docker forwarding. It's up to the user to enable + // forwarding on their host, and configure their firewall appropriately. + return checkIPv4Forwarding() + } + // Enable forwarding and set a default-drop forwarding policy if necessary. + return setupIPv4Forwarding(ffd, d.config.EnableIPTables && !d.config.DisableFilterForwardDrop) }, }, { config.EnableIPv6 && d.config.EnableIPForwarding, "setupIPv6Forwarding", func(*networkConfiguration, *bridgeInterface) error { - return setupIPv6Forwarding(d.firewaller, d.config.EnableIP6Tables && !d.config.DisableFilterForwardDrop) + ffd, ok := d.firewaller.(filterForwardDropper) + if !ok { + // The firewaller can't drop non-Docker forwarding. It's up to the user to enable + // forwarding on their host, and configure their firewall appropriately. + return checkIPv6Forwarding() + } + // Enable forwarding and set a default-drop forwarding policy if necessary. + return setupIPv6Forwarding(ffd, d.config.EnableIP6Tables && !d.config.DisableFilterForwardDrop) }, }, diff --git a/daemon/libnetwork/drivers/bridge/internal/firewaller/firewaller.go b/daemon/libnetwork/drivers/bridge/internal/firewaller/firewaller.go index ce24ee5092..9ab68aaa58 100644 --- a/daemon/libnetwork/drivers/bridge/internal/firewaller/firewaller.go +++ b/daemon/libnetwork/drivers/bridge/internal/firewaller/firewaller.go @@ -76,9 +76,6 @@ type Firewaller interface { // NewNetwork returns an object that can be used to add published ports and legacy // links for a bridge network. NewNetwork(ctx context.Context, nc NetworkConfig) (Network, error) - // FilterForwardDrop sets the default policy of the FORWARD chain in the filter - // table to DROP. - FilterForwardDrop(ctx context.Context, ipv IPVersion) error } // Network can be used to manipulate firewall rules for a bridge network. diff --git a/daemon/libnetwork/drivers/bridge/internal/firewaller/stub.go b/daemon/libnetwork/drivers/bridge/internal/firewaller/stub.go index cf884edd26..f09df48415 100644 --- a/daemon/libnetwork/drivers/bridge/internal/firewaller/stub.go +++ b/daemon/libnetwork/drivers/bridge/internal/firewaller/stub.go @@ -15,7 +15,6 @@ import ( type StubFirewaller struct { Config Networks map[string]*StubFirewallerNetwork - FFD map[IPVersion]bool // filter forward drop } func NewStubFirewaller(config Config) *StubFirewaller { @@ -24,7 +23,6 @@ func NewStubFirewaller(config Config) *StubFirewaller { // A real Firewaller shouldn't hold on to its own networks, the bridge driver is doing that. // But, for unit tests cross-checking the driver, this is useful. Networks: make(map[string]*StubFirewallerNetwork), - FFD: make(map[IPVersion]bool), } } @@ -41,11 +39,6 @@ func (fw *StubFirewaller) NewNetwork(_ context.Context, nc NetworkConfig) (Netwo return nw, nil } -func (fw *StubFirewaller) FilterForwardDrop(_ context.Context, ipv IPVersion) error { - fw.FFD[ipv] = true - return nil -} - type stubFirewallerLink struct { parentIP netip.Addr childIP netip.Addr diff --git a/daemon/libnetwork/drivers/bridge/internal/iptabler/iptabler.go b/daemon/libnetwork/drivers/bridge/internal/iptabler/iptabler.go index 340dae6257..0a51582e3b 100644 --- a/daemon/libnetwork/drivers/bridge/internal/iptabler/iptabler.go +++ b/daemon/libnetwork/drivers/bridge/internal/iptabler/iptabler.go @@ -91,6 +91,7 @@ func NewIptabler(ctx context.Context, config firewaller.Config) (*Iptabler, erro return ipt, nil } +// FilterForwardDrop sets the default policy of the FORWARD chain in the filter table to DROP. func (ipt *Iptabler) FilterForwardDrop(ctx context.Context, ipv firewaller.IPVersion) error { var iptv iptables.IPVersion switch ipv { diff --git a/daemon/libnetwork/drivers/bridge/internal/nftabler/nftabler.go b/daemon/libnetwork/drivers/bridge/internal/nftabler/nftabler.go index 670c35175b..e0fe055bd9 100644 --- a/daemon/libnetwork/drivers/bridge/internal/nftabler/nftabler.go +++ b/daemon/libnetwork/drivers/bridge/internal/nftabler/nftabler.go @@ -85,21 +85,6 @@ func NewNftabler(ctx context.Context, config firewaller.Config) (*Nftabler, erro return nft, nil } -func (nft *Nftabler) getTable(ipv firewaller.IPVersion) nftables.TableRef { - if ipv == firewaller.IPv4 { - return nft.table4 - } - return nft.table6 -} - -func (nft *Nftabler) FilterForwardDrop(ctx context.Context, ipv firewaller.IPVersion) error { - table := nft.getTable(ipv) - if err := table.Chain(ctx, forwardChain).SetPolicy("drop"); err != nil { - return err - } - return nftApply(ctx, table) -} - // init creates the bridge driver's nftables table for IPv4 or IPv6. func (nft *Nftabler) init(ctx context.Context, family nftables.Family) (nftables.TableRef, error) { // Instantiate the table. diff --git a/daemon/libnetwork/drivers/bridge/setup_ip_forwarding.go b/daemon/libnetwork/drivers/bridge/setup_ip_forwarding.go index 4f2845d0f5..0ebd4eb17d 100644 --- a/daemon/libnetwork/drivers/bridge/setup_ip_forwarding.go +++ b/daemon/libnetwork/drivers/bridge/setup_ip_forwarding.go @@ -4,6 +4,7 @@ package bridge import ( "context" + "errors" "fmt" "os" @@ -17,7 +18,24 @@ const ( ipv6ForwardConfAll = "/proc/sys/net/ipv6/conf/all/forwarding" ) -func setupIPv4Forwarding(fw firewaller.Firewaller, wantFilterForwardDrop bool) (retErr error) { +type filterForwardDropper interface { + FilterForwardDrop(context.Context, firewaller.IPVersion) error +} + +func checkIPv4Forwarding() error { + enabled, err := getKernelBoolParam(ipv4ForwardConf) + if err != nil { + return fmt.Errorf("checking IPv4 forwarding: %w", err) + } + if enabled { + return nil + } + // It's the user's responsibility to enable forwarding and secure their host. Or, + // start docker with --ip-forward=false to disable this check. + return errors.New("IPv4 forwarding is disabled: check your host's firewalling and set sysctl net.ipv4.ip_forward=1, or disable this check using daemon option --ip-forward=false") +} + +func setupIPv4Forwarding(ffd filterForwardDropper, wantFilterForwardDrop bool) (retErr error) { changed, err := configureIPForwarding(ipv4ForwardConf, '1') if err != nil { return err @@ -34,16 +52,35 @@ func setupIPv4Forwarding(fw firewaller.Firewaller, wantFilterForwardDrop bool) ( // When enabling ip_forward set the default policy on forward chain to drop. if changed && wantFilterForwardDrop { - if err := fw.FilterForwardDrop(context.TODO(), firewaller.IPv4); err != nil { + if err := ffd.FilterForwardDrop(context.TODO(), firewaller.IPv4); err != nil { return err } } return nil } -func setupIPv6Forwarding(fw firewaller.Firewaller, wantFilterForwardDrop bool) (retErr error) { +func checkIPv6Forwarding() error { + enabledDef, err := getKernelBoolParam(ipv6ForwardConfDefault) + if err != nil { + return fmt.Errorf("checking IPv6 default forwarding: %w", err) + } + enabledAll, err := getKernelBoolParam(ipv6ForwardConfAll) + if err != nil { + return fmt.Errorf("checking IPv6 global forwarding: %w", err) + } + if enabledDef && enabledAll { + return nil + } + + // It's the user's responsibility to enable forwarding and secure their host. Or, + // start docker with --ip-forward=false to disable this check. + return errors.New("IPv6 global forwarding is disabled: check your host's firewalling and set sysctls net.ipv6.conf.all.forwarding=1 and net.ipv6.conf.default.forwarding=1, or disable this check using daemon option --ip-forward=false") +} + +func setupIPv6Forwarding(ffd filterForwardDropper, wantFilterForwardDrop bool) (retErr error) { // Set IPv6 default.forwarding, if needed. - // FIXME(robmry) - is it necessary to set this, setting "all" (below) does the job? + // Setting "all" (below) sets "default" as well, but need to check that "default" is + // set even if "all" is already set. changedDef, err := configureIPForwarding(ipv6ForwardConfDefault, '1') if err != nil { return err @@ -74,7 +111,7 @@ func setupIPv6Forwarding(fw firewaller.Firewaller, wantFilterForwardDrop bool) ( } if (changedAll || changedDef) && wantFilterForwardDrop { - if err := fw.FilterForwardDrop(context.TODO(), firewaller.IPv6); err != nil { + if err := ffd.FilterForwardDrop(context.TODO(), firewaller.IPv6); err != nil { return err } } diff --git a/daemon/libnetwork/drivers/bridge/setup_ip_forwarding_test.go b/daemon/libnetwork/drivers/bridge/setup_ip_forwarding_test.go index 65da1b9f79..7567c169de 100644 --- a/daemon/libnetwork/drivers/bridge/setup_ip_forwarding_test.go +++ b/daemon/libnetwork/drivers/bridge/setup_ip_forwarding_test.go @@ -14,19 +14,20 @@ import ( is "gotest.tools/v3/assert/cmp" ) -type ffdTestFirewaller struct { - ffd firewaller.IPVersion -} - -// NewNetwork is part of interface [firewaller.Firewaller]. -func (f *ffdTestFirewaller) NewNetwork(_ context.Context, _ firewaller.NetworkConfig) (firewaller.Network, error) { - return nil, nil +type ffDropper struct { + ffDrop4 bool + ffDrop6 bool } // FilterForwardDrop is part of interface [firewaller.Firewaller]. Just enough to check // it was called with the expected IPVersion. -func (f *ffdTestFirewaller) FilterForwardDrop(_ context.Context, ipv firewaller.IPVersion) error { - f.ffd = ipv +func (f *ffDropper) FilterForwardDrop(_ context.Context, ipv firewaller.IPVersion) error { + switch ipv { + case firewaller.IPv4: + f.ffDrop4 = true + case firewaller.IPv6: + f.ffDrop6 = true + } return nil } @@ -36,21 +37,16 @@ func TestSetupIPForwarding(t *testing.T) { for _, wantFFD := range []bool{true, false} { t.Run(fmt.Sprintf("wantFFD=%v", wantFFD), func(t *testing.T) { // Disable IP Forwarding if enabled - _, err := configureIPForwarding(ipv4ForwardConf, '0') - assert.NilError(t, err) + setForwarding(t, '0') // Set IP Forwarding - fw := &ffdTestFirewaller{} - err = setupIPv4Forwarding(fw, wantFFD) + ffd := &ffDropper{} + err := setupIPv4Forwarding(ffd, wantFFD) assert.NilError(t, err) // Check what the firewaller was told. - if wantFFD { - assert.Check(t, is.Equal(fw.ffd, firewaller.IPv4)) - } else { - var noVer firewaller.IPVersion - assert.Check(t, is.Equal(fw.ffd, noVer)) - } + assert.Check(t, is.Equal(ffd.ffDrop4, wantFFD)) + assert.Check(t, !ffd.ffDrop6) // Read new setting procSetting, err := os.ReadFile(ipv4ForwardConf) @@ -65,23 +61,15 @@ func TestSetupIP6Forwarding(t *testing.T) { for _, wantFFD := range []bool{true, false} { t.Run(fmt.Sprintf("wantFFD=%v", wantFFD), func(t *testing.T) { - _, err := configureIPForwarding(ipv6ForwardConfDefault, '0') - assert.NilError(t, err) - _, err = configureIPForwarding(ipv6ForwardConfAll, '0') - assert.NilError(t, err) + // Disable IP Forwarding if enabled + setForwarding(t, '0') // Set IP Forwarding - fw := &ffdTestFirewaller{} - err = setupIPv6Forwarding(fw, wantFFD) + ffd := &ffDropper{} + err := setupIPv6Forwarding(ffd, wantFFD) assert.NilError(t, err) - - // Check what the firewaller was told. - if wantFFD { - assert.Check(t, is.Equal(fw.ffd, firewaller.IPv6)) - } else { - var noVer firewaller.IPVersion - assert.Check(t, is.Equal(fw.ffd, noVer)) - } + assert.Check(t, !ffd.ffDrop4) + assert.Check(t, is.Equal(ffd.ffDrop6, wantFFD)) // Read new setting procSetting, err := os.ReadFile(ipv6ForwardConfDefault) @@ -93,3 +81,30 @@ func TestSetupIP6Forwarding(t *testing.T) { }) } } + +func TestCheckForwarding(t *testing.T) { + defer netnsutils.SetupTestOSContext(t)() + + setForwarding(t, '0') + err := checkIPv4Forwarding() + assert.Check(t, is.ErrorContains(err, "IPv4 forwarding is disabled")) + err = checkIPv6Forwarding() + assert.Check(t, is.ErrorContains(err, "IPv6 global forwarding is disabled")) + + setForwarding(t, '1') + err = checkIPv4Forwarding() + assert.Check(t, err) + err = checkIPv6Forwarding() + assert.Check(t, err) +} + +func setForwarding(t *testing.T, val byte) { + for _, sysctl := range []string{ + ipv4ForwardConf, + ipv6ForwardConfDefault, + ipv6ForwardConfAll, + } { + err := os.WriteFile(sysctl, []byte{val, '\n'}, 0o644) + assert.NilError(t, err) + } +} diff --git a/hack/make/.integration-daemon-start b/hack/make/.integration-daemon-start index 78f056356f..76d2efecdf 100644 --- a/hack/make/.integration-daemon-start +++ b/hack/make/.integration-daemon-start @@ -67,6 +67,13 @@ fi dockerd="dockerd" +# When running with the nftables backend, dockerd will not enable IP forwarding (by default, it +# will error on network creation if forwarding is not enabled). +if [ "$DOCKER_FIREWALL_BACKEND" = "nftables" ]; then + sysctl -w net.ipv4.ip_forward=1 > /dev/null + sysctl -w net.ipv6.conf.all.forwarding=1 > /dev/null +fi + if [ -n "$DOCKER_ROOTLESS" ]; then if [ -z "$TEST_SKIP_INTEGRATION_CLI" ]; then echo >&2 '# DOCKER_ROOTLESS requires TEST_SKIP_INTEGRATION_CLI to be set' diff --git a/integration/internal/testutils/networking/firewall.go b/integration/internal/testutils/networking/firewall.go index c7ba4e48ce..0c03087fc3 100644 --- a/integration/internal/testutils/networking/firewall.go +++ b/integration/internal/testutils/networking/firewall.go @@ -1,7 +1,6 @@ package networking import ( - "fmt" "os/exec" "regexp" "strings" @@ -9,45 +8,29 @@ import ( "github.com/moby/moby/v2/testutil/daemon" "gotest.tools/v3/assert" + is "gotest.tools/v3/assert/cmp" "gotest.tools/v3/icmd" "gotest.tools/v3/poll" ) -const ( - // The name of the bridge driver's nftables tables. - nftTable = "docker-bridges" - // The name of the filter-FORWARD chain in nftTable. - nftFFChain = "filter-FORWARD" -) - // Find the policy in, for example "Chain FORWARD (policy ACCEPT)". var rePolicy = regexp.MustCompile("policy ([A-Za-z]+)") // SetFilterForwardPolicies sets the default policy for the FORWARD chain in -// the filter tables for both IPv4 and IPv6. The original policy is restored -// using t.Cleanup(). +// the iptables filter tables for both IPv4 and IPv6. The original policy is +// restored using t.Cleanup(). // // There's only one filter-FORWARD policy, so this won't behave well if used by // tests running in parallel in a single network namespace that expect different // behaviour. -func SetFilterForwardPolicies(t *testing.T, firewallBackend string, policy string) { - t.Helper() - if strings.HasPrefix(firewallBackend, "iptables") { - setIptablesFFP(t, policy) - return - } - if strings.HasPrefix(firewallBackend, "nftables") { - setNftablesFFP(t, policy) - return - } - t.Fatalf("unknown firewall backend %s", firewallBackend) -} - -func setIptablesFFP(t *testing.T, policy string) { +func SetFilterForwardPolicies(t *testing.T, policy string) { t.Helper() for _, iptablesCmd := range []string{"iptables", "ip6tables"} { - origPolicy, err := getChainPolicy(t, exec.Command(iptablesCmd, "-L", "FORWARD")) - assert.NilError(t, err, "failed to get iptables policy") + out, err := exec.Command(iptablesCmd, "-L", "FORWARD").Output() + assert.NilError(t, err, "failed to get %s policy", iptablesCmd) + opMatch := rePolicy.FindSubmatch(out) + assert.Assert(t, is.Len(opMatch, 2), "searching for policy: %w", err) + origPolicy := string(opMatch[1]) if origPolicy == policy { continue } @@ -62,42 +45,6 @@ func setIptablesFFP(t *testing.T, policy string) { } } -func setNftablesFFP(t *testing.T, policy string) { - t.Helper() - policy = strings.ToLower(policy) - for _, family := range []string{"ip", "ip6"} { - origPolicy, err := getChainPolicy(t, exec.Command("nft", "list", "chain", family, nftTable, nftFFChain)) - assert.NilError(t, err, "failed to get nftables policy") - if origPolicy == policy { - continue - } - cmd := func(p string) *exec.Cmd { - return exec.Command("nft", "add", "chain", family, nftTable, nftFFChain, "{", "policy", p, ";", "}") - } - if err := cmd(policy).Run(); err != nil { - t.Fatalf("Failed to set %s filter-FORWARD policy: %v", family, err) - } - t.Cleanup(func() { - if err := cmd(origPolicy).Run(); err != nil { - t.Logf("Failed to restore %s filter-FORWARD policy: %v", family, err) - } - }) - } -} - -func getChainPolicy(t *testing.T, cmd *exec.Cmd) (string, error) { - t.Helper() - out, err := cmd.Output() - if err != nil { - return "", fmt.Errorf("getting policy: %w", err) - } - opMatch := rePolicy.FindSubmatch(out) - if len(opMatch) != 2 { - return "", fmt.Errorf("searching for policy: %w", err) - } - return string(opMatch[1]), nil -} - // FirewalldRunning returns true if "firewall-cmd --state" reports "running". func FirewalldRunning() bool { state, err := exec.Command("firewall-cmd", "--state").CombinedOutput() diff --git a/integration/internal/testutils/networking/l3_segment_linux.go b/integration/internal/testutils/networking/l3_segment_linux.go index 26b4a69659..eb923eff2a 100644 --- a/integration/internal/testutils/networking/l3_segment_linux.go +++ b/integration/internal/testutils/networking/l3_segment_linux.go @@ -77,6 +77,8 @@ func (l3 *L3Segment) AddHost(t *testing.T, hostname, nsName, ifname string, addr l3.bridge.MustRun(t, "ip", "link", "set", hostname, "up", "master", l3.bridge.Iface) host.MustRun(t, "ip", "link", "set", host.Iface, "up") host.MustRun(t, "ip", "link", "set", "lo", "up") + host.MustRun(t, "sysctl", "-w", "net.ipv4.ip_forward=1") + host.MustRun(t, "sysctl", "-w", "net.ipv6.conf.all.forwarding=1") for _, addr := range addrs { host.MustRun(t, "ip", "addr", "add", addr.String(), "dev", host.Iface, "nodad") diff --git a/integration/network/bridge/bridge_linux_test.go b/integration/network/bridge/bridge_linux_test.go index 85a89bac13..671d744479 100644 --- a/integration/network/bridge/bridge_linux_test.go +++ b/integration/network/bridge/bridge_linux_test.go @@ -246,6 +246,8 @@ func TestIPRangeAt64BitLimit(t *testing.T) { func TestFilterForwardPolicy(t *testing.T) { skip.If(t, testEnv.IsRootless, "rootless has its own netns") skip.If(t, networking.FirewalldRunning(), "can't use firewalld in host netns to add rules in L3Segment") + skip.If(t, strings.HasPrefix(testEnv.FirewallBackendDriver(), "nftables"), "no policy is set for nftables") + ctx := setupTest(t) // Set up a netns for each test to avoid sysctl and iptables pollution. @@ -305,30 +307,17 @@ func TestFilterForwardPolicy(t *testing.T) { ) host := l3.Hosts[hostname] - getFwdPolicy := func(usingNftables bool, fam string) string { + getFwdPolicy := func(cmd string) string { t.Helper() - if usingNftables { - out := host.MustRun(t, "nft", "list chain "+fam+" docker-bridges filter-FORWARD") - if strings.Contains(out, "policy accept") { - return "ACCEPT" - } - if strings.Contains(out, "policy drop") { - return "DROP" - } - t.Fatalf("Failed to determine nftables filter-FORWARD policy: %s", out) - return "" - } else { - cmd := fam + "tables" - out := host.MustRun(t, cmd, "-S", "FORWARD") - if strings.HasPrefix(out, "-P FORWARD ACCEPT") { - return "ACCEPT" - } - if strings.HasPrefix(out, "-P FORWARD DROP") { - return "DROP" - } - t.Fatalf("Failed to determine %s FORWARD policy: %s", cmd, out) - return "" + out := host.MustRun(t, cmd, "-S", "FORWARD") + if strings.HasPrefix(out, "-P FORWARD ACCEPT") { + return "ACCEPT" } + if strings.HasPrefix(out, "-P FORWARD DROP") { + return "DROP" + } + t.Fatalf("Failed to determine %s FORWARD policy: %s", cmd, out) + return "" } type sysctls struct{ v4, v6def, v6all string } @@ -354,22 +343,21 @@ func TestFilterForwardPolicy(t *testing.T) { d.StartWithBusybox(ctx, t, tc.daemonArgs...) t.Cleanup(func() { d.Stop(t) }) }) - usingNftables := d.FirewallBackendDriver(t) == "nftables" c := d.NewClientT(t) t.Cleanup(func() { c.Close() }) // If necessary, the IPv4 policy should have been updated when the default bridge network was created. - assert.Check(t, is.Equal(getFwdPolicy(usingNftables, "ip"), tc.expPolicy)) + assert.Check(t, is.Equal(getFwdPolicy("iptables"), tc.expPolicy)) // IPv6 policy should not have been updated yet. - assert.Check(t, is.Equal(getFwdPolicy(usingNftables, "ip6"), "ACCEPT")) + assert.Check(t, is.Equal(getFwdPolicy("ip6tables"), "ACCEPT")) assert.Check(t, is.Equal(getSysctls(), sysctls{tc.expForwarding, tc.initForwarding, tc.initForwarding})) // If necessary, creating an IPv6 network should update the sysctls and policy. const netName = "testnetffp" network.CreateNoError(ctx, t, c, netName, network.WithIPv6()) t.Cleanup(func() { network.RemoveNoError(ctx, t, c, netName) }) - assert.Check(t, is.Equal(getFwdPolicy(usingNftables, "ip"), tc.expPolicy)) - assert.Check(t, is.Equal(getFwdPolicy(usingNftables, "ip6"), tc.expPolicy)) + assert.Check(t, is.Equal(getFwdPolicy("iptables"), tc.expPolicy)) + assert.Check(t, is.Equal(getFwdPolicy("ip6tables"), tc.expPolicy)) assert.Check(t, is.Equal(getSysctls(), sysctls{tc.expForwarding, tc.expForwarding, tc.expForwarding})) }) } diff --git a/integration/networking/bridge_linux_test.go b/integration/networking/bridge_linux_test.go index 47ec967f97..919d5d0871 100644 --- a/integration/networking/bridge_linux_test.go +++ b/integration/networking/bridge_linux_test.go @@ -358,7 +358,6 @@ func TestBridgeINCRouted(t *testing.T) { d := daemon.New(t) d.StartWithBusybox(ctx, t) t.Cleanup(func() { d.Stop(t) }) - firewallBackend := d.FirewallBackendDriver(t) c := d.NewClientT(t) t.Cleanup(func() { c.Close() }) @@ -457,10 +456,12 @@ func TestBridgeINCRouted(t *testing.T) { }, } - for _, fwdPolicy := range []string{"ACCEPT", "DROP"} { - networking.SetFilterForwardPolicies(t, firewallBackend, fwdPolicy) + runTests := func(testName, policy string) { networking.FirewalldReload(t, d) - t.Run(fwdPolicy, func(t *testing.T) { + t.Run(testName, func(t *testing.T) { + if policy != "" { + networking.SetFilterForwardPolicies(t, policy) + } for _, tc := range testcases { t.Run(tc.name+"/v4/ping", func(t *testing.T) { t.Parallel() @@ -497,6 +498,13 @@ func TestBridgeINCRouted(t *testing.T) { } }) } + + if strings.HasPrefix(d.FirewallBackendDriver(t), "iptables") { + runTests("iptables-ACCEPT", "ACCEPT") + runTests("iptables-DROP", "DROP") + } else { + runTests("nftables", "") + } } // TestAccessToPublishedPort checks that a container in one network can diff --git a/integration/networking/port_mapping_linux_test.go b/integration/networking/port_mapping_linux_test.go index 231258b4db..1993878d5e 100644 --- a/integration/networking/port_mapping_linux_test.go +++ b/integration/networking/port_mapping_linux_test.go @@ -648,7 +648,6 @@ func TestDirectRoutingOpenPorts(t *testing.T) { d := daemon.New(t) d.StartWithBusybox(ctx, t) t.Cleanup(func() { d.Stop(t) }) - firewallBackend := d.FirewallBackendDriver(t) c := d.NewClientT(t) t.Cleanup(func() { c.Close() }) @@ -770,9 +769,11 @@ func TestDirectRoutingOpenPorts(t *testing.T) { // Run the ping and http tests in two parallel groups, rather than waiting for // ping/http timeouts separately. (The iptables filter-FORWARD policy affects the // whole host, so ACCEPT/DROP tests can't be parallelized). - for _, fwdPolicy := range []string{"ACCEPT", "DROP"} { - networking.SetFilterForwardPolicies(t, firewallBackend, fwdPolicy) - t.Run(fwdPolicy, func(t *testing.T) { + runTests := func(testName, policy string) { + t.Run(testName, func(t *testing.T) { + if policy != "" { + networking.SetFilterForwardPolicies(t, policy) + } for gwMode := range networks { t.Run(gwMode+"/v4/ping", func(t *testing.T) { testPing(t, "ping", networks[gwMode].ipv4, expPingExit[gwMode]) @@ -795,6 +796,13 @@ func TestDirectRoutingOpenPorts(t *testing.T) { } }) } + + if strings.HasPrefix(d.FirewallBackendDriver(t), "iptables") { + runTests("iptables-ACCEPT", "ACCEPT") + runTests("iptables-DROP", "DROP") + } else { + runTests("nftables", "") + } } func TestAcceptFwMark(t *testing.T) {