summaryrefslogtreecommitdiff
path: root/hosts/ahmed/local-dns/dns-resolver.nix
blob: 7d966ee8d0e7f0e39483f4c6a9a833034a091bec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# This module creates a local DNS server which provides "split horizon DNS".
#
# It only serves devices on the LAN (see `services.dnscache.clientIps`) and for
# those, it claims to have authority over the domain set in `config.linus.local-dns.domain`.
#
# See: https://www.fefe.de/djbdns/split-horizon
{
  config,
  metadata,
  lib,
  ...
}: {
  services.dnscache = {
    enable = true;
    clientIps = [
      "192.168" # LAN
      "127.0.0.1" # Local connections
    ];

    domainServers = {
      # Forward any requests to the split domain to our local, authoritative name server.
      ${config.linus.local-dns.domain} = ["127.0.0.1"];
    };
  };

  # Authoritative name server which claims ownership of the split domain.
  services.tinydns = {
    enable = true;

    # We will only listen for internal queries from the DNS cache.
    ip = "127.0.0.1";

    # Here we publish all the services we want.
    data = let
      subdomainToARecord = subdomain: "=${subdomain}.${config.linus.local-dns.domain}:${metadata.hosts.ahmed.ipv4Address}";
      ARecords = lib.concatMapStringsSep "\n" subdomainToARecord config.linus.local-dns.subdomains;
    in ''
      # We are authoritative over ${config.linus.local-dns.domain}.
      # Here we simply identify as localhost, as only the local dnscache instance will ever see this (I think).
      .${config.linus.local-dns.domain}:127.0.0.1:a
      # Next, we link all the subdomains to our LAN IP.
      ${ARecords}
    '';
  };

  # Allow other devices on LAN to interact with us. In the router's DHCP
  # settings, I have set ahmed's IP as the primary DNS server. This will make
  # all clients (which respect DNS from DHCP) use ahmed if he's online.
  #
  # Notably, the NAT on the router does not route external trafic here; we are
  # a non-authoritative DNS resolver, so we don't want to service the global
  # internet.
  networking.firewall = {
    allowedTCPPorts = [53];
    allowedUDPPorts = [53];
  };
}