DNSCrypt : how to pick the best server

Just wanted to share my experience with setting up DNSCrypt (a.k.a. "dnscrypt-proxy" in LEDE) in case anyone has similar questions/problems along the way.

By default, LEDE is configured to use "fvz-anyone" server, but because it does not have a valid certificate, the syslog is flooded with the following messages of DNSCrypt trying to refetch a valid certificate:

Wed Feb  7 22:01:24 2018 daemon.err dnscrypt-proxy[8949]: dnscrypt-proxy Unable to retrieve server certificates
Wed Feb  7 22:01:25 2018 daemon.info dnscrypt-proxy[8949]: dnscrypt-proxy Refetching server certificates

An easy fix is to switch to another server (e.g. "cisco"), but depending on your location, "cisco" might not be the fastest choice. And since you want DNS requests to be resolved quickly, you need to measure which servers provide you with the best options. A quick search on the internet showed that we're in luck - Christian Hermann (https://github.com/bitbeans) had posted a nice little tool to measure connections to all the DNS severs in the DNSCrypt's csv-file and report them back with all the metrics: https://github.com/bitbeans/dnscrypt-measurement
Not only it reports the fastest servers first, it also provides all important metrics for those servers, so you can pick what you're comfortable with: NoLogs, DNSSEC, Valid Certificate

The only downside of this nifty utility is that you need Windows machine to run it. :slight_smile:

For me, the "Anatomical DNS, NoLogs: True, DNSSEC: True, Certificate Valid: True" was the best choice.

Another problem that stumbled upon was DNSCrypt refusing to start due to the low entropy of the router. It would print the following message in the syslog:

This system doesn't provide enough entropy to quickly generate high-quality random numbers
Installing the rng-utils/rng-tools or haveged packages may help.
On virtualized Linux environments, also consider using virtio-rng.
The service will not start until enough entropy has been collected.

A simple way to check your machine's entropy is by getting the number from "/proc/sys/kernel/random/entropy_avail" with "cat". Mine was at around 350, so I had install "rng-tools":

opkg install rng-tools
# Configure rngd with the watermark of 1000:
uci set system.@rngd[0].fill_watermark=1000
uci set system.@rngd[0].enabled=1
uci commit
service rngd enable
service rngd start

The above configuration change will be reflected at the "/etc/config/system" file. Once started, you can see it run:

lede > ps w | grep rng
9340 root       984 S    /sbin/rngd -f -r /dev/urandom -W 1000

Hope this helps someone.

Enjoy!

UPDATE 02/11/18: Below suggestion is incorrect because as soon as DNSCrypt-proxy goes down, the dnsmasq starts using your ISP for name resolution stored in file "/tmp/resolv.conf.auto". The only way I was able to combine local names lookup with DNSCrypt-proxy is by creating my own file /etc/resolv.conf that gets used by dnsmasq:

search lan
nameserver 127.0.0.1

Please let me know if there is another way to do it.


