Commit Graph

3873 Commits

Author SHA1 Message Date
Rob Murray
a0ff0a361e iptables: Direct routing DROP rules per-container, not per-port
Commit 27adcd5 ("libnet/d/bridge: drop connections to lo mappings, and
direct remote connections") introduced an iptables rule to drop 'direct'
remote connections made to the container's IP address - for each
published port on the container.

The normal filter-FORWARD rules would then drop packets sent directly to
unpublished ports. This rule was only created along with the rest of port
publishing (when a container's endpoint was selected as its gateway). Until
then, all packets addressed directly to the container's ports were dropped
by the filter-FORWARD rules.

But, the rule doesn't need to be per-port. Just drop packets sent
directly to a container's address unless they originate on the host.

That means fewer rules, that can be created along with the endpoint (then
directly-routed get dropped at the same point whether or not the endpoint
is currently the gateway - very slightly earlier than when it's not the
gateway).

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-24 12:00:44 +01:00
Rob Murray
dea236e0ce Split iptabler into multiple files
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-23 10:41:15 +01:00
Rob Murray
282b3f7b97 Move bridge driver iptables code into its own package
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-23 10:41:15 +01:00
Rob Murray
8c36a22e79 Rename function insertMirroredWSL2Rule
It's now shouldInsertMirroredWSL2Rule, because it's a test and
doesn't do the insertion.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-23 10:41:15 +01:00
Rob Murray
aa4abaf820 Use firewaller (iptabler) structs in iptables unit tests
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-23 10:41:14 +01:00
Rob Murray
75c60598b7 Move clearConntrackEntries to bridge_linux.go
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-23 10:41:14 +01:00
Sebastiaan van Stijn
7c52c4d92e update go:build tags to go1.23 to align with vendor.mod
Go maintainers started to unconditionally update the minimum go version
for golang.org/x/ dependencies to go1.23, which means that we'll no longer
be able to support any version below that when updating those dependencies;

> all: upgrade go directive to at least 1.23.0 [generated]
>
> By now Go 1.24.0 has been released, and Go 1.22 is no longer supported
> per the Go Release Policy (https://go.dev/doc/devel/release#policy).
>
> For golang/go#69095.

This updates our minimum version to go1.23, as we won't be able to maintain
compatibility with older versions because of the above.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-17 15:43:19 +02:00
Rob Murray
619f1ddd05 Warn when no external DNS nameservers are found
Since commit 925b484 ("No fallback nameservers for internal
resolver"), if the host's resolv.conf has no nameservers and
no servers are supplied via config, the internal resolver will
not use Google's DNS - so the container will not be able to
resolve external DNS requests.

That can happen when container's are "restart-always" and the
docker daemon starts before the host's DNS is configured.

So, to highlight the issue (which may not be an error, but
probably is), include a warning in the container's resolv.conf
file.

Also, log a warning - logs currently say "No non-localhost DNS
nameservers are left in resolv.conf. Using default external
servers". But, that's misleading because it's from an initial
resolv.conf setup, before the internal resolver configured without
those fallbacks - we'll drop the fallbacks completely once the
default bridge has an internal resolver).

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-17 10:51:06 +01:00
Rob Murray
380ded6309 Store an endpoint count for networks, for downgrade
Since commit 51d7f95 ("libnet: remove struct endpointCnt") an
endpoint count for networks has not been persisted.

But, on downgrade to a version older than that commit, the
missing field caused daemon startup to fail.

So, create the count in the store - it only needs to exist, it's
no longer maintained as a count of endpoints. On downgrade, the
count is probably zero anyway (the daemon is stopped), but the
older daemon fixes it up on startup if necessary.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-15 17:59:34 +01:00
Rob Murray
57bf7a8c70 bridge: Add a missing error check for firewaller setup
It got lost in commit 29e0db2 ("Factor out top-level iptables
setup into its own object").

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-15 12:05:10 +01:00
Rob Murray
3fc5bfd565 Merge pull request #49778 from robmry/fix_delete_legacy_link
Fix removal of legacy links
2025-04-10 15:16:00 +01:00
Rob Murray
4d35864c3d Fix removal of legacy links
It's possible to remove a legacy link from running containers.
When that happens, the Sandbox's Endpoints are removed and
re-added.

Since commit 65120d5 ("Create bridge veth in container netns")
the veth device has been created in the container's netns. When
that happens, a flag is set on the Endpoint to note that it
does not need to be moved into the netns.

But, during the Leave/Join (Sandbox.Refresh) the veth is moved
out of the netns. So, clear the flag during the Leave, to note
that it needs to be moved back in during the Join.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-10 14:22:40 +01:00
Paweł Gronowski
325076df0c Merge pull request #49765 from robmry/iptables_bridge_driver_level_rules
Put bridge driver's top-level iptables config in a separate object
2025-04-10 11:08:51 +00:00
Albin Kerouanton
27e7c650b8 Merge pull request #49773 from akerouanton/improve-has-active-endpoints-error
libnet: add ep name in 'has active endpoints' error
2025-04-09 15:14:37 +02:00
Rob Murray
29e0db25e7 Factor out top-level iptables setup into its own object
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-09 10:54:14 +01:00
Sebastiaan van Stijn
bcbcbb73fa Merge pull request #49743 from dmcgowan/update-archive-to-go-archive
Update archive to use github.com/moby/go-archive
2025-04-09 11:51:14 +02:00
Paweł Gronowski
5172617617 Merge pull request #49774 from akerouanton/fix-ContainerStart-trace
libnet/osl: independent OTel trace for advertiseAddrs
2025-04-09 09:29:48 +00:00
Albin Kerouanton
241d685574 libnet: add ep name in 'has active endpoints' error
There have been numerous reports of the "has active endpoints" error
over the years. Historically, there were some faulty code paths that
could lead to this error, but we believe they all have been fixed by
now.

However, users are still facing this error from time to time. Either
because they forgot that some containers are still running, or because
we still have bugs lying around.

To help users figure whether this error is legitimate, and what triggers
it, add endpoint names (which are just container names) to the error
message.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 10:53:56 +02:00
Albin Kerouanton
489cd7edfc api, daemon, libnet: add a 'trigger' baggage member
Add an OTel span processor copying the 'trigger' baggage member
propagated through contexts to all children spans. It's used to identify
what triggered a trace / span (API call, libnet init, etc...)

All code paths that call libnet's `NewNetwork` set this baggage member
with a unique value.

For instance, this can be used to distinguish bridge's `createNetwork`
spans triggered by daemon / libnet initialization from custom network
creation triggerd by an API call.

Two util functions are added to wrap `baggage.New` and
`baggage.NewMemberRaw` to make it easier to deal with baggage and
members by panicking on error. These should not be used with dynamic
values.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 08:45:33 +02:00
Albin Kerouanton
31ac5cb6d9 libnet: New: plumb context
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 08:45:33 +02:00
Albin Kerouanton
667c7d70b3 libnet/d/bridge: trace network setup steps
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 08:45:33 +02:00
Albin Kerouanton
eaae4b5fb6 libnet/d/bridge: put span prefix in var
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 08:45:33 +02:00
Albin Kerouanton
78be7ebad7 libnet/d/bridge: trace createNetwork
Plumb context from the API down to libnet driver method `CreateNetwork`,
and add an OTel span to the bridge driver's `createNetwork` method.
Include a few attributes describing the network configuration (e.g.
IPv4/IPv6, ICC, internal and MTU).

A new util function, `RecordStatus`, is added to the `otelutil` package
to easily record any error, and update the span status accordingly.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 08:45:33 +02:00
Albin Kerouanton
f8806f2b80 libnet/osl: independent OTel trace for advertiseAddrs
Since commit `eaa84bc`, when a container joins a network, we broadcast
unsolicited ARP/NAs to other containers connected to that network. The
initial advertisement is sent synchronously, and then remaining
advertisements (by default, 2) are sent asynchronously at a regular
interval (by default, 1 second).

An OTel span records the time spent sending subsequent advertisements,
but it's attached to the parent span `libnetwork.osl.AddInterface` so it
affects the overall latency reported by the trace.

The real latency (i.e. excluding the latency of that asynchronous
process), is pretty much what CLI users perceive, so it's an important
measure. It's available on the top-most span in the trace, but limiting
the trace to the real time taken by the Engine to process the HTTP
request seems better.

With this change, the initial advertisement is now tracked by a
dedicated span, and a new independent trace (containing a single span)
is created and linked to the 'initial' span / HTTP trace.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 08:43:34 +02:00
Derek McGowan
d0154d3e59 Update to use github.com/moby/go-archive
Update use of idtools to moby/user for archive and other deprecated uses

Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-04-08 17:35:05 -07:00
Rob Murray
dbea045e0d Report firewalld reload time in Info.FirewallBackend
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-08 10:26:41 +01:00
Rob Murray
a527e5a546 Restore iptables for current networks on firewalld reload
Using iptables.OnReloaded to restore individual per-network rules
on firewalld reload means rules for deleted networks pop back in
to existence (because there was no way to delete the callbacks on
network-delete).

So, on firewalld reload, walk over current networks and ask them
to restore their iptables rules.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-08 10:26:41 +01:00
Rob Murray
9ba5c5d70e Merge pull request #49732 from robmry/nftables_primitives
Add utils for manipulating nftables rules
2025-04-08 09:25:41 +01:00
Rob Murray
a0a86d0982 Add Info.FirewallBackend
Report FirewallBackend in "docker info".

It's currently "iptables" or "iptables+firewalld" on Linux, and
omitted on Windows.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-07 16:56:49 +01:00
Albin Kerouanton
4eebd2c920 libnet: TestNetworkStore: replace assert.Equal with Check
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-07 16:25:00 +02:00
Albin Kerouanton
40650c6982 libnet: de-flake TestNetworkStore
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-07 16:03:36 +02:00
Albin Kerouanton
1c79c893b1 libnet: de-flake TestEndpointStore
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-07 16:03:03 +02:00
Paweł Gronowski
da3b31fb2c Merge pull request #49736 from akerouanton/cache-endpoint-in-memory
libnet: Controller: cache networks & endpoints in-memory
2025-04-07 10:00:36 +00:00
Paweł Gronowski
4f7588f6ad Merge pull request #49724 from akerouanton/fix-duplicated-port-mappings
libnet: fix duplicated port mappings in overlay networks
2025-04-07 09:57:38 +00:00
Sebastiaan van Stijn
6422ff2804 deprecate pkg/atomicwriter, migrate to github.com/moby/sys/atomicwriter
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-04 23:07:00 +02:00
Albin Kerouanton
51d7f95c4b libnet: remove struct endpointCnt
endpointCnt is a refcounter used to track how many endpoints use a
network, and how many networks references a config-only network. It's
stored separately from the network.

This is only used to determine if a network can be removed.

This commit removes the `endpointCnt` struct and all its references. The
refcounter is replaced by two lookups in the newly introduced `networks`
and `endpoints` caches added to the `Controller`.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-04 11:21:17 +02:00
Albin Kerouanton
d377cd3810 libnet: Controller: cache networks in-memory
The `Controller`'s store is used by:

- `deleteFromStore`
- `getNetworks`
- `getNetworksFromStore`
- `updateToStore`
- … and other methods that can't store / delete / retrieve a Network

Calls to `updateToStore` and `deleteFromStore` have been replaced with
`upsertNetwork` and `deleteNetwork`.

Both `getNetworks` and `getNetworksFromStore` call `cacheNetwork` to
ensure networks loaded from the datastore are kept in-memory.

Finally, `sandboxRestore` was instantiating `Network` itself. These are
cached too.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-04 10:03:02 +02:00
Albin Kerouanton
cc8bd2016e libnet: Controller: cache endpoints in-memory
The `Controller`'s store is used by:

- `deleteFromStore`
- `getEndpointFromStore`
- `getEndpointsFromStore`
- `updateToStore`
- … and other methods that can't store / delete / retrieve an Endpoint

Calls to `updateToStore` and `deleteFromStore` have been replaced with
`upsertEndpoint` and `deleteEndpoint`.

Both `getEndpointFromStore` and `getEndpointsFromStore` call
`cacheEndpoint` to ensure endpoints loaded from the datastore are kept
in-memory.

Finally, `sandboxRestore` was instantiating `Endpoint` itself. These are
cached too.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-04 10:03:02 +02:00
Rob Murray
7d742ebf75 Add utils for manipulating nftables rules
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-03 16:47:30 +01:00
Albin Kerouanton
db275ddbc1 libnet: fix duplicated port mappings in overlay networks
Since commit f2a183a99, `getEndpointPortMapInfo` is called for all the
endpoints of a container to get its complete list of port mappings. This
is required as multiple endpoints might publish different ports (e.g.
IPv4-only and IPv6-only endpoints mapping an IPv4 and an IPv6 port).

`getEndpointPortMapInfo` calls `(*Endpoint).DriverInfo()` which has a
dodgy behavior: if the endpoint is part of a sandbox that also has an
endpoint for the `docker_gwbridge` network, then `(*Endpoint).DriverInfo()`
returns the DriverInfo of that `docker_gwbridge` endpoint in place of
the current Endpoint's DriverInfo.

On overlay networks, host port-mappings are made through the
`docker_gwbridge` network (which is automatically attached to all Swarm
tasks). This results in duplicated port mappings reported for all Swarm
containers.

Since `getEndpointPortMapInfo` is the only place where
`(*Endpoint).DriverInfo()` is called, just remove that dodgy behavior.

`(*Endpoint).DriverInfo()` has an OS-specific implementation. Unlike the
Linux implementation, on Windows, `DriverInfo()` returns the DriverInfo
of the gateway endpoint _in addition_ to the current Endpoint's
DriverInfo. So it shouldn't be affected by this bug -- don't touch it.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-02 12:30:50 +02:00
Rob Murray
7243860557 Include per-port rules in iptablesNetwork
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-31 17:04:17 +01:00
Rob Murray
0b5e1f904a Use netip.Addr instead of net.IP for legacy links
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-31 11:52:16 +01:00
Rob Murray
725e699741 Simplify iptables setup for legacy links
Include legacy link setup in IptablesNetwork, with the other
per-network rules.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-31 11:52:16 +01:00
Rob Murray
c5c9dc0376 Merge pull request #49668 from robmry/iptables_network_rules
Bridge: factor out creation of network-level iptables rules
2025-03-31 11:48:45 +01:00
Rob Murray
409707b633 bridge: factor out creation of network-level iptables rules
Create an iptablesNetwork containing all the info needed to
set up per-network iptables rules, give it methods to do
create the rules, and use it instead of per-rule-type calls
from driver.createNetwork().

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-28 16:57:16 +00:00
Rob Murray
0ab6f07c31 Fix TestPassthrough
Doesn't look like it would ever have worked, but:
- init the dbus connection to avoid a segv
- include the chain name when creating the rule
- remove the test rule if it's created

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-27 12:15:16 +00:00
Rob Murray
2d643b6835 Firewalld: skip unit tests that run in their own netns
Firewalld runs in the host netns. So, tests running in
their own netns can't check firewalld's iptables rules.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-27 12:14:20 +00:00
Paweł Gronowski
264fc2fac8 Merge pull request #49705 from robmry/continue_if_bridge_port_down
Start containers, even when connected to a disabled bridge port
2025-03-26 13:08:03 +00:00
Rob Murray
f5d84a45cc Start containers, even when connected to a disabled bridge port
Commit 9a6e96f ("Before sending ARPs/NAs, check the bridge is ready")
introduced a check that, if a container's veth is connected to a bridge,
the port is forwarding before sending unsolicited ARP/NA messages to
advertise the container's MAC/IP addresses.

It waited for up-to 200ms, but it seems that's not always enough.

If the port isn't forwarding, the ARP/NA messages will be silently
dropped. But, if it comes up within two seconds, one or both of the
resends will succeed.

So - keep the wait for 200ms but, if anything goes wrong with checking
the bridge port's state, or it's not forwarding after that time, just
log an info/warning level message and continue.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-26 11:46:38 +00:00
Paweł Gronowski
f14c23a90f libnetwork: Update to any from interface{}
Only files that have go build version enforcing tag

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-03-25 13:42:51 +01:00