Skip to content

Commit

Permalink
Make 'internal' bridge networks accessible from host
Browse files Browse the repository at this point in the history
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 419f5a6)
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
  • Loading branch information
robmry authored and akerouanton committed Mar 1, 2024
1 parent 00b2e10 commit c761353
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 8 deletions.
57 changes: 57 additions & 0 deletions integration/networking/bridge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
}
10 changes: 4 additions & 6 deletions libnetwork/drivers/bridge/setup_ipv4_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}
Expand Down
4 changes: 2 additions & 2 deletions libnetwork/drivers/bridge/setup_verify_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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}
}

Expand Down

0 comments on commit c761353

Please sign in to comment.