From c8b65092be067044f73c3ff643cd822e9ebcb417 Mon Sep 17 00:00:00 2001 From: Jack O'Sullivan Date: Sat, 25 Nov 2023 15:07:58 +0000 Subject: [PATCH] nixos/home/routing-common: Dynamically return WAN IP DNS --- lib/default.nix | 14 ++++++++ lib/dns.nix | 31 ++++++++++++++++ nixos/boxes/home/routing-common/default.nix | 1 + nixos/boxes/home/routing-common/dns.nix | 39 +++++++++++++++------ 4 files changed, 75 insertions(+), 10 deletions(-) diff --git a/lib/default.nix b/lib/default.nix index aef706c..e889606 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -8,6 +8,18 @@ let inherit (lib.flake) defaultSystems; in rec { + pow = + let + pow' = base: exponent: value: + # FIXME: It will silently overflow on values > 2**62 :( + # The value will become negative or zero in this case + if exponent == 0 + then 1 + else if exponent <= 1 + then value + else (pow' base (exponent - 1) (value * base)); + in base: exponent: pow' base exponent base; + attrsToNVList = mapAttrsToList nameValuePair; inherit (import ./net.nix { inherit lib; }) net; @@ -29,6 +41,8 @@ rec { ports = checked (elemAt m 1); }; + netBroadcast = net': net.cidr.host ((pow 2 (net.cidr.size net')) - 1) net'; + mkDefaultSystemsPkgs = path: args': genAttrs defaultSystems (system: import path ((args' system) // { inherit system; })); mkApp = program: { type = "app"; inherit program; }; mkShellApp = pkgs: name: text: mkApp (pkgs.writeShellScript name text).outPath; diff --git a/lib/dns.nix b/lib/dns.nix index 15ac486..55055d6 100644 --- a/lib/dns.nix +++ b/lib/dns.nix @@ -67,4 +67,35 @@ rec { (a.ipv6.address != null && a.ipv6.genPTR) ''@@PTR:${a.ipv6.address}:${toString ndots}@@ IN PTR ${a.name}.${domain}.''; }; + + ifaceA = { pkgs, iface, skipBroadcasts ? [] }: + let + extraFilters = concatMapStringsSep " " (b: ''and .broadcast != \"${b}\"'') skipBroadcasts; + script = pkgs.writeText "if-${iface}-a.lua" '' + local proc = io.popen("${pkgs.iproute2}/bin/ip -j addr show dev ${iface} | ${pkgs.jq}/bin/jq -r '.[0].addr_info[] | select(.family == \"inet\" and .scope == \"global\" ${extraFilters}).local'", "r") + assert(proc, "failed to popen") + + local addr_line = proc:read("*l") + assert(proc:close(), "command failed") + assert(addr_line, "no output from command") + + return addr_line + ''; + in + ''A "dofile('${script}')"''; + + lookupIP = { pkgs, hostname, server, type ? "A" }: + let + script = pkgs.writeScript "drill-${hostname}-${server}.lua" '' + local proc = io.popen("${pkgs.ldns}/bin/drill -Q @${server} ${hostname} ${type}", "r") + assert(proc, "failed to popen") + + local addr_line = proc:read("*l") + assert(proc:close(), "command failed") + assert(addr_line, "no output from command") + + return addr_line + ''; + in + ''${type} "dofile('${script}')"''; } diff --git a/nixos/boxes/home/routing-common/default.nix b/nixos/boxes/home/routing-common/default.nix index 590e4d9..0057fbd 100644 --- a/nixos/boxes/home/routing-common/default.nix +++ b/nixos/boxes/home/routing-common/default.nix @@ -26,6 +26,7 @@ in }; hi = { inherit domain; + name = "${name}-hi"; ipv4 = { address = net.cidr.host (index + 1) prefixes.hi.v4; mask = 22; diff --git a/nixos/boxes/home/routing-common/dns.nix b/nixos/boxes/home/routing-common/dns.nix index 24b0523..ad1d685 100644 --- a/nixos/boxes/home/routing-common/dns.nix +++ b/nixos/boxes/home/routing-common/dns.nix @@ -1,8 +1,12 @@ index: { lib, pkgs, config, assignments, allAssignments, ... }: let - inherit (builtins) attrNames; + inherit (builtins) attrNames elemAt; inherit (lib.my) net; - inherit (lib.my.c.home) prefixes vips; + inherit (lib.my.c.home) prefixes vips routers; + + name = elemAt routers index; + otherIndex = 1 - index; + otherName = elemAt routers otherIndex; authZones = attrNames config.my.pdns.auth.bind.zones; in @@ -63,6 +67,11 @@ in }; }; + systemd.services = { + # Add AF_NETLINK to allow pulling IP from network interfaces + pdns.serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK"; + }; + # For rec_control environment.systemPackages = with pkgs; [ pdns-recursor @@ -80,9 +89,9 @@ in ]; also-notify = [ "127.0.0.1" ]; enable-lua-records = true; - #loglevel = 7; - #log-dns-queries = true; - #log-dns-details = true; + # loglevel = 7; + # log-dns-queries = true; + # log-dns-details = true; api = true; webserver = true; @@ -108,13 +117,23 @@ in 1h ; minimum ) + ${name} IN LUA ${lib.my.dns.ifaceA { + inherit pkgs; + iface = "wan"; + skipBroadcasts = [ (lib.my.netBroadcast prefixes.modem.v4) ]; + }} + ${otherName} IN LUA ${lib.my.dns.lookupIP { + inherit pkgs; + hostname = "${otherName}.${config.networking.domain}"; + server = net.cidr.host (otherIndex + 1) prefixes.hi.v4; + }} + ${elemAt routers 0} IN AAAA ${net.cidr.host 1 prefixes.hi.v6} + ${elemAt routers 1} IN AAAA ${net.cidr.host 2 prefixes.hi.v6} + @ IN NS ns1 @ IN NS ns2 - ; TODO: WAN? - ns1 IN A ${net.cidr.host 1 prefixes.hi.v4} - ns2 IN A ${net.cidr.host 2 prefixes.hi.v4} - ns1 IN AAAA ${net.cidr.host 1 prefixes.hi.v6} - ns2 IN AAAA ${net.cidr.host 2 prefixes.hi.v6} + ns1 IN ALIAS ${elemAt routers 0}.${config.networking.domain}. + ns2 IN ALIAS ${elemAt routers 1}.${config.networking.domain}. jim-core IN A ${net.cidr.host 10 prefixes.core.v4} jim IN A ${net.cidr.host 10 prefixes.hi.v4}