From 60eece38cd2c5f41f948cd463a6ee0f0ad2f9d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Maldonado?= Date: Fri, 4 Oct 2024 01:53:46 +0200 Subject: Fix: setup user chains even if there are running containers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the DOCKER-USER chains are set up on firewall reload or network creation. If there are running containers at startup, configureNetworking won't be called (daemon/daemon_unix.go), so the user chains won't be setup. This commit puts the setup logic on a separate function, and calls it on the original place and on initNetworkController. Signed-off-by: Andrés Maldonado (cherry picked from commit a8bfa83667fb7c31e7274dc83a2aa9c98ace2af2) Signed-off-by: Justin Alvarez --- daemon/daemon_unix.go | 4 ++++ integration/daemon/daemon_test.go | 29 +++++++++++++++++++++++++++++ libnetwork/controller.go | 17 ++++++++++++----- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index 1143dda063..f6704df752 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -852,6 +852,10 @@ func (daemon *Daemon) initNetworkController(cfg *config.Config, activeSandboxes return err } + if err := daemon.netController.SetupUserChains(); err != nil { + log.G(context.TODO()).WithError(err).Warnf("initNetworkController") + } + // Set HostGatewayIP to the default bridge's IP if it is empty setHostGatewayIP(daemon.netController, cfg) return nil diff --git a/integration/daemon/daemon_test.go b/integration/daemon/daemon_test.go index a6436ae7da..045f9bed4f 100644 --- a/integration/daemon/daemon_test.go +++ b/integration/daemon/daemon_test.go @@ -388,6 +388,7 @@ func TestLiveRestore(t *testing.T) { t.Run("volume references", testLiveRestoreVolumeReferences) t.Run("autoremove", testLiveRestoreAutoRemove) + t.Run("user chains", testLiveRestoreUserChainsSetup) } func testLiveRestoreAutoRemove(t *testing.T) { @@ -606,6 +607,34 @@ func testLiveRestoreVolumeReferences(t *testing.T) { }) } +func testLiveRestoreUserChainsSetup(t *testing.T) { + skip.If(t, testEnv.IsRootless(), "rootless daemon uses it's own network namespace") + + t.Parallel() + ctx := testutil.StartSpan(baseContext, t) + + t.Run("user chains should be inserted", func(t *testing.T) { + d := daemon.New(t) + d.StartWithBusybox(ctx, t, "--live-restore") + t.Cleanup(func() { + d.Stop(t) + d.Cleanup(t) + }) + + c := d.NewClientT(t) + + cID := container.Run(ctx, t, c, container.WithCmd("top")) + defer c.ContainerRemove(ctx, cID, containertypes.RemoveOptions{Force: true}) + + d.Stop(t) + icmd.RunCommand("iptables", "--flush", "FORWARD").Assert(t, icmd.Success) + d.Start(t, "--live-restore") + + result := icmd.RunCommand("iptables", "-S", "FORWARD", "1") + assert.Check(t, is.Equal(strings.TrimSpace(result.Stdout()), "-A FORWARD -j DOCKER-USER"), "the jump to DOCKER-USER should be the first rule in the FORWARD chain") + }) +} + func TestDaemonDefaultBridgeWithFixedCidrButNoBip(t *testing.T) { skip.If(t, runtime.GOOS == "windows") diff --git a/libnetwork/controller.go b/libnetwork/controller.go index 8341946756..9c066d238e 100644 --- a/libnetwork/controller.go +++ b/libnetwork/controller.go @@ -707,15 +707,22 @@ addToStore: c.mu.Unlock() } - // Sets up the DOCKER-USER chain for each iptables version (IPv4, IPv6) - // that's enabled in the controller's configuration. + if err := c.SetupUserChains(); err != nil { + log.G(context.TODO()).WithError(err).Warnf("Controller.NewNetwork %s:", name) + } + + return nw, nil +} + +// Sets up the DOCKER-USER chain for each iptables version (IPv4, IPv6) that's +// enabled in the controller's configuration. +func (c *Controller) SetupUserChains() error { for _, ipVersion := range c.enabledIptablesVersions() { if err := setupUserChain(ipVersion); err != nil { - log.G(context.TODO()).WithError(err).Warnf("Controller.NewNetwork %s:", name) + return err } } - - return nw, nil + return nil } var joinCluster NetworkWalker = func(nw *Network) bool { -- 2.27.0