Merge pull request #47481 from akerouanton/25.0-internal-bridge

[25.0 backport] Make 'internal' bridge networks accessible from host
This commit is contained in:
Sebastiaan van Stijn 2024-03-01 11:57:38 +01:00 committed by GitHub
commit 06767446fe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 63 additions and 8 deletions

View file

@ -477,3 +477,60 @@ func TestDefaultBridgeAddresses(t *testing.T) {
})
}
}
// Test that a container on an 'internal' network has IP connectivity with
// the host (on its own subnet, because the n/w bridge has an address on that
// subnet, and it's in the host's namespace).
// Regression test for https://github.com/moby/moby/issues/47329
func TestInternalNwConnectivity(t *testing.T) {
skip.If(t, testEnv.DaemonInfo.OSType == "windows")
ctx := setupTest(t)
d := daemon.New(t)
d.StartWithBusybox(ctx, t, "-D", "--experimental", "--ip6tables")
defer d.Stop(t)
c := d.NewClientT(t)
defer c.Close()
const bridgeName = "intnw"
const gw4 = "172.30.0.1"
const gw6 = "fda9:4130:4715::1234"
network.CreateNoError(ctx, t, c, bridgeName,
network.WithInternal(),
network.WithIPv6(),
network.WithIPAM("172.30.0.0/24", gw4),
network.WithIPAM("fda9:4130:4715::/64", gw6),
network.WithDriver("bridge"),
network.WithOption("com.docker.network.bridge.name", bridgeName),
)
defer network.RemoveNoError(ctx, t, c, bridgeName)
const ctrName = "intctr"
id := container.Run(ctx, t, c,
container.WithName(ctrName),
container.WithImage("busybox:latest"),
container.WithCmd("top"),
container.WithNetworkMode(bridgeName),
)
defer c.ContainerRemove(ctx, id, containertypes.RemoveOptions{Force: true})
execCtx, cancel := context.WithTimeout(ctx, 20*time.Second)
defer cancel()
res := container.ExecT(execCtx, t, c, id, []string{"ping", "-c1", "-W3", gw4})
assert.Check(t, is.Equal(res.ExitCode, 0))
assert.Check(t, is.Equal(res.Stderr(), ""))
assert.Check(t, is.Contains(res.Stdout(), "1 packets transmitted, 1 packets received"))
res = container.ExecT(execCtx, t, c, id, []string{"ping6", "-c1", "-W3", gw6})
assert.Check(t, is.Equal(res.ExitCode, 0))
assert.Check(t, is.Equal(res.Stderr(), ""))
assert.Check(t, is.Contains(res.Stdout(), "1 packets transmitted, 1 packets received"))
// Addresses outside the internal subnet must not be accessible.
res = container.ExecT(execCtx, t, c, id, []string{"ping", "-c1", "-W3", "8.8.8.8"})
assert.Check(t, is.Equal(res.ExitCode, 1))
assert.Check(t, is.Contains(res.Stderr(), "Network is unreachable"))
}

View file

@ -32,10 +32,6 @@ func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error {
// are decoupled, we should assign it only when it's really needed.
i.bridgeIPv4 = config.AddressIPv4
if config.Internal {
return nil
}
if !config.InhibitIPv4 {
addrv4List, err := i.addresses(netlink.FAMILY_V4)
if err != nil {
@ -57,8 +53,10 @@ func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error {
}
}
// Store the default gateway
i.gatewayIPv4 = config.AddressIPv4.IP
if !config.Internal {
// Store the default gateway
i.gatewayIPv4 = config.AddressIPv4.IP
}
return nil
}

View file

@ -20,12 +20,12 @@ func setupVerifyAndReconcileIPv4(config *networkConfiguration, i *bridgeInterfac
addrv4, _ := selectIPv4Address(addrsv4, config.AddressIPv4)
// Verify that the bridge has an IPv4 address.
if !config.Internal && addrv4.IPNet == nil {
if addrv4.IPNet == nil {
return &ErrNoIPAddr{}
}
// Verify that the bridge IPv4 address matches the requested configuration.
if config.AddressIPv4 != nil && addrv4.IPNet != nil && !addrv4.IP.Equal(config.AddressIPv4.IP) {
if config.AddressIPv4 != nil && !addrv4.IP.Equal(config.AddressIPv4.IP) {
return &IPv4AddrNoMatchError{IP: addrv4.IP, CfgIP: config.AddressIPv4.IP}
}