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