{ config, lib, pkgs, ... }: let dnsConfig = pkgs.writeText "pinix-router-dns.conf" '' server: interface: 127.0.0.2 interface: 192.168.50.1 interface: 192.168.51.1 interface: fd42:50:0::1 interface: fd42:50:1::1 access-control: 127.0.0.0/8 allow access-control: 192.168.50.0/24 allow access-control: 192.168.51.0/24 allow # /48 fixiert das 3. Hextet auf 0 und deckt damit nur end0 # (fd42:50:0::/64) ab, nicht wlan0 (fd42:50:1::/64) -- gefunden # am 13.09.2026: DNS ueber IPv6 vom WLAN kam als "Refused" zurueck, # jede Anfrage eines iPad-Clients. /32 deckt beide (und kuenftige) # Subnetze unter fd42:50:* ab. access-control: fd42:50::/32 allow access-control: 0.0.0.0/0 refuse access-control: ::/0 refuse ip-freebind: yes do-ip4: yes do-ip6: yes do-not-query-address: 0.0.0.0/0 username: "" chroot: "" directory: "/run/pinix-router-dns" pidfile: "" do-daemonize: no use-syslog: no # Upstream already synthesises DNS64; validating those synthetic # answers locally would reject signed IPv4-only domains. module-config: "iterator" hide-identity: yes hide-version: yes forward-zone: name: "." # Telekom resolvers advertised by the Nokia on 2026-09-13. # Direct AAAA queries confirmed DNS64 (64:ff9b::/96) on both servers. forward-addr: 2a01:598:7ff:0:10:74:210:221 forward-addr: 2a01:598:7ff:0:10:74:210:222 ''; in { # Match the phone independently of its USB socket or random Ethernet MAC. systemd.network.links."10-nokia-uplink" = { matchConfig = { Driver = "rndis_host"; Property = "ID_MODEL=Nokia_6300_4G"; }; linkConfig.Name = "wan0"; }; networking.interfaces.end0.useDHCP = lib.mkForce false; networking.interfaces.wan0 = { useDHCP = true; tempAddress = "disabled"; }; networking.nameservers = [ "127.0.0.2" ]; networking.dhcpcd.extraConfig = lib.mkForce '' nohook resolv.conf interface wan0 nooption routers ''; boot.kernel.sysctl."net.ipv6.conf.wan0.accept_ra" = 2; # Public authoritative DNS follows the phone's changing global address. # Exclude the LAN DNS64 and Tailnet recursive resolver bindings. # /32 (not /48, see the access-control comment above) to also exclude # wlan0's fd42:50:1::/64, not just end0's fd42:50:0::/64. services.bind.listenOnIpv6 = lib.mkForce [ "!fd42:50::/32" "!fd7a:115c:a1e0::/48" "any" ]; # Public services only on the phone uplink; administration stays on LAN. networking.firewall = { allowedTCPPorts = lib.mkForce [ 53 80 443 ]; allowedUDPPorts = lib.mkForce [ 53 ]; interfaces.end0.allowedTCPPorts = [ 22 53 ]; interfaces.end0.allowedUDPPorts = [ 53 ]; interfaces.tailscale0.allowedTCPPorts = [ 22 ]; }; # Separate DNS64 resolver: preserve the existing authoritative BIND and # Tailnet resolver, which must not receive cellular-only DNS64 answers. systemd.services.pinix-router-dns = { description = "DNS64 for the Nokia uplink and wired management LAN"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; serviceConfig = { DynamicUser = true; RuntimeDirectory = "pinix-router-dns"; AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ]; NoNewPrivileges = true; ProtectSystem = "strict"; ProtectHome = true; ExecStartPre = "${pkgs.unbound}/bin/unbound-checkconf ${dnsConfig}"; ExecStart = "${pkgs.unbound}/bin/unbound -d -c ${dnsConfig}"; Restart = "on-failure"; RestartSec = "2s"; }; }; }