Don't configure IPv6 addr/gw when IPv6 disabled.

When IPv6 is disabled in a container by, for example, using the --sysctl
option - an IPv6 address/gateway is still allocated. Don't attempt to
apply that config because doing so enables IPv6 on the interface.

Signed-off-by: Rob Murray <rob.murray@docker.com>
This commit is contained in:
Rob Murray 2024-03-06 16:31:30 +00:00
parent 4e53936f0a
commit ef5295cda4
2 changed files with 79 additions and 3 deletions

View file

@ -3,6 +3,7 @@ package networking
import (
"context"
"fmt"
"regexp"
"testing"
"time"
@ -12,6 +13,7 @@ import (
"github.com/docker/docker/integration/internal/network"
"github.com/docker/docker/testutil"
"github.com/docker/docker/testutil/daemon"
"github.com/google/go-cmp/cmp/cmpopts"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/skip"
@ -594,3 +596,68 @@ func TestInternalNwConnectivity(t *testing.T) {
assert.Check(t, is.Equal(res.ExitCode, 1))
assert.Check(t, is.Contains(res.Stderr(), "Network is unreachable"))
}
// Check that the container's interface has no IPv6 address when IPv6 is
// disabled in a container via sysctl.
func TestDisableIPv6Addrs(t *testing.T) {
skip.If(t, testEnv.DaemonInfo.OSType == "windows")
ctx := setupTest(t)
d := daemon.New(t)
d.StartWithBusybox(ctx, t)
defer d.Stop(t)
c := d.NewClientT(t)
defer c.Close()
testcases := []struct {
name string
sysctls map[string]string
expIPv6 bool
}{
{
name: "IPv6 enabled",
expIPv6: true,
},
{
name: "IPv6 disabled",
sysctls: map[string]string{"net.ipv6.conf.all.disable_ipv6": "1"},
},
}
const netName = "testnet"
network.CreateNoError(ctx, t, c, netName,
network.WithIPv6(),
network.WithIPAM("fda0:ef3d:6430:abcd::/64", "fda0:ef3d:6430:abcd::1"),
)
defer network.RemoveNoError(ctx, t, c, netName)
inet6RE := regexp.MustCompile(`inet6[ \t]+[0-9a-f:]*`)
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
ctx := testutil.StartSpan(ctx, t)
opts := []func(config *container.TestContainerConfig){
container.WithCmd("ip", "a"),
container.WithNetworkMode(netName),
}
if len(tc.sysctls) > 0 {
opts = append(opts, container.WithSysctls(tc.sysctls))
}
runRes := container.RunAttach(ctx, t, c, opts...)
defer c.ContainerRemove(ctx, runRes.ContainerID,
containertypes.RemoveOptions{Force: true},
)
stdout := runRes.Stdout.String()
inet6 := inet6RE.FindAllString(stdout, -1)
if tc.expIPv6 {
assert.Check(t, len(inet6) > 0, "Expected IPv6 addresses but found none.")
} else {
assert.Check(t, is.DeepEqual(inet6, []string{}, cmpopts.EquateEmpty()))
}
})
}
}

View file

@ -90,8 +90,12 @@ func (sb *Sandbox) updateGateway(ep *Endpoint) error {
return fmt.Errorf("failed to set gateway while updating gateway: %v", err)
}
if err := osSbox.SetGatewayIPv6(joinInfo.gw6); err != nil {
return fmt.Errorf("failed to set IPv6 gateway while updating gateway: %v", err)
// If IPv6 has been disabled in the sandbox a gateway may still have been
// configured, don't attempt to apply it.
if ipv6, ok := sb.ipv6Enabled(); !ok || ipv6 {
if err := osSbox.SetGatewayIPv6(joinInfo.gw6); err != nil {
return fmt.Errorf("failed to set IPv6 gateway while updating gateway: %v", err)
}
}
return nil
@ -279,7 +283,12 @@ func (sb *Sandbox) populateNetworkResources(ep *Endpoint) error {
ifaceOptions = append(ifaceOptions, osl.WithIPv4Address(i.addr), osl.WithRoutes(i.routes))
if i.addrv6 != nil && i.addrv6.IP.To16() != nil {
ifaceOptions = append(ifaceOptions, osl.WithIPv6Address(i.addrv6))
// If IPv6 has been disabled in the Sandbox, an IPv6 address will still have
// been allocated. Don't apply it, because doing so would enable IPv6 on the
// interface.
if ipv6, ok := sb.ipv6Enabled(); !ok || ipv6 {
ifaceOptions = append(ifaceOptions, osl.WithIPv6Address(i.addrv6))
}
}
if len(i.llAddrs) != 0 {
ifaceOptions = append(ifaceOptions, osl.WithLinkLocalAddresses(i.llAddrs))