vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / networking / dnsdist.nix
blobcd87abb3d0725d510eb522da89b7b0e8e6cfc8dc
1 { config, lib, pkgs, ... }:
2 let
3   cfg = config.services.dnsdist;
5   toLua = lib.generators.toLua {};
7   mkBind = cfg: toLua "${cfg.listenAddress}:${toString cfg.listenPort}";
9   configFile = pkgs.writeText "dnsdist.conf" ''
10     setLocal(${mkBind cfg})
11     ${lib.optionalString cfg.dnscrypt.enable dnscryptSetup}
12     ${cfg.extraConfig}
13   '';
15   dnscryptSetup = ''
16     last_rotation = 0
17     cert_serial = 0
18     provider_key = ${toLua cfg.dnscrypt.providerKey}
19     cert_lifetime = ${toLua cfg.dnscrypt.certLifetime} * 60
21     function file_exists(name)
22        local f = io.open(name, "r")
23        return f ~= nil and io.close(f)
24     end
26     function dnscrypt_setup()
27       -- generate provider keys on first run
28       if provider_key == nil then
29         provider_key = "/var/lib/dnsdist/private.key"
30         if not file_exists(provider_key) then
31           generateDNSCryptProviderKeys("/var/lib/dnsdist/public.key",
32                                        "/var/lib/dnsdist/private.key")
33           print("DNSCrypt: generated provider keypair")
34         end
35       end
37       -- generate resolver certificate
38       local now = os.time()
39       generateDNSCryptCertificate(
40         provider_key, "/run/dnsdist/resolver.cert", "/run/dnsdist/resolver.key",
41         cert_serial, now - 60, now + cert_lifetime)
42       addDNSCryptBind(
43         ${mkBind cfg.dnscrypt}, ${toLua cfg.dnscrypt.providerName},
44         "/run/dnsdist/resolver.cert", "/run/dnsdist/resolver.key")
45     end
47     function maintenance()
48       -- certificate rotation
49       local now = os.time()
50       local dnscrypt = getDNSCryptBind(0)
52       if ((now - last_rotation) > 0.9 * cert_lifetime) then
53         -- generate and start using a new certificate
54         dnscrypt:generateAndLoadInMemoryCertificate(
55           provider_key, cert_serial + 1,
56           now - 60, now + cert_lifetime)
58         -- stop advertising the last certificate
59         dnscrypt:markInactive(cert_serial)
61         -- remove the second to last certificate
62         if (cert_serial > 1)  then
63           dnscrypt:removeInactiveCertificate(cert_serial - 1)
64         end
66         print("DNSCrypt: rotated certificate")
68         -- increment serial number
69         cert_serial = cert_serial + 1
70         last_rotation = now
71       end
72     end
74     dnscrypt_setup()
75   '';
77 in {
78   options = {
79     services.dnsdist = {
80       enable = lib.mkEnableOption "dnsdist domain name server";
82       listenAddress = lib.mkOption {
83         type = lib.types.str;
84         description = "Listen IP address";
85         default = "0.0.0.0";
86       };
87       listenPort = lib.mkOption {
88         type = lib.types.port;
89         description = "Listen port";
90         default = 53;
91       };
93       dnscrypt = {
94         enable = lib.mkEnableOption "a DNSCrypt endpoint to dnsdist";
96         listenAddress = lib.mkOption {
97           type = lib.types.str;
98           description = "Listen IP address of the endpoint";
99           default = "0.0.0.0";
100         };
102         listenPort = lib.mkOption {
103           type = lib.types.port;
104           description = "Listen port of the endpoint";
105           default = 443;
106         };
108         providerName = lib.mkOption {
109           type = lib.types.str;
110           default = "2.dnscrypt-cert.${config.networking.hostName}";
111           defaultText = lib.literalExpression "2.dnscrypt-cert.\${config.networking.hostName}";
112           example = "2.dnscrypt-cert.myresolver";
113           description = ''
114             The name that will be given to this DNSCrypt resolver.
116             ::: {.note}
117             The provider name must start with `2.dnscrypt-cert.`.
118             :::
119           '';
120         };
122         providerKey = lib.mkOption {
123           type = lib.types.nullOr lib.types.path;
124           default = null;
125           description = ''
126             The filepath to the provider secret key.
127             If not given a new provider key pair will be generated in
128             /var/lib/dnsdist on the first run.
130             ::: {.note}
131             The file must be readable by the dnsdist user/group.
132             :::
133           '';
134         };
136         certLifetime = lib.mkOption {
137           type = lib.types.ints.positive;
138           default = 15;
139           description = ''
140             The lifetime (in minutes) of the resolver certificate.
141             This will be automatically rotated before expiration.
142           '';
143         };
145       };
147       extraConfig = lib.mkOption {
148         type = lib.types.lines;
149         default = "";
150         description = ''
151           Extra lines to be added verbatim to dnsdist.conf.
152         '';
153       };
154     };
155   };
157   config = lib.mkIf cfg.enable {
158     users.users.dnsdist = {
159       description = "dnsdist daemons user";
160       isSystemUser = true;
161       group = "dnsdist";
162     };
164     users.groups.dnsdist = {};
166     systemd.packages = [ pkgs.dnsdist ];
168     systemd.services.dnsdist = {
169       wantedBy = [ "multi-user.target" ];
171       startLimitIntervalSec = 0;
172       serviceConfig = {
173         User = "dnsdist";
174         Group = "dnsdist";
175         RuntimeDirectory = "dnsdist";
176         StateDirectory = "dnsdist";
177         # upstream overrides for better nixos compatibility
178         ExecStartPre = [ "" "${pkgs.dnsdist}/bin/dnsdist --check-config --config ${configFile}" ];
179         ExecStart = [ "" "${pkgs.dnsdist}/bin/dnsdist --supervised --disable-syslog --config ${configFile}" ];
180       };
181     };
182   };