summaryrefslogtreecommitdiffstats
path: root/krebs/2configs/nameserver.nix
blob: 4b205a13d7fffc40db4e86c42c335dd7ca8da6e3 (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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
{ config, lib, pkgs, ... }: let
  acmeChallenge =
    { domain
    , nameserver
    , adminEmail
    , serial ? 0
    , refresh ? 3600
    , retry ? 900
    , expire ? 604800
    , minimum ? 180
    }:
    pkgs.writeText "${domain}.zone" /* bindzone */ ''
      $TTL 60
      @ IN SOA ${lib.concatStringsSep " " [
        "${nameserver}."
        "${lib.replaceStrings ["@"] ["."] adminEmail}."
        (toString serial)
        (toString refresh)
        (toString retry)
        (toString expire)
        (toString minimum)
      ]}
      @ IN NS ${nameserver}.
    '';
in {
  networking.firewall.allowedTCPPorts = [
    53 # domain for AXFR
  ];
  networking.firewall.allowedUDPPorts = [
    53 # domain
  ];

  krebs.systemd.services.knot.restartIfCredentialsChange = true;
  systemd.services.knot.serviceConfig.LoadCredential = [
    "keys.conf:/var/src/secrets/knot-keys.conf"
  ];

  services.knot = {
    enable = true;
    keyFiles = [
      "/run/credentials/knot.service/keys.conf"
    ];
    extraConfig = /* yaml */ ''
      server:
        udp-max-payload: 4096
        listen: [ 127.0.0.53@2, ${
          lib.concatMapStringsSep ", "
            (addr: "${addr}@53")
            (
              config.krebs.build.host.nets.internet.addrs or []
              ++
              # This is required for hosts at OCI because the default route
              # provided by DHCP is using the private address.
              config.krebs.build.host.nets.intranet.addrs or []
            )
        } ]

      log:
        - target: syslog
          any: debug

      remote:

      acl:
        - id: acme_acl
          key: acme
          action: update

        - id: dane_acl
          key: dane
          action: update

      mod-rrl:
        - id: default
          rate-limit: 200   # Allow 200 resp/s for each flow
          slip: 2           # Every other response slips

      policy:
        - id: rsa2k
          algorithm: rsasha256
          ksk-size: 4096
          zsk-size: 2048

      template:
        - id: default
          global-module: mod-rrl/default
          semantic-checks: on
          zonefile-sync: -1
          zonefile-load: difference-no-serial
          journal-content: all

      zone:
        - domain: krebsco.de
          file: ${pkgs.krebs.zones."krebsco.de"}
          dnssec-signing: on
          dnssec-policy: rsa2k
          acl: dane_acl

        - domain: _acme-challenge.krebsco.de
          file: ${acmeChallenge {
            domain = "_acme-challenge.krebsco.de";
            nameserver = "ns1.krebsco.de";
            adminEmail = "spam@krebsco.de";
          }}
          acl: acme_acl

        - domain: r
          file: ${pkgs.krebs.zones.r}

        - domain: w
          file: ${pkgs.krebs.zones.w}
    '';
  };

  systemd.services."knsupdate-krebsco.de" = {
    serviceConfig = {
      Type = "oneshot";
      SyslogIdentifier = "knsupdate-krebsco.de";
      ExecStart = pkgs.writeDash "knsupdate-krebsco.de" /* sh */ ''
        set -efu

        mk_certificate_association_data() {
          ${pkgs.openssl}/bin/openssl x509 -noout -fingerprint -sha256 < "$1" |
          ${pkgs.coreutils}/bin/cut -d= -f2 |
          ${pkgs.coreutils}/bin/tr -d :
        }

        certfile=/var/lib/acme/krebsco.de/cert.pem
        certificate_association_data=$(mk_certificate_association_data "$certfile")
        keyfile=/var/src/secrets/dane.tsig

        script=$(${pkgs.coreutils}/bin/mktemp -t knsupdate.XXXXXXXX)
        trap 'rm "$script"' EXIT
        (
          exec >"$script"
          echo server krebsco.de.
          echo zone krebsco.de.
          echo origin krebsco.de.
          echo add _25._tcp.ni 60 IN TLSA 3 0 1 $certificate_association_data
          echo add _443._tcp.ni 60 IN TLSA 3 0 1 $certificate_association_data
          echo show
          echo send
          echo answer
          echo quit
        )
        ${pkgs.knot-dns}/bin/knsupdate -k "$keyfile" "$script"
      '';
    };
  };
}