{ hostName, config, lib, pkgs, ... }: lib.mkIf config.site.hosts.${hostName}.services.dnscache.enable { services.kresd = { enable = true; instances = 4; listenPlain = [ "0.0.0.0:53" "[::0]:53" ]; package = pkgs.knot-resolver.override { extraFeatures = true; }; extraConfig = /* lua */ '' modules = { 'http', 'policy', 'predict', 'prefill', 'serve_stale < cache', -- servce stail records while refreshing the record 'workarounds < iterate', -- solve problems around specific broken subdomains, mainly disables case randomization 'view' } cache.size = 500 * MB cache.min_ttl(60) net.listen('127.0.0.1', 8453, { kind = 'webmgmt' }) http.prometheus.namespace = 'resolver_' -- dns42 policy.add(policy.suffix( policy.STUB({'fd42:d42:d42:54::1', 'fd42:d42:d42:53::1', '172.20.0.53', '172.23.0.53'}), policy.todnames({'dn42.', 'd.f.ip6.arpa', '20.172.in-addr.arpa', '21.172.in-addr.arpa', '22.172.in-addr.arpa', '23.172.in-addr.arpa'}) )) -- freifunk policy.add(policy.suffix( policy.STUB({'10.200.0.4', '10.200.0.16'}), policy.todnames({'ffdd.', '200.10.in-addr.arpa', '201.10.in-addr.arpa'}) )) -- size.dns.localZones policy.add(policy.suffix( policy.STUB({'${config.site.net.serv.hosts4.dns}', ${lib.concatStringsSep ", " (map (hosts6: "'${hosts6.dns}'") (builtins.attrValues config.site.net.serv.hosts6))}}), policy.todnames({${lib.concatStringsSep ", " (map (zone: "'${zone.name}'") config.site.dns.localZones)}}) )) -- forward to dns caches policy.add(policy.slice( policy.slice_randomize_psl(), -- quad9 policy.TLS_FORWARD({ {'2620:fe::fe', hostname='dns.quad9.net'}, {'2620:fe::9', hostname='dns.quad9.net'}, {'9.9.9.9', hostname='dns.quad9.net'}, {'149.112.112.112', hostname='dns.quad9.net'} }), -- cloudflare policy.TLS_FORWARD({ {'2606:4700:4700::1111', hostname='cloudflare-dns.com'}, {'2606:4700:4700::1001', hostname='cloudflare-dns.com'}, {'1.1.1.1', hostname='cloudflare-dns.com'}, {'1.0.0.1', hostname='cloudflare-dns.com'} }) )) -- allow access from our networks '' + lib.concatMapStringsSep "\n" (cidr: "view:addr('${cidr}', policy.all(policy.PASS))") [ # localhost "::1/128" "127.0.0.0/8" # mgmt "${config.site.net.mgmt.subnet4}" # dn42 "fd23:42:c3d2:500::/56" "::172.20.72.0/117" "::172.22.99.0/120" "172.20.72.0/21" "172.22.99.0/24" # freifunk "10.200.0.0/15" # DSI "2a00:8180:2000:37::1/128" "2a00:8180:2c00:200::/56" # flpk "${config.site.net.flpk.subnet4}" "2a0f:5382:acab:1400::/56 allow" ] + "\n" + /* lua */ '' -- drop everything that hasn't matched view:addr('0.0.0.0/0', policy.all(policy.DROP)) view:addr('::/0', policy.all(policy.DROP)) predict = { window = 15, -- sampling window period = 24*(60/15) -- track last X hours, divide through sampling window } prefill.config({ ['.'] = { url = 'https://www.internic.net/domain/root.zone', interval = 86400, -- seconds } }) trust_anchors.set_insecure({'dn42', 'd.f.ip6.arpa', 'ffdd'}) ''; }; }