Commit Graph
4 Commits
Author SHA1 Message Date
nilsandClaude Sonnet 5.5 c395a43a78 Add a static ULA per LAN, announced via SLAAC and RDNSS
lans.<n>.ipv6.address (a ULA /64) is assigned to the LAN, announced
with an explicit prefix (networkd only announces the delegated prefix
when prefix delegation is on) and advertised as RDNSS; Unbound listens
and answers on it. Checked at build time: valid IPv6 CIDR, /64, fc00::/7.

Covered by the onestick VM test (client SLAAC address, ping and DNS over
the ULA, RA captured on the wire), assertion cases and a unit test for
the /64 prefix helper.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-28 15:48:47 +01:00
nilsandClaude Sonnet 5.5 6015ee2e6d Add VLANs, firewall zones and inter-zone rules
LANs can sit on an 802.1Q VLAN (`vlan` on a trunk `interface`); networkd
creates the device and brings the trunk up. LANs belong to a named `zone`
(default: their own name). Traffic inside a zone is forwarded freely, traffic
between zones is denied unless a `router.firewall.rules` entry allows it
(protocol, ports, optional destination inside the target zone).

Internet access is now opt-in per LAN (`internet`, default false), replacing
the previous allow-out default. Assertions reject unknown zones, bad
destinations, duplicate devices, over-long device names and a WAN trunk.

Kea subnet IDs now come from the network address so adding LANs does not
renumber them and orphan persistent leases.

Tests: a five-VM `vlans` check (untagged + two VLANs, shared zone, one-way
rules, per-host destination restriction), new assertion cases, parseNet unit
tests, and shared test tooling in tests/common.nix.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 17:54:52 +01:00
nilsandClaude Sonnet 5.5 6038367252 Add IPv6 prefix delegation and PPPoE uplink
IPv6: router.wan.ipv6.enable mirrors the existing uplink config (DHCPv6 with
WithoutRA=solicit, delegated prefix). The ISP delegates a single /64, so
exactly one LAN may claim it via router.lans.<name>.ipv6.pd (asserted); other
LANs stay IPv4-only. SLAAC only, no NAT66.

PPPoE: router.wan.ipv4.type = "pppoe" runs pppd on an optional VLAN of the
uplink, with the password read from a file at service start (never the Nix
store). NAT, forwarding and MSS clamping (MTU 1492) use the derived PPP
device; native IPv6 stays on the untagged link.

Tests: basic.nix is parameterised by uplink type; the pppoe variant uses a
fake ISP with pppoe-server (VLAN 7, CHAP). Both variants cover IPv6 PD, SLAAC,
routing without NAT and WAN-deny. Assertion tests gain PD/PPPoE cases and a
full-system evaluation step.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 16:29:52 +01:00
nilsandClaude Sonnet 5.5 96e5b7b859 Derive LAN subnets and validate addressing at build time
Add an IPv4 helper lib (parse, netmask, cidr, overlap) and derive
router.lans.<name>.ipv4.subnet from address and prefixLength instead of
requiring it twice. New assertions reject invalid addresses, DHCP pools that
are reversed, outside the subnet or contain the router address, and
overlapping LANs.

Add `lib` unit tests and an `assertions` check that evaluates broken configs
and compares the exact error messages.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 15:00:24 +01:00