ADR 0100: the guard lets the machine itself through; in use is a non-loopback listener; openings say from where; 09 in step with the flip
This commit is contained in:
@@ -117,13 +117,14 @@ intention, and each thing the mesh would otherwise take must say what it does in
|
|||||||
module's data has moved. Assigning prepares; taking migrates. Without the distinction the rule
|
module's data has moved. Assigning prepares; taking migrates. Without the distinction the rule
|
||||||
never fires: the host only ever sees what assigned modules declare.
|
never fires: the host only ever sees what assigned modules declare.
|
||||||
- **The firewall found on the machine stays in force.** The mesh loads no table on an adopted node
|
- **The firewall found on the machine stays in force.** The mesh loads no table on an adopted node
|
||||||
that drops by default or accepts. What it needs open it declares as openings the host converges
|
that drops by default or holds an accept. What it needs open it declares as openings the host converges
|
||||||
*through the found firewall*, on the incoming and the forwarded path, marked as the mesh's and
|
*through the found firewall*, on the incoming and the forwarded path, marked as the mesh's and
|
||||||
re-checked on every reconcile so a reload or reboot does not lose them. An accept in a table of
|
re-checked on every reconcile so a reload or reboot does not lose them. An accept in a table of
|
||||||
its own would not help: the found firewall's drop would still be final. What a table of its own
|
its own would not help: the found firewall's drop would still be final. What a table of its own
|
||||||
*can* do is refuse, and a refusal is final too — so the mesh guards the store and the broker's
|
*can* do is refuse, and a refusal is final too — so the mesh guards the store and the broker's
|
||||||
management port from outside the private network in a table that only refuses, which the found
|
management port from everyone but the private network and the machine itself, in a table that
|
||||||
firewall may not do and cannot undo. The bus, the registry and the hub's port stay open to
|
only refuses, ahead of the container runtime's redirect — which the found firewall does not do
|
||||||
|
and cannot undo. The bus, the registry and the hub's port stay open to
|
||||||
anywhere: a node enrols before it has a private-network address.
|
anywhere: a node enrols before it has a private-network address.
|
||||||
- **The foundation's ports are the node's to give** — set at genesis, checked free, and kept as
|
- **The foundation's ports are the node's to give** — set at genesis, checked free, and kept as
|
||||||
that node's settings, read everywhere they are used, so adopting the foundation as modules does
|
that node's settings, read everywhere they are used, so adopting the foundation as modules does
|
||||||
|
|||||||
@@ -77,9 +77,9 @@ have been taken on it. A node stays adopted until the operator converges it. An
|
|||||||
said to be adopted wherever the mesh reports a node's state.
|
said to be adopted wherever the mesh reports a node's state.
|
||||||
|
|
||||||
**A converged genesis refuses a machine in use.** A machine is in use when a container is running
|
**A converged genesis refuses a machine in use.** A machine is in use when a container is running
|
||||||
on it or a port is listening that is neither ssh nor one of the operating system's own services.
|
on it, or a port is listening on an address other than loopback that is not ssh's. Raised without
|
||||||
Raised without saying adopted on such a machine, genesis refuses and names what it found — a
|
saying adopted on such a machine, genesis refuses and names every container and listener it
|
||||||
forgotten flag must not close a working machine.
|
counted — a forgotten flag must not close a working machine.
|
||||||
|
|
||||||
**Before a node is adopted, its predecessor's control is stopped by the operator** — the daemons
|
**Before a node is adopted, its predecessor's control is stopped by the operator** — the daemons
|
||||||
that write its configuration. Its services keep running on what they have.
|
that write its configuration. Its services keep running on what they have.
|
||||||
@@ -99,11 +99,13 @@ rewritten, a container stopped or replaced — is reported as changed by somethi
|
|||||||
or restarted: that is how a predecessor still writing is caught.
|
or restarted: that is how a predecessor still writing is caught.
|
||||||
|
|
||||||
**The firewall found on the machine stays in force.** The mesh loads no table on an adopted node
|
**The firewall found on the machine stays in force.** The mesh loads no table on an adopted node
|
||||||
that drops by default or that accepts — neither genesis's base ruleset nor the filter module's
|
that drops by default or holds an accept — neither genesis's base ruleset nor the filter module's
|
||||||
derived one. What the mesh needs reachable is declared as **openings**: a resource that says a port
|
derived one. What the mesh needs reachable is declared as **openings**: a resource that says a port
|
||||||
is reachable, from where, on the incoming path or the forwarded path — a published container port is
|
is reachable, from where, on the incoming path or the forwarded path — a published container port is
|
||||||
forwarded. The controller derives them from the same inputs as the filter: the `listens` of the
|
forwarded. The controller derives them from the same inputs as the filter, each from where the
|
||||||
modules assigned there, the private network's hub port, and the foundation's ports. The host
|
filter would admit it: the `listens` of the modules assigned there, the private network's hub port
|
||||||
|
and the bus and the registry from anywhere, the store's port and the broker's management port from
|
||||||
|
the private network. The host
|
||||||
converges an opening through the found firewall in that firewall's own terms, marks it as the
|
converges an opening through the found firewall in that firewall's own terms, marks it as the
|
||||||
mesh's, and removes only what it marked; it re-checks each opening on every reconcile, so a reload
|
mesh's, and removes only what it marked; it re-checks each opening on every reconcile, so a reload
|
||||||
or a reboot of the found firewall does not lose it for longer than one reconcile. An opening is a
|
or a reboot of the found firewall does not lose it for longer than one reconcile. An opening is a
|
||||||
@@ -111,12 +113,14 @@ state, not a command, which is what lets it travel over the link. The host repor
|
|||||||
it found. A machine with no firewall needs no openings; a machine with a kind no host speaks is
|
it found. A machine with no firewall needs no openings; a machine with a kind no host speaks is
|
||||||
refused adoption.
|
refused adoption.
|
||||||
|
|
||||||
**The mesh guards its own ports itself, in a table of its own that only refuses.** It accepts by
|
**The mesh guards its own ports itself, in a table of its own that only refuses.** It passes
|
||||||
default and holds nothing but refusals, so it cannot close anything the machine serves — a drop in
|
everything by default and holds nothing but refusals, and the two ports it refuses are the
|
||||||
any chain is final and an accept in it would change nothing — and it is the mesh's, so the found
|
foundation's own, checked free at genesis, so it cannot close anything the machine serves; it is
|
||||||
firewall reloading does not touch it. It refuses the store's port and the broker's management port
|
the mesh's, so the found firewall reloading does not touch it. It refuses the store's port and the
|
||||||
from anywhere but the private network, matched on the port the packet was sent to, before the
|
broker's management port except from the private network and from the machine itself — its
|
||||||
container runtime redirects it. The bus and the registry stay reachable from anywhere, as a node
|
loopback and the container runtime's own networks — at the prerouting hook, ahead of the runtime's
|
||||||
|
destination translation, so it matches the port the packet was sent to, for both address
|
||||||
|
families. The bus and the registry stay reachable from anywhere, as a node
|
||||||
enrols over the bus and pulls from the registry before it has a private-network address
|
enrols over the bus and pulls from the registry before it has a private-network address
|
||||||
([ADR 0088](0088-the-foundation-filters-before-anything-listens.md)); so does the private network's
|
([ADR 0088](0088-the-foundation-filters-before-anything-listens.md)); so does the private network's
|
||||||
hub port. The store is unreachable from outside whatever the found firewall does, and on a machine
|
hub port. The store is unreachable from outside whatever the found firewall does, and on a machine
|
||||||
@@ -134,11 +138,12 @@ checks that too.
|
|||||||
found container: each service is taken on its own, when its data has moved, never by the flip. The
|
found container: each service is taken on its own, when its data has moved, never by the flip. The
|
||||||
preview lists what is reachable on the machine now — every listening socket and every published
|
preview lists what is reachable on the machine now — every listening socket and every published
|
||||||
container port — and for each whether an assigned module declares it or it will close, and every
|
container port — and for each whether an assigned module declares it or it will close, and every
|
||||||
module the flip will take, with what each will replace. The flip then takes those modules, loads the
|
module the flip will take, with the held files each will replace. The flip then takes those modules, loads the
|
||||||
mesh's derived filter in place of its refusal-only table, and retires the found firewall by
|
mesh's derived filter in place of its refusal-only table, and retires the found firewall by
|
||||||
disabling it, never by flushing: the container runtime's rules and the found firewall's own
|
disabling it, never by flushing: the container runtime's rules and the found firewall's own
|
||||||
configuration stay on disk. Returning a converged node to adopted unloads the derived filter,
|
configuration stay on disk. Returning a converged node to adopted unloads the derived filter,
|
||||||
restores the refusal-only table and enables the found firewall again; what was taken stays taken. A
|
restores the refusal-only table, enables the found firewall again and converges the openings
|
||||||
|
through it once more; what was taken stays taken. A
|
||||||
node converges when its migration is done; the mesh is migrated when every node has converged.
|
node converges when its migration is done; the mesh is migrated when every node has converged.
|
||||||
|
|
||||||
**The order is the operator's:** the control-node first, adopted, its modules assigned and taken
|
**The order is the operator's:** the control-node first, adopted, its modules assigned and taken
|
||||||
@@ -179,15 +184,15 @@ port and denying the rest, a service container listening on that port under a na
|
|||||||
module also uses, a file at a path that module declares, a stand-in for the predecessor's control
|
module also uses, a file at a path that module declares, a stand-in for the predecessor's control
|
||||||
that would rewrite that file, and a container holding the registry's port. Then:
|
that would rewrite that file, and a container holding the registry's port. Then:
|
||||||
|
|
||||||
- **Genesis converged** on it refuses and names the running container and the listener.
|
- **Genesis converged** on it refuses and names every container and listener it counted.
|
||||||
- **Genesis adopted, with the registry's port held**, refuses and names the holder; with another
|
- **Genesis adopted, with the registry's port held**, refuses and names the holder; with another
|
||||||
port given, the foundation comes up — and adopting the foundation as modules leaves it on that
|
port given, the foundation comes up — and adopting the foundation as modules leaves it on that
|
||||||
port.
|
port.
|
||||||
- **Nothing that serves changed**: the service is reachable from a second machine, the file is byte
|
- **Nothing that serves changed**: the service is reachable from a second machine, the file is byte
|
||||||
for byte what it was, and the found firewall's rules differ only by rules marked as the mesh's.
|
for byte what it was, and the found firewall's rules differ only by rules marked as the mesh's.
|
||||||
- **The store is unreachable from outside** — probed from a machine off the private network, and
|
- **The store is unreachable from outside** — probed from a machine off the private network, and
|
||||||
again after the found firewall is reloaded — and reachable over it; the bus is reachable from a
|
again after the found firewall is reloaded — and reachable over it and from a container on the
|
||||||
machine that has not yet enrolled.
|
node itself; the bus is reachable from a machine that has not yet enrolled.
|
||||||
- **The mesh works through the found firewall, and keeps working after it is reloaded and after the
|
- **The mesh works through the found firewall, and keeps working after it is reloaded and after the
|
||||||
machine reboots**: the second machine enrols, and the openings are there again.
|
machine reboots**: the second machine enrols, and the openings are there again.
|
||||||
- **A predecessor still writing is caught**: with the stand-in left running, the held file's change
|
- **A predecessor still writing is caught**: with the stand-in left running, the held file's change
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ machine already serving under a predecessor has a firewall of its own, and a sec
|
|||||||
table would close everything it serves. There the base ruleset is not loaded and the filter module
|
table would close everything it serves. There the base ruleset is not loaded and the filter module
|
||||||
is not assigned until the node converges; the foundation's ports are opened through the found
|
is not assigned until the node converges; the foundation's ports are opened through the found
|
||||||
firewall, and a table of the mesh's that only refuses keeps the store's port and the broker's
|
firewall, and a table of the mesh's that only refuses keeps the store's port and the broker's
|
||||||
management port from anyone off the private network — the same promise, the store's port never
|
management port from anyone but the private network and the machine itself — the same promise, the store's port never
|
||||||
answering from outside, kept by other means. The bus and the registry stay reachable from anywhere,
|
answering from outside, kept by other means. The bus and the registry stay reachable from anywhere,
|
||||||
as they are here, because a node enrols and pulls before it has a private-network address. The
|
as they are here, because a node enrols and pulls before it has a private-network address. The
|
||||||
foundation's ports themselves are the node's, given at genesis and kept as its settings. **Checked**
|
foundation's ports themselves are the node's, given at genesis and kept as its settings. **Checked**
|
||||||
|
|||||||
@@ -537,21 +537,25 @@ is why the check reads packets.*
|
|||||||
### On an adopted node
|
### On an adopted node
|
||||||
|
|
||||||
*2026-09-22, [ADR 0100](../../02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md).* **The firewall found on the machine stays in force**, and the mesh
|
*2026-09-22, [ADR 0100](../../02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md).* **The firewall found on the machine stays in force**, and the mesh
|
||||||
loads no table there that drops by default or that accepts — neither genesis's base ruleset nor
|
loads no table there that drops by default or holds an accept — neither genesis's base ruleset nor
|
||||||
the derived one. Every base chain at a hook runs and a drop in any is final, whatever the other
|
the derived one. Every base chain at a hook runs and a drop in any is final, whatever the other
|
||||||
firewall is written in, so a second, stricter table would close every port the machine serves, and
|
firewall is written in, so a second, stricter table would close every port the machine serves, and
|
||||||
an accept in one would open nothing the found firewall drops. What the mesh needs reachable it
|
an accept in one would open nothing the found firewall drops. What the mesh needs reachable it
|
||||||
declares as **openings**: a port, from where, on the incoming path or the forwarded path — a
|
declares as **openings**: a port, from where, on the incoming path or the forwarded path — a
|
||||||
published container port is forwarded, and a firewall that filters only incoming traffic never
|
published container port is forwarded, and a firewall that filters only incoming traffic never
|
||||||
sees it. The controller derives them from what the filter would be derived from: the assigned
|
sees it. The controller derives them from what the filter would be derived from, each from where
|
||||||
modules' `listens`, the hub's port, the foundation's ports. The host converges each opening through
|
the filter would admit it: the assigned modules' `listens`, the hub's port, the bus and the registry
|
||||||
|
from anywhere; the store's port and the broker's management port from the private network. The host converges each opening through
|
||||||
the found firewall in that firewall's own terms, marks it as the mesh's, removes only what it
|
the found firewall in that firewall's own terms, marks it as the mesh's, removes only what it
|
||||||
marked, and re-checks every opening on each reconcile so a reload or a reboot does not lose it for
|
marked, and re-checks every opening on each reconcile so a reload or a reboot does not lose it for
|
||||||
longer than one reconcile. An opening is state, not a command, so it travels over the link like any
|
longer than one reconcile. An opening is state, not a command, so it travels over the link like any
|
||||||
other resource. **The mesh guards its own ports in a table of its own that only refuses** —
|
other resource. **The mesh guards its own ports in a table of its own that only refuses** —
|
||||||
accepting by default and holding nothing but refusals, so it cannot close what the machine serves,
|
passing everything by default and holding nothing but refusals of the foundation's own two ports,
|
||||||
and the found firewall's reload does not touch it. It refuses the store's port and the broker's
|
checked free at genesis, so it cannot close what the machine serves, and the found firewall's
|
||||||
management port from outside the private network, matched on the port the packet was sent to; the
|
reload does not touch it. It refuses the store's port and the broker's management port except from
|
||||||
|
the private network and the machine itself — loopback and the container runtime's networks — at
|
||||||
|
the prerouting hook, before the container runtime redirects the packet, so it matches the port the
|
||||||
|
packet was sent to, for both address families; the
|
||||||
bus, the registry and the hub's port stay reachable from anywhere, as a node enrols and pulls
|
bus, the registry and the hub's port stay reachable from anywhere, as a node enrols and pulls
|
||||||
before it has a private-network address. One kind of found firewall is spoken; a machine with none
|
before it has a private-network address. One kind of found firewall is spoken; a machine with none
|
||||||
needs no openings, and a machine with another kind is refused adoption. Converging the node refuses
|
needs no openings, and a machine with another kind is refused adoption. Converging the node refuses
|
||||||
@@ -560,7 +564,7 @@ sockets and published ports — what will close and which modules it will take,
|
|||||||
derived filter in place of the refusal-only table and disables the found firewall without flushing
|
derived filter in place of the refusal-only table and disables the found firewall without flushing
|
||||||
it. *How it is checked:* the adoption bed asserts the found firewall's rules differ only by the
|
it. *How it is checked:* the adoption bed asserts the found firewall's rules differ only by the
|
||||||
mesh's marked rules, that the store is unreachable from off the private network before and after
|
mesh's marked rules, that the store is unreachable from off the private network before and after
|
||||||
the found firewall reloads, that a machine not yet enrolled reaches the bus, that a second machine
|
the found firewall reloads and reachable from a container on the node, that a machine not yet enrolled reaches the bus, that a second machine
|
||||||
enrols through the openings before and after a reload and a reboot, and that after the flip the
|
enrols through the openings before and after a reload and a reboot, and that after the flip the
|
||||||
declared port is open and the undeclared one closed.
|
declared port is open and the undeclared one closed.
|
||||||
|
|
||||||
|
|||||||
@@ -297,11 +297,13 @@ the others — and the controller records it and says so in every declaration, w
|
|||||||
**taken** on that node. On an adopted node what is found is held until its module is taken
|
**taken** on that node. On an adopted node what is found is held until its module is taken
|
||||||
([05-the-node-host](05-the-node-host.md)): assigning a module prepares it, taking it is its
|
([05-the-node-host](05-the-node-host.md)): assigning a module prepares it, taking it is its
|
||||||
cutover. The firewall found there stays in force and the mesh opens what it needs through it
|
cutover. The firewall found there stays in force and the mesh opens what it needs through it
|
||||||
([08-connectivity](08-connectivity.md)). **Converging is one act per node, previewed**: it lists
|
([08-connectivity](08-connectivity.md)). **Converging is one act per node, previewed**: it refuses
|
||||||
what is reachable on the machine now — listening sockets and published ports — and whether an
|
while an assigned module still holds a found container; otherwise it lists what is reachable on the
|
||||||
assigned module declares each or it will close, then takes every module not yet taken, loads the
|
machine now — listening sockets and published ports — whether an assigned module declares each or
|
||||||
mesh's own filter and disables the found one without flushing it. Returning a converged node to
|
it will close, and which modules it will take, then takes them, loads the mesh's own filter in place
|
||||||
adopted enables the found firewall again. *How it is checked:* a lab bed prepares a machine the way
|
of its refusal-only table and disables the found firewall without flushing it. Returning a
|
||||||
|
converged node to adopted unloads the derived filter, restores the refusal-only table, enables the
|
||||||
|
found firewall again and converges the openings through it; what was taken stays taken. *How it is checked:* a lab bed prepares a machine the way
|
||||||
a predecessor leaves one and asserts nothing that serves changes until a module is taken or the
|
a predecessor leaves one and asserts nothing that serves changes until a module is taken or the
|
||||||
node is converged, and that the flip closes exactly what the preview said.
|
node is converged, and that the flip closes exactly what the preview said.
|
||||||
|
|
||||||
|
|||||||
@@ -113,8 +113,8 @@ checks the private network's range does not overlap a tunnel the predecessor run
|
|||||||
**does not load the base ruleset**: the machine's own firewall already filters; the mesh opens its
|
**does not load the base ruleset**: the machine's own firewall already filters; the mesh opens its
|
||||||
foundation's ports through it and keeps the store from outside with a table of its own that only
|
foundation's ports through it and keeps the store from outside with a table of its own that only
|
||||||
refuses ([08-connectivity](08-connectivity.md)). **A converged genesis refuses a machine in use** —
|
refuses ([08-connectivity](08-connectivity.md)). **A converged genesis refuses a machine in use** —
|
||||||
a container running, or a port listening that is neither ssh nor the operating system's own — so a
|
a container running, or a port listening on an address other than loopback that is not ssh's —
|
||||||
forgotten flag cannot close a working machine. *How it is checked:* the adoption bed raises genesis converged on a machine in use and
|
and names every one it counted, so a forgotten flag cannot close a working machine. *How it is checked:* the adoption bed raises genesis converged on a machine in use and
|
||||||
asserts the refusal, then adopted with the registry's port held and asserts the refusal names its
|
asserts the refusal, then adopted with the registry's port held and asserts the refusal names its
|
||||||
holder, then with another port given asserts the foundation comes up, stays on that port once
|
holder, then with another port given asserts the foundation comes up, stays on that port once
|
||||||
adopted as modules, and the machine's service is still reachable.
|
adopted as modules, and the machine's service is still reachable.
|
||||||
|
|||||||
Reference in New Issue
Block a user