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"
'';
};
};
}
|