diff --git a/03-DESIGN/01-to-be/02-scenario-declaration.md b/03-DESIGN/01-to-be/02-scenario-declaration.md index a818906..62e59b2 100644 --- a/03-DESIGN/01-to-be/02-scenario-declaration.md +++ b/03-DESIGN/01-to-be/02-scenario-declaration.md @@ -308,6 +308,86 @@ not first. - **Steps.** A scenario is a desired state. Anything expressed as an ordered list of actions belongs in the lifecycle, not the declaration. +## What the model deliberately does not contain + +A real network is full of equipment: a modem, a router, switches, access points, controllers. +Almost none of it appears here, and the omission is deliberate rather than an oversight. + +**The test is whether a device changes what an IP packet can do.** If two machines can exchange +packets, at the same addresses, with the same reachability and the same MTU, whether or not the +device exists — then the device is invisible to the mesh, and modelling it would add a fixture +with no fault to catch. + +| Equipment | Modelled? | Why | +|---|---|---| +| **Switch** | no | Moves frames within a segment. Two machines on a switch are two machines on a segment. | +| **Access point** | no | Bridges wireless clients onto a segment. A machine on wifi and a machine on cable are the same machine to IP. | +| **Network controller** | no | Configures equipment. Its effects appear as segments and policy; it has no packets of its own. | +| **Cabling, PoE, uplink speed** | no | Change performance and availability, not reachability. | +| **Router / security gateway** | **yes — it *is* the gateway** | Translation, forwarding and inter-segment policy all live here. | +| **ISP modem** | **only in router mode** | In bridge mode it is a media converter and invisible. Doing its own NAT, it is a second gateway — and that is double NAT. | +| **VLANs** | **yes — they are segments** | Machines on separate VLANs cannot reach each other except through the router, which is the definition of a separate segment. | +| **Inter-VLAN firewall rules** | **yes** — see below | A rule stopping one segment reaching another is a reachability fact, and the mesh will hit it. | + +The two entries worth dwelling on are the ones where a common household setup produces +something the mesh has to survive. + +**A modem in router mode gives you double NAT.** Your gateway holds a private address from the +modem, which holds the public one. Forwarding then requires a rule on *both*, and one of them +may not be configurable. This is expressible as nested segments — `to:` chains — but publishing +through two gateways is not, and remains open. + +**Segmented networks are the common case, not the exotic one.** A router with separate networks +for trusted machines, guests and devices is ordinary, and the rules between them are ordinary +too. A mesh node on one segment and a mesh node on another are, as far as reachability goes, on +different networks that happen to share a gateway. + +## Segments may share a gateway + +Several segments can name the same parent and the same external address. That is one router +with several networks behind it, which is what a VLAN-capable gateway is: + +```yaml +segments: + trusted: + kind: private + cidr: [192.168.1.0/24] + gateway: { to: internet, address: 203.0.113.50, nat: [v4], forwardable: true } + devices: + kind: private + cidr: [192.168.30.0/24] + gateway: { to: internet, address: 203.0.113.50, nat: [v4], forwardable: true } +``` + +Identical gateway declarations mean **one gateway machine**, not two. The lab materialises a +single router serving both, because that is what the topology being reproduced is — and two +routers sharing one address would not work anyway. + +## Policy between segments + +Sharing a gateway does not mean segments can reach each other. What they may do is stated +separately, because it is a fact about a pair rather than a property of either: + +```yaml +policy: + - { from: devices, to: trusted, allow: false } # devices may not initiate to trusted + - { from: trusted, to: devices, allow: true } # the reverse is fine +``` + +Default is `true` between segments behind the same gateway, matching a router with no rules +configured. Asymmetry is the normal case and the reason this cannot be a single flag: the +useful configuration is almost always one-directional. + +This is **not** the same as `machines[].inbound`, and conflating them loses a real distinction: + +| | Enforced by | Blocks | +|---|---|---| +| `policy` | the gateway, between segments | everything crossing, regardless of what the destination thinks | +| `inbound` | the machine itself | unsolicited traffic that already reached it | + +A mesh node behind a `policy` deny cannot be reached even by a peer that knows exactly where it +is — and that is a real topology, not a contrived one. + ## Is this general? — the axes a setup can vary along The question that matters is not *does this cover our mesh*, but **can it express any mesh**. @@ -320,7 +400,9 @@ how the mesh behaves**. Bandwidth does not change correctness; MTU does. | **Reachability** | attached · forwardable gateway · unforwardable gateway · isolated | yes | the core of the model, and **per family** | | **Address family** | IPv4 · IPv6 · dual-stack · neither | yes | `cidr:` and `address:` take both; `nat:` names which families are translated | | **Interfaces per machine** | one · several | yes | `at:` takes a list | -| **Reachability policy** | symmetric · asymmetric | yes | `inbound:` — a routable machine that refuses everything | +| **Reachability policy, host** | symmetric · asymmetric | yes | `inbound:` — a routable machine that refuses everything | +| **Reachability policy, network** | open · segmented · asymmetric between segments | yes | `policy:` — inter-segment rules, as a segmented router enforces | +| **Segments per gateway** | one · several behind one router | yes | identical gateway declarations mean one gateway machine | | **Gateway state** | permanent · expiring mappings | yes | `mapping_ttl:` | | **Path MTU** | standard · reduced | yes | `segments[].mtu` | | **Overlapping ranges** | distinct · two sites both on `192.168.1.0/24` | yes | segments may carry the same range | @@ -357,11 +439,17 @@ revisited — and it would be revisited by a real failure, which is the right tr ### The honest summary -The model now covers **where a machine sits** and **what the path between machines is like**, -across both address families, which together are what the mesh's reachability logic turns on. +The model now covers **where a machine sits**, **what the path between machines is like**, and +**what is permitted between them** — across both address families. Together those are what the +mesh's reachability logic turns on. -What it does not model is *change over time* beyond moving a machine, and *degradation* short of -failure. Both are absences chosen rather than overlooked. +It contains almost no equipment, by the test above: a device that does not change what an IP +packet can do has no fault for a scenario to catch. What it does contain is every device that +does — which turns out to be the router, and a modem only when the modem is also a router. + +What it still does not model is *change over time* beyond moving a machine, *degradation* short +of failure, and *publishing through two gateways at once*. The first two are chosen; the third +is the one real absence, and it is exactly the double-NAT case. ## Open