DNS-Over-HTTPS on Pi-hole


What is DNS-Over-HTTPS?

DNS-Over-HTTPS (DoH) is a protocol for performing DNS lookups via HTTPS.

With regular DNS, requests are sent in plain-text, with no method to detect tampering. This means that not only can a malicous actor look at all the DNS requests you are making, they can also tamper with the response and redirect your device to resources in their control (such as a fake login page for internet banking).

Nowadays in a lot of countries the ISP's have an obligation to record all traffic of their clients. Because more and more sites use HTTPS, it is impossible for ISP's to see which sites you visited. But because all DNS request are made in plain text, they still know what sites you looking at. Even if you don't use your ISP's DNS servers.

DNS-Over-HTTPS prevents this by using standard HTTPS requests to retrieve DNS information. This means that the connection from the device to the DNS server is secure and can not easily be snooped, monitored, tampered with or blocked. The DNS requests in your network are still in plain text, but as soon as it passes the Pi-Hole server it is transported via a secure tunnel to the Cloudflare DoH server.

I think it is good to know that there is another encryption method. DNS over TLS (DoT).


Configuring DNS-Over-HTTPS

Along with releasing their DNS service 1.1.1.1, Cloudflare implemented DNS-Over-HTTPS proxy functionality in to one of their tools: cloudflared (also known as argo-tunnel). In the following sections we will be covering how to install and configure this tool on Pi-hole.


Installing cloudflared (32-bit Raspberry Pi)

Here we are downloading the precompiled binary and copying it to the /usr/local/bin/ directory to allow execution by the cloudflared user: wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm sudo mv -f ./cloudflared-linux-arm /usr/local/bin/cloudflared sudo chmod +x /usr/local/bin/cloudflared Proceed to run the binary with the -v flag to check it is all working: $ cloudflared -v


Configuring cloudflared to run on startup

Create a cloudflared user to run the daemon: sudo useradd -s /usr/sbin/nologin -r -M cloudflared Proceed to create a configuration file for cloudflared: sudo nano /etc/default/cloudflared Edit configuration file by copying the following in to /etc/default/cloudflared. This file contains the command-line options that get passed to cloudflared on startup: # Commandline args for cloudflared, using Cloudflare DNS CLOUDFLARED_OPTS=--port 5053 --upstream https://1.1.1.1/dns-query --upstream https://1.0.0.1/dns-query Update the permissions for the configuration file and cloudflared binary to allow access for the cloudflared user: sudo chown cloudflared:cloudflared /etc/default/cloudflared sudo chown cloudflared:cloudflared /usr/local/bin/cloudflared

Then create the systemd script by copying the following into /etc/systemd/system/cloudflared.service. This will control the running of the service and allow it to run on startup: sudo nano /etc/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 the systemd service to run on startup, then start the service and check its status: sudo systemctl enable cloudflared sudo systemctl start cloudflared sudo systemctl status cloudflared

Now test that it is working! Run the following dig command: $ dig @127.0.0.1 -p 5053 google.com A response should be returned similar to the one below: pi@raspberrypi:~ $ dig @127.0.0.1 -p 5053 google.com ; <<>> DiG 9.11.5-P4-5.1-Raspbian <<>> @127.0.0.1 -p 5053 google.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12157 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: 22179adb227cd67b (echoed) ;; QUESTION SECTION: ;google.com. IN A ;; ANSWER SECTION: google.com. 191 IN A 172.217.22.14 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#5053(127.0.0.1) ;; WHEN: Wed Dec 04 09:29:50 EET 2019 ;; MSG SIZE rcvd: 77


Configuring Pi-hole

Finally, configure Pi-hole to use the local cloudflared service as the upstream DNS server
by specifying 127.0.0.1#5053 as the Custom DNS (IPv4): 127.0.0.1#5053


Updating cloudflared

The cloudflared tool will not receive updates through the package manager. However, you should keep the program update to date. You can either do this manually, or via a cron script.
The procedure for updating depends on how you configured the cloudflared binary.

If you configured cloudflared via service install
If you configured cloudflared using their service install command, then you can use the built in update command: sudo cloudflared update sudo systemctl restart cloudflared

Automating Cloudflared Updates
If you want to have the system update cloudflared automatically,
simply place the update commands for your configuration method in the file /etc/cron.weekly/cloudflared-updater, and adjust permissions: sudo nano /etc/cron.weekly/cloudflared-updater #!/bin/bash sudo chmod +x /etc/cron.weekly/cloudflared-updater sudo chown root:root /etc/cron.weekly/cloudflared-updater

The system will now attempt to update the cloudflared binary automatically, once per week.


DNS over HTTPS - How to check?

https://1.1.1.1/help

The output must be something like the one below:


Documentation