aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2019-10-05 12:43:18 +0000
committerKatharina Fey <kookie@spacekookie.de>2019-10-05 12:44:52 +0000
commitcf85056ba64caf3267d43255ef4a1243e9c8ee3b (patch)
tree3051519e9c8275b870aac43f80af875715c9d124 /nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix
parent1148b1d122bc03e9a3665856c9b7bb96bd4e3994 (diff)
parent2436c27541b2f52deea3a4c1691216a02152e729 (diff)
Add 'nixpkgs/' from commit '2436c27541b2f52deea3a4c1691216a02152e729'
git-subtree-dir: nixpkgs git-subtree-mainline: 1148b1d122bc03e9a3665856c9b7bb96bd4e3994 git-subtree-split: 2436c27541b2f52deea3a4c1691216a02152e729
Diffstat (limited to 'nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix')
-rw-r--r--nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix199
1 files changed, 199 insertions, 0 deletions
diff --git a/nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix b/nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix
new file mode 100644
index 00000000000..bf13d5c6f5f
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/dnscrypt-wrapper.nix
@@ -0,0 +1,199 @@
+{ config, lib, pkgs, ... }:
+with lib;
+
+let
+ cfg = config.services.dnscrypt-wrapper;
+ dataDir = "/var/lib/dnscrypt-wrapper";
+
+ daemonArgs = with cfg; [
+ "--listen-address=${address}:${toString port}"
+ "--resolver-address=${upstream.address}:${toString upstream.port}"
+ "--provider-name=${providerName}"
+ "--provider-publickey-file=public.key"
+ "--provider-secretkey-file=secret.key"
+ "--provider-cert-file=${providerName}.crt"
+ "--crypt-secretkey-file=${providerName}.key"
+ ];
+
+ genKeys = ''
+ # generates time-limited keypairs
+ keyGen() {
+ dnscrypt-wrapper --gen-crypt-keypair \
+ --crypt-secretkey-file=${cfg.providerName}.key
+
+ dnscrypt-wrapper --gen-cert-file \
+ --crypt-secretkey-file=${cfg.providerName}.key \
+ --provider-cert-file=${cfg.providerName}.crt \
+ --provider-publickey-file=public.key \
+ --provider-secretkey-file=secret.key \
+ --cert-file-expire-days=${toString cfg.keys.expiration}
+ }
+
+ cd ${dataDir}
+
+ # generate provider keypair (first run only)
+ if [ ! -f public.key ] || [ ! -f secret.key ]; then
+ dnscrypt-wrapper --gen-provider-keypair
+ fi
+
+ # generate new keys for rotation
+ if [ ! -f ${cfg.providerName}.key ] || [ ! -f ${cfg.providerName}.crt ]; then
+ keyGen
+ fi
+ '';
+
+ rotateKeys = ''
+ # check if keys are not expired
+ keyValid() {
+ fingerprint=$(dnscrypt-wrapper --show-provider-publickey | awk '{print $(NF)}')
+ dnscrypt-proxy --test=${toString (cfg.keys.checkInterval + 1)} \
+ --resolver-address=127.0.0.1:${toString cfg.port} \
+ --provider-name=${cfg.providerName} \
+ --provider-key=$fingerprint
+ }
+
+ cd ${dataDir}
+
+ # archive old keys and restart the service
+ if ! keyValid; then
+ echo "certificate soon to become invalid; backing up old cert"
+ mkdir -p oldkeys
+ mv -v ${cfg.providerName}.key oldkeys/${cfg.providerName}-$(date +%F-%T).key
+ mv -v ${cfg.providerName}.crt oldkeys/${cfg.providerName}-$(date +%F-%T).crt
+ systemctl restart dnscrypt-wrapper
+ fi
+ '';
+
+in {
+
+
+ ###### interface
+
+ options.services.dnscrypt-wrapper = {
+ enable = mkEnableOption "DNSCrypt wrapper";
+
+ address = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = ''
+ The DNSCrypt wrapper will bind to this IP address.
+ '';
+ };
+
+ port = mkOption {
+ type = types.int;
+ default = 5353;
+ description = ''
+ The DNSCrypt wrapper will listen for DNS queries on this port.
+ '';
+ };
+
+ providerName = mkOption {
+ type = types.str;
+ default = "2.dnscrypt-cert.${config.networking.hostName}";
+ example = "2.dnscrypt-cert.myresolver";
+ description = ''
+ The name that will be given to this DNSCrypt resolver.
+ Note: the resolver name must start with <literal>2.dnscrypt-cert.</literal>.
+ '';
+ };
+
+ upstream.address = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = ''
+ The IP address of the upstream DNS server DNSCrypt will "wrap".
+ '';
+ };
+
+ upstream.port = mkOption {
+ type = types.int;
+ default = 53;
+ description = ''
+ The port of the upstream DNS server DNSCrypt will "wrap".
+ '';
+ };
+
+ keys.expiration = mkOption {
+ type = types.int;
+ default = 30;
+ description = ''
+ The duration (in days) of the time-limited secret key.
+ This will be automatically rotated before expiration.
+ '';
+ };
+
+ keys.checkInterval = mkOption {
+ type = types.int;
+ default = 1440;
+ description = ''
+ The time interval (in minutes) between key expiration checks.
+ '';
+ };
+
+ };
+
+
+ ###### implementation
+
+ config = mkIf cfg.enable {
+
+ users.users.dnscrypt-wrapper = {
+ description = "dnscrypt-wrapper daemon user";
+ home = "${dataDir}";
+ createHome = true;
+ };
+ users.groups.dnscrypt-wrapper = { };
+
+ security.polkit.extraConfig = ''
+ // Allow dnscrypt-wrapper user to restart dnscrypt-wrapper.service
+ polkit.addRule(function(action, subject) {
+ if (action.id == "org.freedesktop.systemd1.manage-units" &&
+ action.lookup("unit") == "dnscrypt-wrapper.service" &&
+ subject.user == "dnscrypt-wrapper") {
+ return polkit.Result.YES;
+ }
+ });
+ '';
+
+ systemd.services.dnscrypt-wrapper = {
+ description = "dnscrypt-wrapper daemon";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ path = [ pkgs.dnscrypt-wrapper ];
+
+ serviceConfig = {
+ User = "dnscrypt-wrapper";
+ WorkingDirectory = dataDir;
+ Restart = "on-failure";
+ ExecStart = "${pkgs.dnscrypt-wrapper}/bin/dnscrypt-wrapper ${toString daemonArgs}";
+ };
+
+ preStart = genKeys;
+ };
+
+
+ systemd.services.dnscrypt-wrapper-rotate = {
+ after = [ "network.target" ];
+ requires = [ "dnscrypt-wrapper.service" ];
+ description = "Rotates DNSCrypt wrapper keys if soon to expire";
+
+ path = with pkgs; [ dnscrypt-wrapper dnscrypt-proxy gawk ];
+ script = rotateKeys;
+ serviceConfig.User = "dnscrypt-wrapper";
+ };
+
+
+ systemd.timers.dnscrypt-wrapper-rotate = {
+ description = "Periodically check DNSCrypt wrapper keys for expiration";
+ wantedBy = [ "multi-user.target" ];
+
+ timerConfig = {
+ Unit = "dnscrypt-wrapper-rotate.service";
+ OnBootSec = "1min";
+ OnUnitActiveSec = cfg.keys.checkInterval * 60;
+ };
+ };
+
+ };
+}