at 23.11-pre 3.7 kB view raw
1{ config, lib, pkgs, ... }: 2 3let 4 inherit (lib) 5 concatStringsSep 6 mkEnableOption mkIf mkOption types; 7 8 cfg = config.services.https-dns-proxy; 9 10 providers = { 11 cloudflare = { 12 ips = [ "1.1.1.1" "1.0.0.1" ]; 13 url = "https://cloudflare-dns.com/dns-query"; 14 }; 15 google = { 16 ips = [ "8.8.8.8" "8.8.4.4" ]; 17 url = "https://dns.google/dns-query"; 18 }; 19 quad9 = { 20 ips = [ "9.9.9.9" "149.112.112.112" ]; 21 url = "https://dns.quad9.net/dns-query"; 22 }; 23 opendns = { 24 ips = [ "208.67.222.222" "208.67.220.220" ]; 25 url = "https://doh.opendns.com/dns-query"; 26 }; 27 custom = { 28 inherit (cfg.provider) ips url; 29 }; 30 }; 31 32 defaultProvider = "quad9"; 33 34 providerCfg = 35 concatStringsSep " " [ 36 "-b" 37 (concatStringsSep "," providers."${cfg.provider.kind}".ips) 38 "-r" 39 providers."${cfg.provider.kind}".url 40 ]; 41 42in 43{ 44 meta.maintainers = with lib.maintainers; [ peterhoeg ]; 45 46 ###### interface 47 48 options.services.https-dns-proxy = { 49 enable = mkEnableOption (lib.mdDoc "https-dns-proxy daemon"); 50 51 address = mkOption { 52 description = lib.mdDoc "The address on which to listen"; 53 type = types.str; 54 default = "127.0.0.1"; 55 }; 56 57 port = mkOption { 58 description = lib.mdDoc "The port on which to listen"; 59 type = types.port; 60 default = 5053; 61 }; 62 63 provider = { 64 kind = mkOption { 65 description = lib.mdDoc '' 66 The upstream provider to use or custom in case you do not trust any of 67 the predefined providers or just want to use your own. 68 69 The default is ${defaultProvider} and there are privacy and security 70 trade-offs when using any upstream provider. Please consider that 71 before using any of them. 72 73 Supported providers: ${concatStringsSep ", " (builtins.attrNames providers)} 74 75 If you pick the custom provider, you will need to provide the 76 bootstrap IP addresses as well as the resolver https URL. 77 ''; 78 type = types.enum (builtins.attrNames providers); 79 default = defaultProvider; 80 }; 81 82 ips = mkOption { 83 description = lib.mdDoc "The custom provider IPs"; 84 type = types.listOf types.str; 85 }; 86 87 url = mkOption { 88 description = lib.mdDoc "The custom provider URL"; 89 type = types.str; 90 }; 91 }; 92 93 preferIPv4 = mkOption { 94 description = lib.mdDoc '' 95 https_dns_proxy will by default use IPv6 and fail if it is not available. 96 To play it safe, we choose IPv4. 97 ''; 98 type = types.bool; 99 default = true; 100 }; 101 102 extraArgs = mkOption { 103 description = lib.mdDoc "Additional arguments to pass to the process."; 104 type = types.listOf types.str; 105 default = [ "-v" ]; 106 }; 107 }; 108 109 ###### implementation 110 111 config = lib.mkIf cfg.enable { 112 systemd.services.https-dns-proxy = { 113 description = "DNS to DNS over HTTPS (DoH) proxy"; 114 requires = [ "network.target" ]; 115 after = [ "network.target" ]; 116 wants = [ "nss-lookup.target" ]; 117 before = [ "nss-lookup.target" ]; 118 wantedBy = [ "multi-user.target" ]; 119 serviceConfig = rec { 120 Type = "exec"; 121 DynamicUser = true; 122 ProtectHome = "tmpfs"; 123 ExecStart = lib.concatStringsSep " " ( 124 [ 125 (lib.getExe pkgs.https-dns-proxy) 126 "-a ${toString cfg.address}" 127 "-p ${toString cfg.port}" 128 "-l -" 129 providerCfg 130 ] 131 ++ lib.optional cfg.preferIPv4 "-4" 132 ++ cfg.extraArgs 133 ); 134 Restart = "on-failure"; 135 }; 136 }; 137 }; 138}