├── .env ├── README.md ├── dnscrypt-proxy.toml ├── docker-compose.yml ├── docker-stack.yml ├── pdnsd.conf └── upgrade.sh /.env: -------------------------------------------------------------------------------- 1 | #custom listen 2 | #HOST_SERVICE_LISTEN=127.0.0.1:53 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | dnscrypt docker compose/stack. 2 | 3 | ### compose 4 | 5 | * customize listen in .env file. 6 | * supported on Linux/Windows/MacOS. 7 | 8 | ```bash 9 | docker-compose up -d 10 | ``` 11 | 12 | ### stack 13 | 14 | supported on Linux(because of host mode network) 15 | 16 | ```bash 17 | docker stack deploy -c ./docker-stack.yml dnscrypt 18 | ``` 19 | 20 | Change You first dns server to 127.0.0.1 and enjoy. 21 | -------------------------------------------------------------------------------- /dnscrypt-proxy.toml: -------------------------------------------------------------------------------- 1 | 2 | ############################################## 3 | # # 4 | # dnscrypt-proxy configuration # 5 | # # 6 | ############################################## 7 | 8 | ## This is an example configuration file. 9 | ## You should adjust it to your needs, and save it as "dnscrypt-proxy.toml" 10 | ## 11 | ## Online documentation is available here: https://dnscrypt.info/doc 12 | 13 | 14 | 15 | ################################## 16 | # Global settings # 17 | ################################## 18 | 19 | ## List of servers to use 20 | ## 21 | ## Servers from the "public-resolvers" source (see down below) can 22 | ## be viewed here: https://dnscrypt.info/public-servers 23 | ## 24 | ## If this line is commented, all registered servers matching the require_* filters 25 | ## will be used. 26 | ## 27 | ## The proxy will automatically pick the fastest, working servers from the list. 28 | ## Remove the leading # first to enable this; lines starting with # are ignored. 29 | 30 | server_names = ['google', 'cloudflare', 'powerdns-doh', 'quad9-dnscrypt-ip4-nofilter-alt'] 31 | 32 | 33 | ## List of local addresses and ports to listen to. Can be IPv4 and/or IPv6. 34 | ## Note: When using systemd socket activation, choose an empty set (i.e. [] ). 35 | 36 | listen_addresses = ['0.0.0.0:5454'] 37 | 38 | 39 | ## Maximum number of simultaneous client connections to accept 40 | 41 | max_clients = 250 42 | 43 | 44 | ## Require servers (from static + remote sources) to satisfy specific properties 45 | 46 | # Use servers reachable over IPv4 47 | ipv4_servers = true 48 | 49 | # Use servers reachable over IPv6 -- Do not enable if you don't have IPv6 connectivity 50 | ipv6_servers = false 51 | 52 | # Use servers implementing the DNSCrypt protocol 53 | dnscrypt_servers = true 54 | 55 | # Use servers implementing the DNS-over-HTTPS protocol 56 | doh_servers = true 57 | 58 | 59 | ## Require servers defined by remote sources to satisfy specific properties 60 | 61 | # Server must support DNS security extensions (DNSSEC) 62 | require_dnssec = false 63 | 64 | # Server must not log user queries (declarative) 65 | require_nolog = true 66 | 67 | # Server must not enforce its own blacklist (for parental control, ads blocking...) 68 | require_nofilter = true 69 | 70 | 71 | ## Always use TCP to connect to upstream servers. 72 | ## This can be can be useful if you need to route everything through Tor. 73 | ## Otherwise, leave this to `false`, as it doesn't improve security 74 | ## (dnscrypt-proxy will always encrypt everything even using UDP), and can 75 | ## only increase latency. 76 | 77 | force_tcp = false 78 | 79 | 80 | ## HTTP / SOCKS proxy 81 | ## Uncomment the following line to route all TCP connections to a local Tor node 82 | ## Tor doesn't support UDP, so set `force_tcp` to `true` as well. 83 | 84 | # proxy = "socks5://127.0.0.1:9050" 85 | 86 | 87 | 88 | ## How long a DNS query will wait for a response, in milliseconds 89 | 90 | timeout = 2500 91 | 92 | 93 | ## Keepalive for HTTP (HTTPS, HTTP/2) queries, in seconds 94 | 95 | keepalive = 30 96 | 97 | 98 | ## Load-balancing strategy: 'p2' (default), 'ph', 'fastest' or 'random' 99 | 100 | # lb_strategy = 'p2' 101 | 102 | 103 | ## Log level (0-6, default: 2 - 0 is very verbose, 6 only contains fatal errors) 104 | 105 | log_level = 0 106 | 107 | 108 | ## log file for the application 109 | 110 | # log_file = 'dnscrypt-proxy.log' 111 | 112 | 113 | ## Use the system logger (syslog on Unix, Event Log on Windows) 114 | 115 | # use_syslog = true 116 | 117 | 118 | ## Delay, in minutes, after which certificates are reloaded 119 | 120 | cert_refresh_delay = 240 121 | 122 | 123 | ## DNSCrypt: Create a new, unique key for every single DNS query 124 | ## This may improve privacy but can also have a significant impact on CPU usage 125 | ## Only enable if you don't have a lot of network load 126 | 127 | # dnscrypt_ephemeral_keys = false 128 | 129 | 130 | ## DoH: Disable TLS session tickets - increases privacy but also latency 131 | 132 | # tls_disable_session_tickets = false 133 | 134 | 135 | ## DoH: Use a specific cipher suite instead of the server preference 136 | ## 49199 = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 137 | ## 49195 = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 138 | ## 52392 = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 139 | ## 52393 = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 140 | ## 141 | ## On non-Intel CPUs such as MIPS routers and ARM systems (Android, Raspberry Pi...), 142 | ## the following suite improves performance. 143 | ## This may also help on Intel CPUs running 32-bit operating systems. 144 | ## 145 | ## Keep tls_cipher_suite empty if you have issues fetching sources or 146 | ## connecting to some DoH servers. Google and Cloudflare are fine with it. 147 | 148 | # tls_cipher_suite = [52392, 49199] 149 | 150 | 151 | ## Fallback resolver 152 | ## This is a normal, non-encrypted DNS resolver, that will be only used 153 | ## for one-shot queries when retrieving the initial resolvers list, and 154 | ## only if the system DNS configuration doesn't work. 155 | ## No user application queries will ever be leaked through this resolver, 156 | ## and it will not be used after IP addresses of resolvers URLs have been found. 157 | ## It will never be used if lists have already been cached, and if stamps 158 | ## don't include host names without IP addresses. 159 | ## It will not be used if the configured system DNS works. 160 | ## A resolver supporting DNSSEC is recommended. This may become mandatory. 161 | ## 162 | ## People in China may need to use 114.114.114.114:53 here. 163 | ## Other popular options include 8.8.8.8 and 1.1.1.1. 164 | 165 | fallback_resolver = '223.5.5.5:53' 166 | 167 | 168 | ## Never let dnscrypt-proxy try to use the system DNS settings; 169 | ## unconditionally use the fallback resolver. 170 | 171 | ignore_system_dns = true 172 | 173 | 174 | ## Maximum time (in seconds) to wait for network connectivity before 175 | ## initializing the proxy. 176 | ## Useful if the proxy is automatically started at boot, and network 177 | ## connectivity is not guaranteed to be immediately available. 178 | ## Use 0 to disable. 179 | 180 | netprobe_timeout = 30 181 | 182 | 183 | ## Automatic log files rotation 184 | 185 | # Maximum log files size in MB 186 | log_files_max_size = 10 187 | 188 | # How long to keep backup files, in days 189 | log_files_max_age = 7 190 | 191 | # Maximum log files backups to keep (or 0 to keep all backups) 192 | log_files_max_backups = 1 193 | 194 | 195 | 196 | ######################### 197 | # Filters # 198 | ######################### 199 | 200 | ## Immediately respond to IPv6-related queries with an empty response 201 | ## This makes things faster when there is no IPv6 connectivity, but can 202 | ## also cause reliability issues with some stub resolvers. 203 | ## Do not enable if you added a validating resolver such as dnsmasq in front 204 | ## of the proxy. 205 | 206 | block_ipv6 = false 207 | 208 | 209 | 210 | ################################################################################## 211 | # Route queries for specific domains to a dedicated set of servers # 212 | ################################################################################## 213 | 214 | ## Example map entries (one entry per line): 215 | ## example.com 9.9.9.9 216 | ## example.net 9.9.9.9,8.8.8.8,1.1.1.1 217 | 218 | # forwarding_rules = 'forwarding-rules.txt' 219 | 220 | 221 | 222 | ############################### 223 | # Cloaking rules # 224 | ############################### 225 | 226 | ## Cloaking returns a predefined address for a specific name. 227 | ## In addition to acting as a HOSTS file, it can also return the IP address 228 | ## of a different name. It will also do CNAME flattening. 229 | ## 230 | ## Example map entries (one entry per line) 231 | ## example.com 10.1.1.1 232 | ## www.google.com forcesafesearch.google.com 233 | 234 | # cloaking_rules = 'cloaking-rules.txt' 235 | 236 | 237 | 238 | ########################### 239 | # DNS cache # 240 | ########################### 241 | 242 | ## Enable a DNS cache to reduce latency and outgoing traffic 243 | 244 | cache = true 245 | 246 | 247 | ## Cache size 248 | 249 | cache_size = 512 250 | 251 | 252 | ## Minimum TTL for cached entries 253 | 254 | cache_min_ttl = 600 255 | 256 | 257 | ## Maximum TTL for cached entries 258 | 259 | cache_max_ttl = 86400 260 | 261 | 262 | ## Minimum TTL for negatively cached entries 263 | 264 | cache_neg_min_ttl = 60 265 | 266 | 267 | ## Maximum TTL for negatively cached entries 268 | 269 | cache_neg_max_ttl = 600 270 | 271 | 272 | 273 | ############################### 274 | # Query logging # 275 | ############################### 276 | 277 | ## Log client queries to a file 278 | 279 | [query_log] 280 | 281 | ## Path to the query log file (absolute, or relative to the same directory as the executable file) 282 | 283 | # file = 'query.log' 284 | 285 | 286 | ## Query log format (currently supported: tsv and ltsv) 287 | 288 | format = 'tsv' 289 | 290 | 291 | ## Do not log these query types, to reduce verbosity. Keep empty to log everything. 292 | 293 | # ignored_qtypes = ['DNSKEY', 'NS'] 294 | 295 | 296 | 297 | ############################################ 298 | # Suspicious queries logging # 299 | ############################################ 300 | 301 | ## Log queries for nonexistent zones 302 | ## These queries can reveal the presence of malware, broken/obsolete applications, 303 | ## and devices signaling their presence to 3rd parties. 304 | 305 | [nx_log] 306 | 307 | ## Path to the query log file (absolute, or relative to the same directory as the executable file) 308 | 309 | # file = 'nx.log' 310 | 311 | 312 | ## Query log format (currently supported: tsv and ltsv) 313 | 314 | format = 'tsv' 315 | 316 | 317 | 318 | ###################################################### 319 | # Pattern-based blocking (blacklists) # 320 | ###################################################### 321 | 322 | ## Blacklists are made of one pattern per line. Example of valid patterns: 323 | ## 324 | ## example.com 325 | ## =example.com 326 | ## *sex* 327 | ## ads.* 328 | ## ads*.example.* 329 | ## ads*.example[0-9]*.com 330 | ## 331 | ## Example blacklist files can be found at https://download.dnscrypt.info/blacklists/ 332 | ## A script to build blacklists from public feeds can be found in the 333 | ## `utils/generate-domains-blacklists` directory of the dnscrypt-proxy source code. 334 | 335 | [blacklist] 336 | 337 | ## Path to the file of blocking rules (absolute, or relative to the same directory as the executable file) 338 | 339 | # blacklist_file = 'blacklist.txt' 340 | 341 | 342 | ## Optional path to a file logging blocked queries 343 | 344 | # log_file = 'blocked.log' 345 | 346 | 347 | ## Optional log format: tsv or ltsv (default: tsv) 348 | 349 | # log_format = 'tsv' 350 | 351 | 352 | 353 | ########################################################### 354 | # Pattern-based IP blocking (IP blacklists) # 355 | ########################################################### 356 | 357 | ## IP blacklists are made of one pattern per line. Example of valid patterns: 358 | ## 359 | ## 127.* 360 | ## fe80:abcd:* 361 | ## 192.168.1.4 362 | 363 | [ip_blacklist] 364 | 365 | ## Path to the file of blocking rules (absolute, or relative to the same directory as the executable file) 366 | 367 | # blacklist_file = 'ip-blacklist.txt' 368 | 369 | 370 | ## Optional path to a file logging blocked queries 371 | 372 | # log_file = 'ip-blocked.log' 373 | 374 | 375 | ## Optional log format: tsv or ltsv (default: tsv) 376 | 377 | # log_format = 'tsv' 378 | 379 | 380 | 381 | ###################################################### 382 | # Pattern-based whitelisting (blacklists bypass) # 383 | ###################################################### 384 | 385 | ## Whitelists support the same patterns as blacklists 386 | ## If a name matches a whitelist entry, the corresponding session 387 | ## will bypass names and IP filters. 388 | ## 389 | ## Time-based rules are also supported to make some websites only accessible at specific times of the day. 390 | 391 | [whitelist] 392 | 393 | ## Path to the file of whitelisting rules (absolute, or relative to the same directory as the executable file) 394 | 395 | # whitelist_file = 'whitelist.txt' 396 | 397 | 398 | ## Optional path to a file logging whitelisted queries 399 | 400 | # log_file = 'whitelisted.log' 401 | 402 | 403 | ## Optional log format: tsv or ltsv (default: tsv) 404 | 405 | # log_format = 'tsv' 406 | 407 | 408 | 409 | ########################################## 410 | # Time access restrictions # 411 | ########################################## 412 | 413 | ## One or more weekly schedules can be defined here. 414 | ## Patterns in the name-based blocklist can optionally be followed with @schedule_name 415 | ## to apply the pattern 'schedule_name' only when it matches a time range of that schedule. 416 | ## 417 | ## For example, the following rule in a blacklist file: 418 | ## *.youtube.* @time-to-sleep 419 | ## would block access to YouTube only during the days, and period of the days 420 | ## define by the 'time-to-sleep' schedule. 421 | ## 422 | ## {after='21:00', before= '7:00'} matches 0:00-7:00 and 21:00-0:00 423 | ## {after= '9:00', before='18:00'} matches 9:00-18:00 424 | 425 | [schedules] 426 | 427 | # [schedules.'time-to-sleep'] 428 | # mon = [{after='21:00', before='7:00'}] 429 | # tue = [{after='21:00', before='7:00'}] 430 | # wed = [{after='21:00', before='7:00'}] 431 | # thu = [{after='21:00', before='7:00'}] 432 | # fri = [{after='23:00', before='7:00'}] 433 | # sat = [{after='23:00', before='7:00'}] 434 | # sun = [{after='21:00', before='7:00'}] 435 | 436 | # [schedules.'work'] 437 | # mon = [{after='9:00', before='18:00'}] 438 | # tue = [{after='9:00', before='18:00'}] 439 | # wed = [{after='9:00', before='18:00'}] 440 | # thu = [{after='9:00', before='18:00'}] 441 | # fri = [{after='9:00', before='17:00'}] 442 | 443 | 444 | 445 | ######################### 446 | # Servers # 447 | ######################### 448 | 449 | ## Remote lists of available servers 450 | ## Multiple sources can be used simultaneously, but every source 451 | ## requires a dedicated cache file. 452 | ## 453 | ## Refer to the documentation for URLs of public sources. 454 | ## 455 | ## A prefix can be prepended to server names in order to 456 | ## avoid collisions if different sources share the same for 457 | ## different servers. In that case, names listed in `server_names` 458 | ## must include the prefixes. 459 | ## 460 | ## If the `urls` property is missing, cache files and valid signatures 461 | ## must be already present; This doesn't prevent these cache files from 462 | ## expiring after `refresh_delay` hours. 463 | 464 | [sources] 465 | 466 | ## An example of a remote source from https://github.com/DNSCrypt/dnscrypt-resolvers 467 | 468 | [sources.'public-resolvers'] 469 | urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v2/public-resolvers.md', 'https://download.dnscrypt.info/resolvers-list/v2/public-resolvers.md'] 470 | cache_file = 'public-resolvers.md' 471 | minisign_key = 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3' 472 | refresh_delay = 72 473 | prefix = '' 474 | 475 | ## Another example source, with resolvers censoring some websites not appropriate for children 476 | ## This is a subset of the `public-resolvers` list, so enabling both is useless 477 | 478 | # [sources.'parental-control'] 479 | # urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v2/parental-control.md', 'https://download.dnscrypt.info/resolvers-list/v2/parental-control.md'] 480 | # cache_file = 'parental-control.md' 481 | # minisign_key = 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3' 482 | 483 | 484 | 485 | ## Optional, local, static list of additional servers 486 | ## Mostly useful for testing your own servers. 487 | 488 | [static] 489 | 490 | # [static.'google'] 491 | # stamp = 'sdns://AgUAAAAAAAAAAAAOZG5zLmdvb2dsZS5jb20NL2V4cGVyaW1lbnRhbA' 492 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "2.1" 2 | x-logging: 3 | &default-logging 4 | driver: "json-file" 5 | options: 6 | max-size: "200k" 7 | max-file: "10" 8 | 9 | services: 10 | greendns: 11 | container_name: greendns 12 | image: faicker/greendns:latest 13 | restart: unless-stopped 14 | ports: 15 | - "${DNS_LISTEN:-127.0.0.1:53}:5353/udp" 16 | environment: 17 | - LDS=127.0.0.1:5453 18 | - RDS=127.0.0.1:5454 19 | - CACHE=true 20 | - RFC1918=true 21 | - LISTEN=0.0.0.0:5353 22 | logging: *default-logging 23 | 24 | pdnsd: 25 | container_name: pdnsd 26 | image: faicker/pdnsd:latest 27 | volumes: 28 | - ./pdnsd.conf:/etc/pdnsd.conf 29 | restart: unless-stopped 30 | network_mode: "service:greendns" 31 | logging: *default-logging 32 | 33 | dnscrypt-proxy: 34 | container_name: dnscrypt-proxy 35 | image: faicker/dnscrypt-proxy-2:latest 36 | volumes: 37 | - ./dnscrypt-proxy.toml:/config/dnscrypt-proxy.toml:ro 38 | restart: unless-stopped 39 | network_mode: "service:greendns" 40 | logging: *default-logging 41 | 42 | -------------------------------------------------------------------------------- /docker-stack.yml: -------------------------------------------------------------------------------- 1 | version: "3.5" 2 | x-logging: 3 | &default-logging 4 | driver: "json-file" 5 | options: 6 | max-size: "200k" 7 | max-file: "10" 8 | configs: 9 | dnscrypt-proxy: 10 | name: dnscrypt-proxy-${DNSCRYPT-PROXY_CONFIG_VERSION:-0} 11 | file: ./dnscrypt-proxy.toml 12 | pdnsd: 13 | name: pdnsd-${PDNSD_CONFIG_VERSION:-0} 14 | file: ./pdnsd.conf 15 | networks: 16 | hostnet: 17 | external: true 18 | name: host 19 | 20 | services: 21 | greendns: 22 | image: faicker/greendns:latest 23 | depends_on: 24 | - dnscrypt-proxy-2 25 | - pdnsd 26 | networks: 27 | hostnet: {} 28 | deploy: 29 | replicas: 1 30 | restart_policy: 31 | condition: any 32 | logging: *default-logging 33 | env_file: .env 34 | 35 | dnscrypt-proxy-2: 36 | image: faicker/dnscrypt-proxy-2:latest 37 | configs: 38 | - source: dnscrypt-proxy 39 | target: /config/dnscrypt-proxy.toml 40 | mode: 0440 41 | networks: 42 | hostnet: {} 43 | deploy: 44 | replicas: 1 45 | restart_policy: 46 | condition: any 47 | logging: *default-logging 48 | 49 | pdnsd: 50 | image: vimagick/pdnsd:latest 51 | configs: 52 | - source: pdnsd 53 | target: /etc/pdnsd.conf 54 | mode: 0440 55 | networks: 56 | hostnet: {} 57 | deploy: 58 | replicas: 1 59 | restart_policy: 60 | condition: any 61 | logging: *default-logging 62 | -------------------------------------------------------------------------------- /pdnsd.conf: -------------------------------------------------------------------------------- 1 | global { 2 | perm_cache=204800; 3 | cache_dir="/var/cache/pdnsd"; 4 | run_as="pdnsd"; 5 | server_port=5453; 6 | server_ip = any; 7 | status_ctl = on; 8 | timeout=5; 9 | neg_domain_pol=on; 10 | } 11 | 12 | server { 13 | label="lds"; 14 | ip = 223.5.5.5, 114.114.114.114; 15 | randomize_servers=on; 16 | proxy_only=on; 17 | timeout=2; 18 | purge_cache=off; 19 | } 20 | -------------------------------------------------------------------------------- /upgrade.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # for docker stack 3 | # FIXME. both updated(pdnsd and dnscrypt-proxy-2) if one config changed. 4 | 5 | service_name="$1" 6 | if [[ -z $service_name ]]; then 7 | echo "usage: $0 service_name" 8 | exit 1 9 | fi 10 | 11 | config_name=$(docker service inspect --format '{{(index .Spec.TaskTemplate.ContainerSpec.Configs 0).ConfigName }}' $service_name) 12 | 13 | if [[ -z "$config_name" ]]; then 14 | echo "get service $service_name first config failed" 15 | exit 1 16 | fi 17 | now_version=${config_name##*-} 18 | new_version=$((now_version+1)) 19 | echo "version, now=$now_version, new=$new_version" 20 | 21 | name=$(echo ${config_name%%-*} | tr 'a-z' 'A-Z') 22 | eval "${name}_CONFIG_VERSION=$new_version" 23 | export ${name}_CONFIG_VERSION 24 | docker stack deploy -c ./dnscrypt.yml dnscrypt 25 | if [[ $? -eq 0 ]]; then 26 | docker config rm $config_name 27 | fi 28 | --------------------------------------------------------------------------------