at 21.11-pre 7.5 kB view raw
1{ config, lib, pkgs, ...}: 2 3with lib; 4 5let 6 cfg = config.services.stubby; 7 8 fallbacks = concatMapStringsSep "\n " (x: "- ${x}") cfg.fallbackProtocols; 9 listeners = concatMapStringsSep "\n " (x: "- ${x}") cfg.listenAddresses; 10 11 # By default, the recursive resolvers maintained by the getdns 12 # project itself are enabled. More information about both getdns's servers, 13 # as well as third party options for upstream resolvers, can be found here: 14 # https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Test+Servers 15 # 16 # You can override these values by supplying a yaml-formatted array of your 17 # preferred upstream resolvers in the following format: 18 # 19 # 106 # - address_data: IPv4 or IPv6 address of the upstream 20 # port: Port for UDP/TCP (default is 53) 21 # tls_auth_name: Authentication domain name checked against the server 22 # certificate 23 # tls_pubkey_pinset: An SPKI pinset verified against the keys in the server 24 # certificate 25 # - digest: Only "sha256" is currently supported 26 # value: Base64 encoded value of the sha256 fingerprint of the public 27 # key 28 # tls_port: Port for TLS (default is 853) 29 30 defaultUpstream = '' 31 - address_data: 145.100.185.15 32 tls_auth_name: "dnsovertls.sinodun.com" 33 tls_pubkey_pinset: 34 - digest: "sha256" 35 value: 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4= 36 - address_data: 145.100.185.16 37 tls_auth_name: "dnsovertls1.sinodun.com" 38 tls_pubkey_pinset: 39 - digest: "sha256" 40 value: cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA= 41 - address_data: 185.49.141.37 42 tls_auth_name: "getdnsapi.net" 43 tls_pubkey_pinset: 44 - digest: "sha256" 45 value: foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q= 46 - address_data: 2001:610:1:40ba:145:100:185:15 47 tls_auth_name: "dnsovertls.sinodun.com" 48 tls_pubkey_pinset: 49 - digest: "sha256" 50 value: 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4= 51 - address_data: 2001:610:1:40ba:145:100:185:16 52 tls_auth_name: "dnsovertls1.sinodun.com" 53 tls_pubkey_pinset: 54 - digest: "sha256" 55 value: cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA= 56 - address_data: 2a04:b900:0:100::38 57 tls_auth_name: "getdnsapi.net" 58 tls_pubkey_pinset: 59 - digest: "sha256" 60 value: foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q= 61 ''; 62 63 # Resolution type is not changeable here because it is required per the 64 # stubby documentation: 65 # 66 # "resolution_type: Work in stub mode only (not recursive mode) - required for Stubby 67 # operation." 68 # 69 # https://dnsprivacy.org/wiki/display/DP/Configuring+Stubby 70 71 confFile = pkgs.writeText "stubby.yml" '' 72 resolution_type: GETDNS_RESOLUTION_STUB 73 dns_transport_list: 74 ${fallbacks} 75 appdata_dir: "/var/cache/stubby" 76 tls_authentication: ${cfg.authenticationMode} 77 tls_query_padding_blocksize: ${toString cfg.queryPaddingBlocksize} 78 edns_client_subnet_private: ${if cfg.subnetPrivate then "1" else "0"} 79 idle_timeout: ${toString cfg.idleTimeout} 80 listen_addresses: 81 ${listeners} 82 round_robin_upstreams: ${if cfg.roundRobinUpstreams then "1" else "0"} 83 ${cfg.extraConfig} 84 upstream_recursive_servers: 85 ${cfg.upstreamServers} 86 ''; 87in 88 89{ 90 options = { 91 services.stubby = { 92 93 enable = mkEnableOption "Stubby DNS resolver"; 94 95 fallbackProtocols = mkOption { 96 default = [ "GETDNS_TRANSPORT_TLS" ]; 97 type = with types; listOf (enum [ 98 "GETDNS_TRANSPORT_TLS" 99 "GETDNS_TRANSPORT_TCP" 100 "GETDNS_TRANSPORT_UDP" 101 ]); 102 description = '' 103 Ordered list composed of one or more transport protocols. 104 Strict mode should only use <literal>GETDNS_TRANSPORT_TLS</literal>. 105 Other options are <literal>GETDNS_TRANSPORT_UDP</literal> and 106 <literal>GETDNS_TRANSPORT_TCP</literal>. 107 ''; 108 }; 109 110 authenticationMode = mkOption { 111 default = "GETDNS_AUTHENTICATION_REQUIRED"; 112 type = types.enum [ 113 "GETDNS_AUTHENTICATION_REQUIRED" 114 "GETDNS_AUTHENTICATION_NONE" 115 ]; 116 description = '' 117 Selects the Strict or Opportunistic usage profile. 118 For strict, set to <literal>GETDNS_AUTHENTICATION_REQUIRED</literal>. 119 for opportunistic, use <literal>GETDNS_AUTHENTICATION_NONE</literal>. 120 ''; 121 }; 122 123 queryPaddingBlocksize = mkOption { 124 default = 128; 125 type = types.int; 126 description = '' 127 EDNS0 option to pad the size of the DNS query to the given blocksize. 128 ''; 129 }; 130 131 subnetPrivate = mkOption { 132 default = true; 133 type = types.bool; 134 description = '' 135 EDNS0 option for ECS client privacy. Default is 136 <literal>true</literal>. If set, this option prevents the client 137 subnet from being sent to authoritative nameservers. 138 ''; 139 }; 140 141 idleTimeout = mkOption { 142 default = 10000; 143 type = types.int; 144 description = "EDNS0 option for keepalive idle timeout expressed in 145 milliseconds."; 146 }; 147 148 listenAddresses = mkOption { 149 default = [ "127.0.0.1" "0::1" ]; 150 type = with types; listOf str; 151 description = '' 152 Sets the listen address for the stubby daemon. 153 Uses port 53 by default. 154 Ise IP@port to specify a different port. 155 ''; 156 }; 157 158 roundRobinUpstreams = mkOption { 159 default = true; 160 type = types.bool; 161 description = '' 162 Instructs stubby to distribute queries across all available name 163 servers. Default is <literal>true</literal>. Set to 164 <literal>false</literal> in order to use the first available. 165 ''; 166 }; 167 168 upstreamServers = mkOption { 169 default = defaultUpstream; 170 type = types.lines; 171 description = '' 172 Replace default upstreams. See <citerefentry><refentrytitle>stubby 173 </refentrytitle><manvolnum>1</manvolnum></citerefentry> for an 174 example of the entry formatting. In Strict mode, at least one of the 175 following settings must be supplied for each nameserver: 176 <literal>tls_auth_name</literal> or 177 <literal>tls_pubkey_pinset</literal>. 178 ''; 179 }; 180 181 debugLogging = mkOption { 182 default = false; 183 type = types.bool; 184 description = "Enable or disable debug level logging."; 185 }; 186 187 extraConfig = mkOption { 188 default = ""; 189 type = types.lines; 190 description = '' 191 Add additional configuration options. see <citerefentry> 192 <refentrytitle>stubby</refentrytitle><manvolnum>1</manvolnum> 193 </citerefentry>for more options. 194 ''; 195 }; 196 }; 197 }; 198 199 config = mkIf cfg.enable { 200 environment.systemPackages = [ pkgs.stubby ]; 201 systemd.services.stubby = { 202 description = "Stubby local DNS resolver"; 203 after = [ "network.target" ]; 204 before = [ "nss-lookup.target" ]; 205 wantedBy = [ "multi-user.target" ]; 206 207 serviceConfig = { 208 Type = "notify"; 209 AmbientCapabilities = "CAP_NET_BIND_SERVICE"; 210 CapabilityBoundingSet = "CAP_NET_BIND_SERVICE"; 211 ExecStart = "${pkgs.stubby}/bin/stubby -C ${confFile} ${optionalString cfg.debugLogging "-l"}"; 212 DynamicUser = true; 213 CacheDirectory = "stubby"; 214 }; 215 }; 216 }; 217}