Also of note is that all guides for setting up DNSCrypt (e.g. https://wiki.openwrt.org/inbox/dnscrypt) instruct to disable /etc/resolv.conf file by dnsmasq with:

option noresolv 1

however, this is incorrect because it leads to incorrect file /tmp/resolv.conf being used by local processes that need name resolution (e.g. "wget" or "ping").

The current LEDE code in /etc/init.d/dnsmasq properly assembles the file /tmp/resolv.conf to point to the localhost and be able to properly resolve local network names. So, set the option "option noresolv 0" and make sure that the resolv.conf is not leaking your DNS traffic to your ISP:

lede > cat /etc/resolv.conf
search lan
nameserver 127.0.0.1

LEDE should update to dnscrypt-proxy v2.

v1 has reached EOL, and the resolvers list for v1 is not updated any more.
v2 automatically picks the best server, no additional tools needed.

3 Likes

That's awesome Frank! Looking forward to switching to it with the next Lede/OpenWRT release!

Is there a way to specify parameters for servers that should only be considered from the list? For example, I only want to connect to a server with NoLogs=true, DNSSEC=true and with a Valid Certificate.

Sure, the following filters can be set in the configuration file in order to only pick matching servers:

ipv4_servers = true
ipv6_servers = false
require_dnssec = false
require_nolog = false
require_nofilter = false
dnscrypt_servers = true
doh_servers = true

Also, dnscrypt-proxy -list will display the list of servers after having applied these filters, whereas -list-all displays all of them. You can add -json to have a nice, parsable JSON output.

3 Likes

I've had the same problem as the OP with invalid server certificates. I've set up multiple dnscrypt resolvers as described in the OpenWrt wiki.
While we wait for dnscrypt v2 support: I want to make sure that dnsmasq falls back to ISP servers if dnscrypt fails, because in my absence, I'd rather have unencrypted DNS than internet outages for the other users of my networks.

So if my config looks like this:

list server '127.0.0.1#5353'
list server '127.0.0.1#5454'
list server '/pool.ntp.org/208.67.222.222'
option noresolv 0
option resolvfile '/etc/resolv-custom.conf'

with resolv-custom.conf:

options timeout:1
nameserver ISP_DNS
nameserver ISP_DNS_IPv6

Does dnsmasq use all of these randomly or does it always try the explicitly specified dnscrypt-proxy ones first? Do I need dnsmasq's strict-order option? The dnsmasq manpage isn't clear about how manually specified upstream servers are handled, if the resolv file contains nameservers.

Edit: The extended test on https://www.dnsleaktest.com/ confirms that I need:

option strictorder '1'

Otherwise, dnsmasq chooses one of the (likely faster) ISP servers.

A simple way to check your machine’s entropy is by getting the number from “/proc/sys/kernel/random/entropy_avail” with “cat”. Mine was at around 350, so I had install “rng-tools”:

Be careful with this - note how it's running, it's using urandom as a source (a source of pseudo random numbers that is guaranteed not to block) - so essentially you are feeding the kernel from a source that is ultimately generated from the (probably fairly low level) randomness it already has (which was the source of your original problem). So it gets over the hurdle of being able to run dnscrypt - but you are very far from having a good source of randomness locally.

You could run haveged - which would marginally improve things a little, as it generates randomness from timing differences in the CPU.

You can already install manually DNSCrypt-Proxy v2.
I have it running on my LEDE 17.01 build for a few days now. No issues. The servers are chosen based on lowest latency. If one of them stops working, another takes it place.

@r43k3n I also want to move from dnscrypt-proxy v1.9.4 to v2, can you share the setup and configuration details on how you achieved this? Furthermore, does the (now unsupported) luci companion package still work with the newer version, I am guessing not.

I don't use LuCI so I won't be able to help with the LuCI companion you mentioned.
I modified heavily the original installation tutorial for v2 so I could keep both v1 and v2 installed at the same time. If you'd like to replace v1 with v2 permanently you might want to make necessary changes to the instructions I'll post below.

I'm using Windows 7 so the tutorial will be based on that particular OS.

  1. Download the DNSCrypt-Proxy Releases package for your router. Make sure to match the package with your router's CPU architecture.
    I'm using TP-Link Archer C2600 (ipq806x) so the correct package for this platform is dnscrypt-proxy-linux_arm-2.0.X.tar.gz

  2. Extract the .zip package to a new folder. For reference I'll name it dnscrypt-proxy-v2-binary.

  3. Change the name of dnscrypt-proxy to dnscrypt-proxy-v2

  4. The binary file is around ~7 MB, after compression the binary shrinks to around ~1,6 MB. To compress the file, download UPX and extract it to dnscrypt-proxy-v2-binary folder.

  5. Open CMD inside the dnscrypt-proxy-v2-binary folder and enter the command posted below. Make sure you use the correct name of binary file.
    upx --lzma dnscrypt-proxy-v2

  6. Using SCP protocol (ex. WinSCP) copy compressed dnscrypt-proxy-v2 binary to /usr/sbin on your router.

  7. Open terminal, connect to your router and set the correct permissions for the binary file.
    chmod 755 /usr/sbin/dnscrypt-proxy-v2

  8. Using SCP, on your router:
    a) create dnscrypt-proxy-v2 folder inside /etc/
    b) create example folder inside dnscrypt-proxy-v2 to have a backup of original configuration files for DNSCrypt-Proxy v2

  9. Using SPC copy files listed below to /etc/dnscrypt-proxy-v2/example

    example-backlist.txt
    example-cloaking-rules.txt
    example-dnscrypt-proxy.toml
    example-forwarding-rules.txt
    example-whitelist.txt
    LICENSE
    
  10. Using SCP copy (at least) example-dnscrypt-proxy.toml to /etc/dnscrypt-proxy-v2 and change it's name to dnscrypt-proxy-v2.toml and make necessary adjustments OR use ready-to-go config files from point 12.

  11. For minimal effort change the line listen_addresses = ['127.0.0.1:53', '[::1]:53']
    to listen_addresses = ['127.0.0.53:5353'] OR use the ready-to-go config files files from point 12.

  12. Links to content of my DNSCrypt-Proxy v2 config files:
    blacklist.txt
    cloaking-rules.txt
    dnscrypt-proxy-v2.toml
    forwarding-rules.txt
    LICENSE
    whitelist.txt

  13. Download the init .zip and using SCP copy the file inside it to /etc/init.d/.

  14. Set permissions to the init file
    chmod 755 /etc/init.d/dnscrypt-proxy-v2

  15. If you don't use v1 open /etc/config/dhcp file and inside section config dnsmasq add line
    list server '127.0.0.1#5353'

  16. To make sure the DNSCrypt-Proxy-v2 binary, init and config files are included in your router's config backups add below to /etc/sysupgrade.conf

    ## DNSCrypt-Proxy-v2
    
    /etc/init.d/dnscrypt-proxy-v2
    /usr/sbin/dnscrypt-proxy-v2
    /etc/dnscrypt-proxy-v2/
    
  17. Inside terminal disable v1...

    service dnscrypt-proxy stop
    service dnscrypt-proxy disable
    
  18. ...and enable v2

    service dnscrypt-proxy-v2 enable
    service dnscrypt-proxy-v2 start
    
