From 67ffa47090d4682456f4ee3231637ac298d2b9ad Mon Sep 17 00:00:00 2001 From: Rob Murray Date: Tue, 5 Aug 2025 10:51:35 +0100 Subject: [PATCH] nftables: don't enable IP forwarding For nftables only, never enable IP forwarding on the host. Instead, return an error on network creation if forwarding is not enabled, required by a bridge network, and --ip-forward=true. If IPv4 forwarding is not enabled when the daemon is started with nftables enabled and other config at defaults, the daemon will exit when it tries to create the default bridge. Otherwise, network creation will fail with an error if IPv4/IPv6 forwarding is not enabled when a network is created with IPv4/IPv6. It's the user's responsibility to configure and secure their host when they run Docker with nftables. Signed-off-by: Rob Murray --- .../libnetwork/drivers/bridge/bridge_linux.go | 18 ++++- .../bridge/internal/firewaller/firewaller.go | 3 - .../bridge/internal/firewaller/stub.go | 7 -- .../bridge/internal/iptabler/iptabler.go | 1 + .../bridge/internal/nftabler/nftabler.go | 15 ---- .../drivers/bridge/setup_ip_forwarding.go | 47 +++++++++-- .../bridge/setup_ip_forwarding_test.go | 81 +++++++++++-------- hack/make/.integration-daemon-start | 7 ++ .../internal/testutils/networking/firewall.go | 71 +++------------- .../testutils/networking/l3_segment_linux.go | 2 + .../network/bridge/bridge_linux_test.go | 42 ++++------ integration/networking/bridge_linux_test.go | 16 +++- .../networking/port_mapping_linux_test.go | 16 +++- 13 files changed, 164 insertions(+), 162 deletions(-) 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) {