DNSCrypt

DNSCrypt encrypts and authenticates DNS traffic between user and DNS resolver. While IP traffic itself is unchanged, it prevents local spoofing of DNS queries, ensuring DNS responses are sent by the server of choice. [1]

Installation

Install the dnscrypt-proxy package.

Configuration

When dnscrypt-proxy.socket is enabled, dnscrypt-proxy accepts incoming requests on 127.0.0.1:53 to an OpenDNS resolver. The default DNS resolver for dnscrypt-proxy.service is dnscrypt.eu-nl. Compatible resolver names are visible in the first column of /usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv.

To change the default, edit dnscrypt-proxy.service. It is recommended to choose a provider close to your location.

Alter the resolv.conf file and replace the current set of resolver addresses with localhost:

nameserver 127.0.0.1

Other programs may overwrite this setting; see resolv.conf#Preserve DNS settings for details.

Tips and tricks

DNSCrypt as a forwarder for local DNS cache

It is recommended to run DNSCrypt as a forwarder for a local DNS cache, otherwise every single query will make a round-trip to the upstream resolver. Any local DNS caching program should work, examples below show configuration for Unbound, dnsmasq, and pdnsd.

Example: configuration for Unbound

Configure Unbound to your liking (remember to set /etc/resolv.conf to use the local DNS server) and add the following lines to the end of the server section in /etc/unbound/unbound.conf:

do-not-query-localhost: no
forward-zone:
  name: "."
  forward-addr: 127.0.0.1@40
Note: Port 40 is given as an example as Unbound by default listens to 53, these must be different.
Tip: If you are setting up a server add interface: 0.0.0.0@53 and access-control: your-network/subnet-mask allow inside the server: section so that the other computers of your LAN can connect to the server. A client must be configured with nameserver address-of-your-server in /etc/resolv.conf.

Start the systemd service unbound.service. Then configure DNScrypt to match Unbound's new forward-zone IP and port with systemctl edit --full dnscrypt-proxy.socket:

[Unit]
Description=dnscrypt-proxy listening socket
After=network.target

[Socket]
ListenStream=127.0.0.1:40
ListenDatagram=127.0.0.1:40

[Install]
WantedBy=sockets.target

Restart dnscrypt-proxy.service and unbound.service to apply the changes.

Example: configuration for dnsmasq

Configure dnsmasq as a local DNS cache. The basic configuration to work with DNSCrypt:

/etc/dnsmasq.conf
no-resolv
server=127.0.0.2#2053
listen-address=127.0.0.1

If you configured DNSCrypt to use a resolver with enabled DNSSEC validation, make sure to enable it also in dnsmasq:

/etc/dnsmasq.conf
proxy-dnssec

Configure DNSCrypt to listen on 127.0.0.2:2053 with systemctl edit --full dnscrypt-proxy.socket:

[Unit]
Description=dnscrypt-proxy listening socket
After=network.target

[Socket]
ListenStream=127.0.0.2:2053
ListenDatagram=127.0.0.2:2053

[Install]
WantedBy=sockets.target

Restart dnscrypt-proxy.service and dnsmasq.service to apply the changes.

Example: configuration for pdnsd

Install pdnsd. A basic configuration to work with DNSCrypt is:

/etc/pdnsd.conf
global {
	perm_cache=16384;
	cache_dir="/var/cache/pdnsd";
	run_as="pdnsd";
 	server_ip = 127.0.0.1;
	status_ctl = on;
	query_method=udp_tcp;
	min_ttl=15m;       # Retain cached entries at least 15 minutes.
	max_ttl=1w;        # One week.
	timeout=10;        # Global timeout option (10 seconds).
	neg_domain_pol=on;
	udpbufsize=1024;   # Upper limit on the size of UDP messages.
}

server {
	label = "dnscrypt-proxy";
	ip = 127.0.0.2;
	port = 53;
	timeout = 4;
	uptest = query;
	interval = 15m;
	proxy_only=on;
}

source {
	owner=localhost;
	file="/etc/hosts";
}


rr {
	name=localhost;
	reverse=on;
	a=127.0.0.1;
	owner=localhost;
	soa=localhost,root.localhost,42,86400,900,86400,86400;
}

Configure DNSCrypt to listen on 127.0.0.2:53 with systemctl edit --full dnscrypt-proxy.socket:

[Unit]
Description=dnscrypt-proxy listening socket
After=network.target

[Socket]
ListenStream=127.0.0.2:53
ListenDatagram=127.0.0.2:53

[Install]
WantedBy=sockets.target

Be sure you have configured resolv.conf properly for 127.0.0.1.

Restart dnscrypt-proxy.service and pdnsd.service to apply the changes.

Enable EDNS0

Extension Mechanisms for DNS that, among other things, allows a client to specify how large a reply over UDP can be.

Add the following line to your /etc/resolv.conf:

options edns0

You may also wish to add the following argument to dnscrypt-proxy:

--edns-payload-size=<bytes>

The default size being 1252 bytes, with values up to 4096 bytes being purportedly safe. A value below or equal to 512 bytes will disable this mechanism, unless a client sends a packet with an OPT section providing a payload size.

Test EDNS0

Make use of the DNS Reply Size Test Server, use the dig command line tool from the bind-tools package to issue a TXT query for the name rs.dns-oarc.net:

$ dig +short rs.dns-oarc.net txt

With EDNS0 supported, the output should look similar to this:

rst.x3827.rs.dns-oarc.net.
rst.x4049.x3827.rs.dns-oarc.net.
rst.x4055.x4049.x3827.rs.dns-oarc.net.
"2a00:d880:3:1::a6c1:2e89 DNS reply size limit is at least 4055 bytes"
"2a00:d880:3:1::a6c1:2e89 sent EDNS buffer size 4096"