nixos-config/config/service/local-network.nix

208 lines
5.5 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
hostname = config.instance.hostname;
domain-name = config.fudo.hosts.${hostname}.domain;
site-name = config.fudo.hosts.${hostname}.site;
zone-name = config.fudo.domains.${domain-name}.zone;
site = config.fudo.sites.${site-name};
cfg = config.fudo.services.local-network;
resolverOpts = {
options = {
ip = mkOption {
type = str;
description = "IP address of the upstream recursive resolver.";
default = "1.1.1.1";
};
port = mkOption {
type = port;
description = "Port of DNS server on the recursive resolver.";
default = 53;
};
};
};
in {
options.fudo.services.local-network = with types; {
enable = mkEnableOption "Enable local network server.";
internal-interfaces = mkOption {
type = listOf str;
description = ''
Interfaces on which to:
* Accept NAT traffic
* Serve DNS
* Serve DHCP
'';
};
external-interface = mkOption {
type = str;
description = "Interface facing the larger internet.";
example = "extif0";
};
resolvers = mkOption {
type = listOf (submodule resolverOpts);
description = "List of upstream DNS servers.";
default = [
{ ip = "1.1.1.1"; }
{ ip = "1.0.0.1"; }
{ ip = "9.9.9.9"; }
{ ip = "149.112.112.112"; }
];
};
dns-filter-proxy = {
enable = mkEnableOption "Enable DNS filter.";
http-listen-port = mkOption {
type = port;
description = "Port on localhost on which to listen for HTTP requests.";
default = 4080;
};
http-host-alias = mkOption {
type = str;
description = "Host alias for the DNS filter server.";
default = "dns-filter";
};
dns-listen-port = mkOption {
type = port;
description = "Port on localhost on which to listen for DNS requests.";
default = 4053;
};
upstream-dns = mkOption {
type = listOf str;
description = "List of upstream DNS-over-HTTPS endpoints.";
default = [
"https://1.1.1.1/dns-query"
"https://1.0.0.1/dns-query"
# These 11 addrs send the network, so the response can prefer closer answers
"https://9.9.9.11/dns-query"
"https://149.112.112.11/dns-query"
"https://2620:fe::11/dns-query"
"https://2620:fe::fe:11/dns-query"
];
};
};
};
config = mkIf (site.local-gateway != null) (let
host-ipv4 = pkgs.lib.network.host-ipv4 config;
gateway-host = site.local-gateway;
nameserver-host = gateway-host;
gateway-ip = host-ipv4 gateway-host;
nameserver-ip = host-ipv4 gateway-host;
is-gateway = hostname == gateway-host;
agp = cfg.dns-filter-proxy;
fqdn = hostname: "${hostname}.${domain-name}.";
in {
networking = {
nat = mkIf is-gateway {
enable = true;
externalInterface = cfg.external-interface;
internalInterfaces = cfg.internal-interfaces;
};
nameservers = [ nameserver-ip ];
firewall = if is-gateway then {
enable = true;
trustedInterfaces = cfg.internal-interfaces;
} else {
enable = false;
};
};
fudo = {
adguard-dns-proxy = mkIf agp.enable {
enable = true;
http = {
listen-ip = "127.0.0.1";
listen-port = agp.http-listen-port;
};
dns = {
listen-ips = [ "127.0.0.1" ];
listen-port = agp.dns-listen-port;
reverse-dns = [ (host-ipv4 gateway-host) ];
};
local-domain-name = domain-name;
};
zones."${zone-name}" = {
aliases = {
"${agp.http-host-alias}" = mkIf (agp.enable) (fqdn gateway-host);
ns = (fqdn nameserver-host);
gw = (fqdn gateway-host);
};
hosts = {
gateway.ipv4-address = gateway-ip;
nameserver.ipv4-address = nameserver-ip;
};
nameservers = [ "nameserver" ];
srv-records = {
tcp.domain = [{
host = "nameserver.${domain-name}";
port = 53;
}];
udp.domain = [{
host = "nameserver.${domain-name}";
port = 53;
}];
};
};
local-network = {
enable = is-gateway;
domain = domain-name;
dns-servers = [ nameserver-ip ];
gateway = gateway-ip;
dhcp-interfaces = cfg.internal-interfaces;
dns-listen-ips =
optionals is-gateway [ nameserver-ip "127.0.0.1" "127.0.1.1" ];
dns-listen-ipv6s =
optionals (is-gateway && config.networking.enableIPv6) [ "::1" ];
recursive-resolver = if agp.enable then {
host = "127.0.0.1";
port = agp.dns-listen-port;
} else {
host = cfg.resolver.ip;
port = cfg.resolver.port;
};
network = site.network;
dhcp-dynamic-network = site.dynamic-network;
search-domains = [ domain-name "fudo.org" ];
enable-reverse-mappings = true;
zone-definition = config.fudo.zones.${zone-name};
};
};
services.nginx = mkIf agp.enable {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
virtualHosts = {
"${agp.http-host-alias}.${domain-name}" = {
locations."/".proxyPass =
"http://127.0.0.1:${toString agp.http-listen-port}";
};
};
};
});
}