DNSCrypt

Dan Schaper edited this page Feb 25, 2018 · 89 revisions

Note: This is a community provided and edited document. These instructions are not monitored by the Pi-hole development team.

dnscrypt-proxy 2 on Pi-hole

Important: dnscrypt-proxy 1.x has reached EOL. It is not maintained any more, and won't get any new features nor security patches. The old list of resolvers is not updated any more. As of 2018, everybody should use dnscrypt-proxy 2.x.

Updated instructions: Installing dnscrypt-proxy 2.0 on Pi-hole

dnscrypt-proxy 1.x on Pi-hole (original instructions for version 1)

Follow these steps to install and enable DNSCrypt on your Pi-hole installation. Read more about DNSCrypt here: DNSCrypt.

Please note that your Pi-hole will stop working during the installation so keep that in mind if there are other users on your network using the Pi-hole.

Please note, I take no responsibility for any breakage or corruption of your Pi-hole installation when following this guide.


Install necessary system packages

sudo apt-get update
sudo apt-get -y install build-essential tcpdump dnsutils libsodium-dev 
sudo apt-get -y install locate bash-completion libsystemd-dev pkg-config

Build DNSCrypt from the sources

mkdir -p dnsproxy
cd dnsproxy
wget https://launchpad.net/ubuntu/+archive/primary/+files/dnscrypt-proxy_1.9.5.orig.tar.gz
tar -xf LATEST.tar.bz2
cd dnscrypt-proxy[tab completion]
sudo ldconfig
./configure --with-systemd
make
sudo make install

Configure the system

Add a dnscrypt user so the DNSCrypt-Proxy won't run as root

sudo useradd -r -d /var/dnscrypt -m -s /usr/sbin/nologin dnscrypt

Starts DNSProxy in daemon mode automatically

The following 2 files are now located in the dnscrypt-proxy-[version] folder:

dnscrypt-proxy.service and dnscrypt-proxy.socket

This eases the creation of the service because now systemd takes care of creating the sockets, which avoids long shutdown times if a wrong pid was set etc (see DNSCrypt-Proxy using systemd)

First take a look at the DNSCrypt public resolver list and select which resolvers you want to use. (Nearby Location, No Logging etc.)

In this example I will be using the DNSCrypt.eu servers, but feel free to use any servers that suite best for you.

  • dnscrypt.eu-dk
  • dnscrypt.eu-nl

as well as

  • dnscrypt.eu-dk-ipv6
  • dnscrypt.eu-nl-ipv6

for IPv6 connections (if your service provider (only) supports IPv6).

Then just simply copy the dnscrypt-proxy.socket adding @resolver-name (from the 'Name' column in the list) at the end:

cp dnscrypt-proxy.socket dnscrypt-proxy@dnscrypt.eu-dk.socket

and change the IP from 127.0.0.1:53 to anything from 127.0.0.2 to 127.255.255.254: You could as well just change the port (127.0.0.1:53 is used by dnsmasq), but with different localhost IPs the Forwarding destinations in the Pi-hole Webinterface is showing each Proxy individually.

nano dnscrypt-proxy@dnscrypt.eu-dk.socket

[Unit]
Description=dnscrypt-proxy listening socket

[Socket]
ListenStream=127.10.10.1:41
ListenDatagram=127.10.10.1:41

[Install]
WantedBy=sockets.target

and for the @dnscrypt.eu-nl server alike (I used 127.10.10.2 and 127.20.20.1/2 for the IPv6 servers)

To complete the setup we need to alter the dnscrypt-proxy.service as well: create a copy of the .service file adding an @ at the end

cp dnscrypt-proxy.service dnscrypt-proxy@.service

and edit the file:

nano dnscrypt-proxy@.service

change Requires=dnscrypt-proxy.socket in line 4 to

Requires=dnscrypt-proxy@%i.socket

and the Also=dnscrypt-proxy.socket in line 9 to

Also=dnscrypt-proxy@dnscrypt.eu-dk.socket
Also=dnscrypt-proxy@dnscrypt.eu-nl.socket
Also=dnscrypt-proxy@dnscrypt.eu-dk-ipv6.socket
Also=dnscrypt-proxy@dnscrypt.eu-nl-ipv6.socket

and at the end change (as of the latest DNSCrypt 1.9.4, these entries do not exist so the following "to" entries need to be added manually. 1.9.4 seems to reference a template file /usr/local/etc/dnscrypt-proxy.conf, which will need to removed from the "ExecStart=" line in the below example)

      --resolver-name=<resolver name> \
      --user=<user name to run the service as>

to

      --resolver-name=%i \
      --user=dnscrypt

and add a

Restart=always

at the last line

The resulting file should look like this (dnscrypt-proxy@.service):

[Unit]
Description=DNSCrypt client proxy
Documentation=man:dnscrypt-proxy(8)
Requires=dnscrypt-proxy@%i.socket
After=network.target
Before=nss-lookup.target

[Install]
Also=dnscrypt-proxy@dnscrypt.eu-dk.socket
Also=dnscrypt-proxy@dnscrypt.eu-nl.socket
Also=dnscrypt-proxy@dnscrypt.eu-dk-ipv6.socket
Also=dnscrypt-proxy@dnscrypt.eu-nl-ipv6.socket
WantedBy=multi-user.target

[Service]
Type=simple
NonBlocking=true

# Fill in the resolver name with one from dnscrypt-resolvers.csv file
# It is also recommended to create a dedicated system user, for example _dnscrypt
# Additional features, such as ephemeral keys and plugins, can be enabled here as well
ExecStart=/usr/local/sbin/dnscrypt-proxy \
        --resolver-name=%i \
        --user=dnscrypt

Restart=always

For strengthened security you could add

        -E \ or --ephemeral-keys \

between the lines of --resolver-name and --user, but after reading the note at DNSCrypt.org:

--ephemeral-keys: improve privacy by using an ephemeral public key for each query. Recommended if you are not using your own server, any the remote server is logging your activity, and your client IP address is frequently changing. Not enabled by default because it may be slow, especially on non-Intel CPUs.

I for myself decided against it.

Activate the service

copy all related files to the systemd folder:

sudo cp ./dnscrypt-proxy@* /etc/systemd/system/

and activate it:

sudo systemctl daemon-reload

sudo systemctl enable dnscrypt-proxy@.service

the output should look similar as follows:

Created symlink from /etc/systemd/system/sockets.target.wants/dnscrypt-proxy@dnscrypt.eu-dk.socket to /lib/systemd/system/dnscrypt-proxy@dnscrypt.eu-dk.socket.
Created symlink from /etc/systemd/system/sockets.target.wants/dnscrypt-proxy@dnscrypt.eu-dk-ipv6.socket to /lib/systemd/system/dnscrypt-proxy@dnscrypt.eu-dk-ipv6.socket.
Created symlink from /etc/systemd/system/sockets.target.wants/dnscrypt-proxy@dnscrypt.eu-nl.socket to /lib/systemd/system/dnscrypt-proxy@dnscrypt.eu-nl.socket.
Created symlink from /etc/systemd/system/sockets.target.wants/dnscrypt-proxy@dnscrypt.eu-nl-ipv6.socket to /lib/systemd/system/dnscrypt-proxy@dnscrypt.eu-nl-ipv6.socket.

ps ax | grep dnscrypt

should now already list all 4 proxies running on your Pi:

/usr/local/sbin/dnscrypt-proxy --resolver-name=dnscrypt.eu-dk --user=dnscrypt
...

Then reboot the RPI

sudo reboot


Test DNSCrypt

sudo systemctl status -l dnscrypt-proxy@\*

You should have a similar output (one for each proxy):

● dnscrypt-proxy@dnscrypt.eu-dk.service - DNSCrypt client proxy
Loaded: loaded (/lib/systemd/system/dnscrypt-proxy@.service; disabled)
Active: active (running) since Tue 2016-10-11 09:45:25 CEST; 1min 39s ago
  Docs: man:dnscrypt-proxy(8)
Main PID: 1940 (dnscrypt-proxy)
CGroup: /system.slice/system-dnscrypt\x2dproxy.slice/dnscrypt-proxy@dnscrypt.eu-dk.service
       └─1940 /usr/local/sbin/dnscrypt-proxy --resolver-name=dnscrypt.eu-dk --user=dnscrypt

 Oct 11 09:45:25 Raspberry-Pi-3 dnscrypt-proxy[1940]: [INFO] + DNS Security Extensions are supported
 Oct 11 09:45:25 Raspberry-Pi-3 dnscrypt-proxy[1940]: [INFO] + Provider supposedly doesn't keep logs
 Oct 11 09:45:25 Raspberry-Pi-3 dnscrypt-proxy[1940]: [NOTICE] Starting dnscrypt-proxy 1.7.0
 Oct 11 09:45:25 Raspberry-Pi-3 dnscrypt-proxy[1940]: [INFO] Generating a new session key pair
 Oct 11 09:45:25 Raspberry-Pi-3 dnscrypt-proxy[1940]: [INFO] Done
 Oct 11 09:45:25 Raspberry-Pi-3 dnscrypt-proxy[1940]: [INFO] Server certificate with serial '0001' received
 Oct 11 09:45:25 Raspberry-Pi-3 dnscrypt-proxy[1940]: [INFO] This certificate is valid
 Oct 11 09:45:25 Raspberry-Pi-3 dnscrypt-proxy[1940]: [INFO] Chosen certificate #808464433 is valid from [2016-09-10] to [2017-09-10]
 Oct 11 09:45:25 Raspberry-Pi-3 dnscrypt-proxy[1940]: [INFO] Server key fingerprint is D616:D268:09D2:29A7:9457:DE07:3DE8:EBD8:3C24:BFF3:2BF7:B406:108B:44DA:51FE:3711
 Oct 11 09:45:25 Raspberry-Pi-3 dnscrypt-proxy[1940]: [NOTICE] Proxying from 127.10.10.1:41 to 77.66.84.233:443

The last line is important and should look something like the above!

For further checks you can run:

sudo tail -f /var/log/syslog

If the sockets come up Inactive(dead)

On some configurations the above "enable" command will create the individual sockets and define the services, but not actually enable the services. This will mainly occur if the default.target does not match the service target. To remediate, enable the various services individually:

sudo systemctl enable dnscrypt-proxy@dnscrypt.eu-dk.service

Do this for all selected dnscrypt end-points. Afterwards reboot, or alternatively you can test immediately by also starting the services:

sudo systemctl start dnscrypt-proxy@dnscrypt.eu-dk.service

After starting the services manually or rebooting the services should now look as above.


Change your DNSMasq config

Change DNS resolver in DNSMasq config

sudo nano /etc/dnsmasq.d/02-dnscrypt.conf

Add this section and point to dnscrypt-proxy

# Add other name servers here, with domain specs if they are for
# non-public domains.
 server=127.10.10.1#41
 server=127.10.10.2#41    (if adding a second resolver)
 server=127.20.20.1#41    (if you are using the IPv6 ones as well)
 server=127.20.20.2#41  

sudo nano /etc/pihole/setupVars.conf

and comment out the PIHOLE_DNS1 and PIHOLE_DNS2 lines

#PIHOLE_DNS1=...
#PIHOLE_DNS2=...

sudo nano /etc/dnsmasq.d/01-pihole.conf

and comment out all lines starting with server=

#server=...

This makes sure DNSCrypt is always used and not reset to the DNS servers you provided in the initial setup. (Pi-hole will remove the server= lines on the next update if they are commented out, else they will silently reappear and DNSCrypt will be bypassed)

Restart dnsmasq

sudo service dnsmasq restart


Now you should be using encrypted DNS lookups!

Check these sites to verify that it is operating properly:

Verify DNSSEC if chosen provider is DNSSEC enabled, Test DNSSEC

Check DNS leaks, DNS leak test

Run nslookup pi-hole.net to check your Pi-hole is using 127.0.0.1#53 as it's DNS. If not, check the IP config of your Pi (/etc/dhcpcd.conf if using static IP) and check that /etc/resolv.conf is using 127.0.0.1


Additional step: Update dnscrypt-resolvers.csv regulary

In case the server certificate get's updated it's important to have an up to date copy of the dnscrypt-resolvers.csv from github.com.

To automate this process you can write a simple shell script:

sudo nano /usr/local/share/dnscrypt-proxy/update_resolvers.sh

#!/bin/bash
# timestamp
NOW=$(date +"%F_%H-%M")

# Make sure only root can run our script
if [ "$(id -u)" != "0" ]; then
  echo "This script must be run as root" 1>&2
  exit 1
fi

# get the latest copy from github
cd /tmp
wget -O "dnscrypt-resolvers-$NOW.csv" https://raw.githubusercontent.com/jedisct1/dnscrypt-resolvers/master/v1/dnscrypt-resolvers.csv
 
 ### If code block to avoid null resolvers file ###
 if [ -s "dnscrypt-resolvers-$NOW.csv" ]; then
 # adjust permissions
 chown root:staff "/tmp/dnscrypt-resolvers-$NOW.csv"

 # move it to the correct location
 cd /usr/local/share/dnscrypt-proxy/
 mv -f dnscrypt-resolvers.csv dnscrypt-resolvers.csv.bak
 mv -f "/tmp/dnscrypt-resolvers-$NOW.csv" ./dnscrypt-resolvers.csv

 # restart all dnscrypt-proxies
 systemctl restart dnscrypt-proxy@\*
 echo "Resolvers file updated"
 else
 echo "File is null"
 fi
 ### End IF code block ###

 exit 0

Run the script manually or automated adding it to the roots crontab

sudo chmod +x /usr/local/share/dnscrypt-proxy/update_resolvers.sh (only needed after initial creation)

sudo /usr/local/share/dnscrypt-proxy/update_resolvers.sh

or

sudo crontab -e

at the bottom add:

minute  hour  *  *  *  /usr/local/share/dnscrypt-proxy/update_resolvers.sh

will run the script every day at hour:minute. You could run it just once per week by replacing the last * with a number from 0 to 7 (0=sunday, 1=monday and so on)

e.g.

37  2  *  *  0  /usr/local/share/dnscrypt-proxy/update_resolvers.sh

will run the script every sunday night at 2:37 am.

add custom host name to display in the web-frontend

Since pi-hole version 2.9.4 it is possible to define a name for your custom DNSCrypt entries. Just make sure you don't overwrite any legitimate hostnames (e.g. use .local or .dns at the end as long as they haven't been assigned by ICANN yet (you can check all new gTLDs here - avoid using any of those as well as any regular TLD (.com, .net, .uk etc.)

sudo nano /etc/hosts

For our setup it could look like this:

# DNSCrypt Proxies running on this machine
127.10.10.1     dk.dnscrypt.eu.dns
127.10.10.2     nl.dnscrypt.eu.dns
# DNSCrypt Proxies for IPv6
127.20.20.1     ipv6.dk.dnscrypt.eu.dns
127.20.20.2     ipv6.nl.dnscrypt.eu.dns

Save the file (be careful not to delete anything, especially the localhost parts) and reload the web interface - and enjoy the new "Forward Destinations" pie chart.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.