Make 'internal' bridge networks accessible from host
Prior to release 25.0.0, the bridge in an internal network was assigned
an IP address - making the internal network accessible from the host,
giving containers on the network access to anything listening on the
bridge's address (or INADDR_ANY on the host).
This change restores that behaviour. It does not restore the default
route that was configured in the container, because packets sent outside
the internal network's subnet have always been dropped. So, a 'connect()'
to an address outside the subnet will still fail fast.
Signed-off-by: Rob Murray <rob.murray@docker.com>
(cherry picked from commit 419f5a6372
)
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
This commit is contained in:
parent
00b2e1072b
commit
c761353e7c
3 changed files with 63 additions and 8 deletions
|
@ -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"))
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue