Files
cnx-network-clan/modules/router/dns-dhcp.nix
T
Berwn 19e1acda51 Renumber gw-cnx-1 to the fleet addressing scheme (OPNsense replacement)
The newedge.house site adopts the 10.1.<vlanId>.0/24 convention: mgmt 10
(the old untagged LAN), lan 20, iot 40, voip 50, dmz 60, unit1-5 110-150.
PPPoE is untagged at this site. Static leases move to a new per-VLAN
dhcp.reservations option rendered into Kea host reservations.
2026-07-31 11:39:54 +07:00

85 lines
2.3 KiB
Nix

# LAN DHCP (Kea) and DNS (Blocky). Fully declarative: one Kea subnet per VLAN
# with dhcp.enable, Blocky as the blocklist resolver every DHCP lease points
# at. Blocky's HTTP listener (:4000) serves Prometheus metrics, scraped by
# control over the mesh (firewall.nix scopes it to the mesh subnet).
{
config,
lib,
...
}:
let
cfg = config.cnx.router;
dhcpVlans = lib.filterAttrs (_: vlan: vlan.dhcp.enable) cfg.vlans;
in
{
config = lib.mkIf cfg.enable {
services.kea.dhcp4 = {
enable = true;
settings = {
interfaces-config.interfaces = lib.mapAttrsToList (name: _: "vlan-${name}") dhcpVlans;
lease-database = {
type = "memfile";
persist = true;
name = "/var/lib/kea/dhcp4.leases";
};
valid-lifetime = 86400;
subnet4 = lib.mapAttrsToList (name: vlan: {
id = vlan.id;
subnet = vlan.subnet;
interface = "vlan-${name}";
valid-lifetime = vlan.dhcp.leaseTime;
pools = [ { pool = "${vlan.dhcp.pool.from} - ${vlan.dhcp.pool.to}"; } ];
reservations = lib.mapAttrsToList (host: res: {
hostname = host;
hw-address = res.hwAddress;
ip-address = res.ipAddress;
}) vlan.dhcp.reservations;
option-data = [
{
name = "routers";
data = vlan.address;
}
{
name = "domain-name-servers";
data = vlan.address;
}
];
}) dhcpVlans;
};
};
services.blocky = {
enable = true;
settings = {
ports = {
dns = 53;
http = 4000;
};
upstreams.groups.default = [
"9.9.9.9"
"149.112.112.112"
"2620:fe::fe"
];
blocking = {
denylists.ads = [
"https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"
];
clientGroupsBlock.default = [ "ads" ];
};
caching = {
minTime = "5m";
prefetching = true;
};
prometheus.enable = true;
};
};
# The router itself resolves via public resolvers, not via Blocky, so DNS
# for deploys/updates survives a broken local resolver.
networking.nameservers = [
"9.9.9.9"
"1.1.1.1"
];
};
}