Pi-hole DNS-over-HTTPS using Cloudflared

The problem:

DON’T TRUST CLOUDFLARE!

This tutorial is for educational purposes only!

Even if you are visiting a site using HTTPS, your DNS query is sent over an unencrypted connection. That means that even if you are browsing https://cloudflare.com, anyone listening to packets on the network knows you are attempting to visit cloudflare.com.
The second problem with unencrypted DNS is that it is easy for a Man-In-The-Middle to change DNS answers to route unsuspecting visitors to their phishing, malware or surveillance site. DNSSEC solves this problem as well by providing a mechanism to check the validity of a DNS answer, but only a single-digit percentage of domains use DNSSEC.
To combat this problem, Cloudflare offers DNS resolution over an HTTPS endpoint. If you build a mobile application, browser, operating system, IoT device or router, you can choose for your users to use the DNS over HTTPS endpoint instead of sending DNS queries over plaintext for increased security and privacy of your users.
— https://developers.cloudflare.com/1.1.1.1/dns-over-https/

I assume that you have installed Pi-hole on your system and want to use cloudflare’s DNS-over-HTTPS client to secure* the network. * If you trust cloudflare.
This article is based on the official Pi-hole guide on ‘Configuring DNS-Over-HTTPS on Pihole’ (https://docs.pi-hole.net/guides/dns-over-https/).
Read that article for the complete and updated information about DoH on Pi-hole.

This are the commands needed to configure DoH on Pi-Hole.

Install cloudflared:
The download links can be found here: https://developers.cloudflare.com/argo-tunnel/downloads/

If you are using ARM CPU, open up terminal session and execute the following (do not include $):


$ wget -c https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-arm.tgz
$ tar -xvzf cloudflared-stable-linux-arm.tgz
$ sudo cp ./cloudflared /usr/local/bin
$ sudo chmod +x /usr/local/bin/cloudflared  

$ sudo useradd -s /usr/sbin/nologin -r -M cloudflared

Create a new file and add the configuration of cloudflared:

$ sudo nano /etc/default/cloudflared

# Commandline args for cloudflared
CLOUDFLARED_OPTS=--port 5053 --upstream https://1.1.1.1/dns-query --upstream https://1.0.0.1/dns-query

Change the permissions to cloudflared from root:


$ sudo chown cloudflared:cloudflared /etc/default/cloudflared
$ sudo chown cloudflared:cloudflared /usr/local/bin/cloudflared

Create a systemd service configuration:


$ sudo nano /lib/systemd/system/cloudflared.service

[Unit]
Description=cloudflared DNS over HTTPS proxy
After=syslog.target network-online.target

[Service]
Type=simple
User=cloudflared
EnvironmentFile=/etc/default/cloudflared
ExecStart=/usr/local/bin/cloudflared proxy-dns $CLOUDFLARED_OPTS
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target

Enable and start cloudflared systemd service:


sudo systemctl enable cloudflared
sudo systemctl start cloudflared
sudo systemctl status cloudflared

Test DoH:


$ dig @127.0.0.1 -p 5053 cloudflare.com

; <> DiG 9.10.3-P4-Raspbian <> @127.0.0.1 -p 5053 cloudflare.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46075
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1452
;; QUESTION SECTION:
;cloudflare.com.			IN	A

;; ANSWER SECTION:
cloudflare.com.		232	IN	A	198.41.214.162
cloudflare.com.		232	IN	A	198.41.215.162

;; Query time: 203 msec
;; SERVER: 127.0.0.1#5053(127.0.0.1)
;; WHEN: Fri Feb 15 09:02:26 PST 2019
;; MSG SIZE  rcvd: 103

Change Pi-hole’s upstream DNS:
Login to your Pi-hole admin site, go to the settings > DNS, uncheck the DNS servers and add a custom DNS with the value

127.0.0.1#5053

Click save and logout.

If you did not activate the web interface, just login to SSH and edit the ff. files, remove the other DNS server or replace with:


$ sudo nano /etc/pihole/setupVars.conf
PIHOLE_DNS_1=127.0.0.1#5053

$ sudo nano /etc/dnsmasq.d/01-pihole.conf
server=127.0.0.1#5053

Restart pi-hole and dnsmasq:


$ sudo pihole restartdns

Here are the output of the commands:


$ wget -c https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-arm.tgz
Resolving bin.equinox.io (bin.equinox.io)... 34.232.40.183, 34.226.180.131, 34.238.3.58, ...
Connecting to bin.equinox.io (bin.equinox.io)|34.232.40.183|:443... connected.
HTTP request sent, awaiting response... 200 OK                          
Length: 8128269 (7.8M) [application/octet-stream]                     
Saving to: ‘cloudflared-stable-linux-arm.tgz’                                                  
                                                                                                 
cloudflared-stable-linux 100%[================================>]   7.75M   390KB/s    in 51s
                                                                     
2019-02-12 21:12:46 (157 KB/s) - ‘cloudflared-stable-linux-arm.tgz’ saved [8128269/8128269]

$ tar -xvzf cloudflared-stable-linux-arm.tgz
cloudflared                                

$ sudo cp ./cloudflared /usr/local/bin

$ cloudflared -v
cloudflared version 2019.2.0 (built 2019-02-11-2010 UTC)    

$ sudo systemctl enable cloudflared
Created symlink /etc/systemd/system/multi-user.target.wants/cloudflared.service → /lib/systemd/system/cloudflared.service.

$ sudo systemctl start cloudflared

$ sudo systemctl status cloudflared
● cloudflared.service - cloudflared DNS over HTTPS proxy
   Loaded: loaded (/lib/systemd/system/cloudflared.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2019-02-12 21:15:08 PST; 295ms ago
 Main PID: 6551 (cloudflared)
   CGroup: /system.slice/cloudflared.service
           └─6551 /usr/local/bin/cloudflared proxy-dns --port 5053 --upstream https://1.1.1.1/dns-

Feb 12 21:15:08 raspbian systemd[1]: Started cloudflared DNS over HTTPS proxy.
lines 1-8/8 (END)

    

References:
https://discourse.pi-hole.net/t/the-pihole-command-with-examples/738
https://github.com/pi-hole/pi-hole/wiki/Upstream-DNS-Providers
https://docs.pi-hole.net/guides/dns-over-https/
https://developers.cloudflare.com/1.1.1.1/dns-over-https/cloudflared-proxy/
https://github.com/cloudflare/cloudflared

Except where otherwise noted, this work is licensed under Creative Commons Attribution-ShareAlike 4.0 International License (http://creativecommons.org/licenses/by-sa/4.0/).
I hope that this post is useful to you, if you liked this post you may support me via liberapay or patreon. Thank you for your support.