{ config, lib, ... }: let cfg = config.router; lans = lib.attrValues cfg.lans; ipv4 = (import ./lib.nix { inherit lib; }).ipv4; # Tunnels that opted into DNS: listen on each of their addresses. dnsAddrs = lib.concatMap (w: w.addresses) (lib.filter (w: w.dns) (lib.attrValues cfg.wireguard)); addrOf = a: builtins.head (lib.splitString "/" a); # IPv4 gets the proper network address; IPv6 netblocks are masked by Unbound. netOf = a: let parts = lib.splitString "/" a; in if lib.hasInfix ":" a then a else ipv4.cidr (builtins.head parts) (lib.toInt (builtins.elemAt parts 1)); in { config = lib.mkIf cfg.enable { services.unbound = { enable = true; settings = { server = { interface = [ "127.0.0.1" ] ++ map (l: l.ipv4.address) lans ++ map addrOf dnsAddrs; # LAN addresses are assigned by networkd, possibly after Unbound starts. ip-freebind = true; access-control = [ "127.0.0.0/8 allow" ] ++ map (l: "${l.ipv4.subnet} allow") lans ++ map (a: "${netOf a} allow") dnsAddrs; }; } // lib.optionalAttrs (cfg.dns.forwarders != [ ]) { forward-zone = [ { name = "."; forward-addr = cfg.dns.forwarders; } ]; }; }; }; }