Files
hq/04-ISSUES/137-converging-a-machine-cut-off-its-own-guests/00-report.md
T

3.8 KiB

status, opened, located-in, fixed-by, amended-design
status opened located-in fixed-by amended-design
resolved 2026-09-28
mesh-controller internal/catalogue
mesh-controller — a machine says which networks it routes and the derived filter forwards them, their guests keeping address and name service ([ADR 0137](../../02-DECISIONS/0137-a-machine-says-which-networks-it-routes.md)).

137 — Converging a machine cut off its own guests, and nothing said so

What was observed

A workstation was flipped from adopted to converged, so the mesh's derived filter replaced what was there. The flip reported success, the machine reported that it had applied its declaration, and every surface of the mesh read green.

A container on one of that machine's networks could no longer reach anything:

192.168.64.2/20
OUTBOUND BLOCKED

Five of the machine's container networks were affected, and every network its test beds create. The reason is in the filter's forward chain, which denies by default and then allows two ranges:

ip saddr 172.16.0.0/12 accept   # the container runtime's bridge networks
ip saddr 192.168.128.0/17 accept # the networks its compose files are given

Those two are constants in the controller. The machine's guests were allocated from neither: its compose networks from other parts of 192.168/16, and each test bed a fresh 10.x/24. So the rules were correct for a machine whose runtime was left at its defaults, and a guess on this one.

Two further things were closed by the same flip, and for the same reason nobody saw them: a guest asks its host for an address over DHCP and for names over DNS, both of which arrive at the input chain, where no module had declared them.

Why it matters beyond this instance

The preview could not have warned. It lists what the machine reported as listening, and says so honestly: it ends with a line that traffic the machine routes is "not previewed". What it did not say is that routing was about to be denied by default, or which ranges would survive. An operator reading a 350-line preview approves what it shows.

It is the second time today that a constant stood in for something the mesh cannot know. The intrusion-prevention module named a firewall front-end two machines do not have (issue 136), and the filter names the address ranges one runtime happens to use. Both were true where they were written and silently false elsewhere.

And the code already knew. The comment above those two lines says a machine configured otherwise "needs this to say so — which is a thing the mesh cannot derive and a reason this list is named here rather than computed". The gap was documented at the point where it was introduced, and the way to say it was never built. A comment naming a missing mechanism is a rule that is not enforced.

What was done

A machine says which networks it routes; the filter forwards them and admits their guests' address and name service. Added to the runtime's defaults rather than replacing them, so a machine that names one range keeps the others. Node-level, because the machine routes them and the module that loads the filter may be replaced. The converge preview now says what a machine routes, and what it will keep forwarding if it says nothing.

What is still true

The flip is still the moment a machine's unmanaged services close. That is what converging means and the preview names each one. This issue is not about the ports that were meant to close; it is about the ones nothing could name.

Egress is still not previewed per network. The preview says which ranges will be forwarded, not which of the machine's guests sit inside them. Deriving that would need the machine to report its bridges, and a bed's bridge does not exist until the bed runs.