As first step, configure the tunnel part of cloudflared normally.
In Cloudflare Zero Trust, create a DNS Location. Enable just the DNS over HTTPS (DoH) endpoint. An endpoint such as https://xxxxxxxxxx.cloudflare-gateway.com/dns-query will be generated; take note of it
(optional) in Cloudflare Zero Trust, create your desired DNS Policy, inside Firewall policies, in order to block web site categories (malware, phishing, etc.) based on their DNS names
Verify that the endpoint is actually reachable and allowing queries: this example sends a DoH query for the 'A' record for 'www.microsoft.com':
curl -H 'accept: application/dns-json' 'https://xxxxxxxxxx.cloudflare-gateway.com/dns-query?name=www.microsoft.com&type=A'
We now need to tell the cloudflared agent to activate also the DoH feature. In /etc/cloudflared/config.yml, add the following:
proxy-dns: true proxy-dns-port: 5053 # or any unused local port proxy-dns-upstream: - https://xxxxxxxxxx.cloudflare-gateway.com/dns-query # the endpoint noted before bootstrap: 1.1.1.1
Restart cloudflared and check that cloudflared is now listening on port 5053 specified in the config.yml file:
netstat -tulnp | grep 5053 tcp 0 0 127.0.0.1:5053 0.0.0.0:* LISTEN 12564/cloudflared udp 0 0 127.0.0.1:5053 0.0.0.0:* 12564/cloudflared
Now we need to tell dnsmasq to use the endpoint on 5053 as forwarder, and the general Cloudflare DNS address (1.1.1.1) as fallback. Edit the dnsmasq section of /etc/config/dhcp, making sure to include the following:
... option allservers '0' ... # Primary DoH proxy (via cloudflared) list server '127.0.0.1#5053' # Fallback if DoH proxy is not available list server '1.1.1.1'
Note the allservers line: we need to ensure that queries go first to 127.0.0.1#5053, and to 1.1.1.1 only as fallback; not in parallel to both upstreams. See the allservers option in all_options for details.
Check that DoH is actually enforced, by using Cloudflare's test page (https://1.1.1.1/help)