From 8377f369f11f645772eb121ed7bfe5ab8163662d Mon Sep 17 00:00:00 2001 From: Felix Albrigtsen Date: Sun, 18 Jan 2026 21:32:50 +0100 Subject: [PATCH] Add support for ipv6-reverse --- hosts.nix | 10 +++-- zoneConfig.nix | 2 +- zones/reverse-ipv6.nix | 86 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 zones/reverse-ipv6.nix diff --git a/hosts.nix b/hosts.nix index cb4f80e..95c026d 100644 --- a/hosts.nix +++ b/hosts.nix @@ -5,9 +5,10 @@ in { # Note: See ./README.md for usage # Hosts specified here will be included in the default/general DNS setup, with records in - # - pvv.org - # - pvv.ntnu.no + # - pvv.org. + # - pvv.ntnu.no. # - 210.241.129.in-addr.arpa. (reverse-ipv4, where applicable) + # - 9.1.0.0.3.0.0.0.7.0.1.0.0.2.ip6.arpa. (reverse-ipv6, where applicable) # Terminaler demiurgen = { @@ -27,7 +28,10 @@ in # PVV-DNS code stress-testing: utenipv4 = { - ipv6 = pvvv6 1337; + ipv6 = [ + (pvvv6 1337) + (pvvv6 "cafe:babe") + ]; }; utenipv6 = { diff --git a/zoneConfig.nix b/zoneConfig.nix index 4b547c6..42cd277 100644 --- a/zoneConfig.nix +++ b/zoneConfig.nix @@ -15,7 +15,7 @@ let "pvv.org" = ./zones/pvv.org.nix; "210.241.129.in-addr.arpa" = ./zones/reverse-ipv4-parent.nix; "128-255.210.241.129.in-addr.arpa" = ./zones/reverse-ipv4.nix; - #"reverse-ipv6" = ./zones/reverse-ipv6.nix; + "9.1.0.0.3.0.0.0.7.0.1.0.0.2.ip6.arpa" = ./zones/reverse-ipv6.nix; }; in stdenvNoCC.mkDerivation { diff --git a/zones/reverse-ipv6.nix b/zones/reverse-ipv6.nix new file mode 100644 index 0000000..67b2a66 --- /dev/null +++ b/zones/reverse-ipv6.nix @@ -0,0 +1,86 @@ +{ dns, lib, ... }: + +with dns.lib.combinators; +let + pvvv6Prefix = builtins.substring 0 14 (normalizev6 "2001:700:300:1900::"); + domainSuffix = ".pvv.ntnu.no."; + + # Pad a number or string with zeroes to length 4 (32 -> "0032") + padTo4 = + n: + let + padded = "0000${toString n}"; + in + builtins.substring (builtins.stringLength padded - 4) 4 padded; + + # Takes an IPv6 address on the format nnnnXXXXnnnn (literal XXXX) and replaces XXXX with enough zeroes to make a full 128 bit address + padDoubleColon = + addr: + let + parts = lib.splitString "XXXX" addr; + nibbleCount = builtins.foldl' builtins.add 0 (map builtins.stringLength parts); + zeros = lib.concatStrings (builtins.genList (i: "0") (32 - nibbleCount)); + in + lib.replaceStrings [ "XXXX" ] [ zeros ] addr; + + # Translate an IPv6 address (e.g. 2001:700:300:1900::1) into the fully expanded 20010700030019000000000000000001 + normalizev6 = + addr: + (lib.pipe addr [ + (lib.replaceStrings [ "::" ] [ ":XXXX:" ]) + (lib.splitString ":") + (map padTo4) + (map (lib.splitString "")) + (lib.flatten) + (lib.concatStrings) + (padDoubleColon) + ]); + + # Translate an address from the form 20010700030019000000000000000001 to the prefix-stripped, reversed and dotted form + # 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 as used in a PTR record + ptrFormatv6 = + addr: + (lib.pipe addr [ + (lib.removePrefix pvvv6Prefix) + (lib.splitString "") + (lib.flatten) + (lib.filter (n: n != "")) + (lib.reverseList) + (lib.concatStringsSep ".") + ]); + + pvvHostRecords = import ../pvv-subdomains.nix { inherit dns lib; }; + + # Find all the AAAA-records pointing into the PVV-network, and generate the opposing PTR records + # TODO: Handle duplicates? + pvvHostReverseRecords = builtins.listToAttrs ( + lib.concatLists ( + lib.mapAttrsToList ( + target: host: + lib.map (aaaaRecordKey: { + name = ptrFormatv6 aaaaRecordKey; + value.PTR = [ (target + domainSuffix) ]; + }) (lib.filter (e: lib.hasPrefix pvvv6Prefix e) (map normalizev6 (host.AAAA or [ ]))) + ) pvvHostRecords + ) + ); + + additionalReverseRecords = { + "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0".PTR = [ "hb-gw4.ntnu.no." ]; # Gateway router/switch + }; +in +{ + useOrigin = true; # Don't output fully qualified names + + SOA = { + nameServer = "dvask.pvv.ntnu.no"; + adminEmail = "drift@pvv.ntnu.no"; + serial = 2025021701; # TODO: Automate + }; + NS = [ + "dvask.pvv.ntnu.no" + "nn.unintett.no" + ]; + + subdomains = pvvHostReverseRecords // additionalReverseRecords; +}