The full topology now raises: four machines, three routers, a transit router, six segments, in 35 seconds. Everything the declaration model can express except `place`, which is refused because the node host it would place does not exist yet. Transit was a real gap, not a bug. The design says public networks are unrelated and routed to each other, never bridged — and I built the segments and never built the thing that routes between them, so three public networks were islands and nothing crossed. A transit router now holds an interface on every public segment, forwarding and no translation: the closest thing the lab has to the internet, deliberately dumb. Proven rather than asserted, by ping TTL across the raised topology: within one segment ttl=64 no hops across two unrelated public networks ttl=62 gateway + transit multicast between public networks 0 replies A flat internet would have shown ttl=64 and answered multicast — which would let a node discover a peer it could never reach in production, and report success. That is the fault the as-is layer records the mesh already hitting with multicast name resolution. inbound: deny is implemented as a host firewall on the machine, read back after applying. A declared refusal that silently did not load leaves the machine wide open, which looks exactly like a machine that is working. Established and related traffic is accepted, so a defended machine can still dial out rather than being a disconnected one. Verified by running, all of it: home -> devices (policy allow) reachable devices -> home (policy deny) blocked behind unforwardable NAT -> out reachable in -> behind unforwardable NAT unreachable inbound: deny, dialling out reachable reaching a machine that denies inbound refused The two routers differ exactly as declared: the forwardable one carries the policy rule and no inbound drop, the unforwardable one carries `ct state new drop` and no DNAT.
82 lines
2.0 KiB
YAML
82 lines
2.0 KiB
YAML
# One machine with a routable address, one publicly named but behind a household
|
|
# connection, one stationary machine on that network, one that roams.
|
|
#
|
|
# Three unrelated public networks, routed to each other and never bridged — putting them
|
|
# in one prefix would make ARP adjacency, non-decrementing TTL and crossing multicast
|
|
# true in the lab and false in production.
|
|
scenario: the-ordinary-shape
|
|
|
|
segments:
|
|
hosting:
|
|
kind: public
|
|
cidr: [192.0.2.0/24, "2001:db8:a::/48"]
|
|
|
|
isp-home:
|
|
kind: public
|
|
cidr: [198.51.100.0/24, "2001:db8:b::/48"]
|
|
|
|
isp-mobile:
|
|
kind: public
|
|
cidr: [203.0.113.0/24, "2001:db8:c::/48"]
|
|
|
|
home:
|
|
kind: private
|
|
cidr: [192.168.1.0/24, "2001:db8:b:1::/64"]
|
|
mtu: 1492
|
|
gateway:
|
|
to: isp-home
|
|
address: [198.51.100.7, "2001:db8:b::7"]
|
|
nat: [v4]
|
|
forwardable: true
|
|
mapping_ttl: 120s
|
|
|
|
devices:
|
|
kind: private
|
|
cidr: [192.168.30.0/24]
|
|
gateway:
|
|
to: isp-home
|
|
address: [198.51.100.7]
|
|
nat: [v4]
|
|
forwardable: true
|
|
mapping_ttl: 120s
|
|
|
|
cafe:
|
|
kind: private
|
|
cidr: [10.50.0.0/16]
|
|
mtu: 1400
|
|
gateway:
|
|
to: isp-mobile
|
|
address: [203.0.113.129]
|
|
nat: [v4]
|
|
forwardable: false
|
|
mapping_ttl: 30s
|
|
|
|
policy:
|
|
- { from: devices, to: home, allow: false }
|
|
- { from: home, to: devices, allow: true }
|
|
|
|
machines:
|
|
anchor:
|
|
at: { segment: hosting, address: [192.0.2.10, "2001:db8:a::10"] }
|
|
inbound: allow
|
|
|
|
home-server:
|
|
at: { segment: home, address: [192.168.1.135, "2001:db8:b:1::135"] }
|
|
published:
|
|
- { port: 443, on: home }
|
|
inbound: allow
|
|
|
|
workstation:
|
|
at: { segment: home, address: [192.168.1.250, "2001:db8:b:1::250"] }
|
|
inbound: deny
|
|
|
|
laptop:
|
|
at: { segment: home, address: [192.168.1.98, "2001:db8:b:1::98"] }
|
|
inbound: deny
|
|
|
|
# No `place:` yet. The node host it would place does not exist — this lab is being built to
|
|
# develop it, and the lab refuses declarations it cannot materialise rather than raising a
|
|
# mesh that silently lacks them.
|
|
|
|
snapshot: raised
|