3 Likes

@r43k3n extremely well detailed instructions, thank you. I shall give that a try! :grinning:

What is the meaning of changing the listening address from 127.0.0.1 to 127.0.0.53?

The entire 127.0.0.0/8 range is available for your computer alone, so changing to another address is just a way to let your computer not conflict with another program already listening on .1

1 Like

I have problems with paragraph 13 of the instructions above, the file can not be downloaded, and if you use the script from the original instructions, throws an error on the rc.common. Can someone lay out a script from this instruction?

What is this?

root@OpenWrt:~# /etc/init.d/dnscrypt-proxy enable
': No such file or directory.common

@vanyaindigo, in the future, you may wish to make a new thread for your issue instead of hijacking this one.

Also include more details.

  • Regarding the download, did you use HTTP?

I downloaded dnscrypt v2 manually

Please be more clear.

You manually downloaded:

  • to the router?
  • to your local machine?
  • to a USB stick?
  • from where/what URL?

The first, according to instructions:

The dnscrypt-proxy file is quite large, but can be compressed for a massive reduction of its size, from ~12 Mb down to ~2 Mb.

In order to do so, use UPX on any platform (Windows, Linux, macOS...) with the following command:

upx --lzma dnscrypt-proxy

The second:

Use scp to copy:

  • dnscrypt-proxy to /usr/sbin/
  • The modified dnscrypt-proxy.toml file to /etc/config/
  • This init.d file by @etam saved as /etc/init.d/dnscrypt-proxy

You are obviously missing the last step and the link is obsolete.