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>
45 lines
1.3 KiB
Nix
45 lines
1.3 KiB
Nix
{ config, lib, ... }:
|
|
let
|
|
cfg = config.router;
|
|
dhcpLans = lib.filter (l: l.dhcp.enable) (lib.attrValues cfg.lans);
|
|
ipv4 = (import ./lib.nix { inherit lib; }).ipv4;
|
|
in
|
|
{
|
|
config = lib.mkIf (cfg.enable && dhcpLans != [ ]) {
|
|
services.kea.dhcp4 = {
|
|
enable = true;
|
|
settings = {
|
|
interfaces-config = {
|
|
interfaces = map (l: l.device) dhcpLans;
|
|
# Interfaces are configured asynchronously by networkd.
|
|
re-detect = true;
|
|
};
|
|
lease-database = {
|
|
type = "memfile";
|
|
persist = true;
|
|
name = "/var/lib/kea/dhcp4.leases";
|
|
};
|
|
valid-lifetime = 3600;
|
|
# The ID keys persistent leases, so derive it from the network address:
|
|
# stable when LANs are added or removed (an index would shift).
|
|
subnet4 = map (l: {
|
|
id = ipv4.networkOf (ipv4.parse l.ipv4.address) l.ipv4.prefixLength;
|
|
inherit (l.ipv4) subnet;
|
|
interface = l.device;
|
|
pools = [ { pool = "${l.dhcp.pool.start} - ${l.dhcp.pool.end}"; } ];
|
|
option-data = [
|
|
{
|
|
name = "routers";
|
|
data = l.ipv4.address;
|
|
}
|
|
{
|
|
name = "domain-name-servers";
|
|
data = l.ipv4.address;
|
|
}
|
|
];
|
|
}) dhcpLans;
|
|
};
|
|
};
|
|
};
|
|
}
|