Setting Up DNS-over-HTTPS on Technitium with Cloudflare

If you're running your own Technitium DNS Server and want to secure your queries with DNS-over-HTTPS using Cloudflare, this guide will walk you through the steps I followed to get it working. Unfortunately, existing documentation on this topic is sparse and outdated.

DoH is a protocol that encrypts DNS queries by sending them over HTTPS instead of traditional plaintext UDP or TCP. This improves privacy and security by preventing third parties (like ISPs or attackers on public Wi-Fi) from seeing which domains you are trying to resolve.

How it works:

Instead of sending DNS queries in plaintext over port 53, DoH sends them as encrypted HTTPS requests over port 443.

The queries are handled by a DoH-compatible DNS resolver, such as Cloudflare (1.1.1.1), Google (8.8.8.8), or your own Technitium DNS setup if configured for DoH.

Because the requests are encrypted, ISPs and other intermediaries cannot easily inspect or modify your DNS traffic.

What it does:

Protects DNS queries from being read or modified.

Your ISP cannot see or log which domains you visit.

Stops attackers from redirecting you to malicious sites.

Helps prevent MitM attacks on DNS traffic.

What it does not do:

Your ISP or network provider can still see your IP address and which websites you connect to. To hide your IP, you need a VPN or Tor.

Even if DNS queries are encrypted, your ISP or attackers can analyze encrypted traffic patterns (SNI, TLS handshakes, IP connections) to guess which websites you visit.

It only encrypts DNS queries—it does not provide ad or tracker blocking unless used with a DNS resolver that blocks them.

Your ISP can still throttle specific websites/services based on traffic patterns, even if DNS queries are encrypted.

Update Technitium to the Latest Version

Before anything else, ensure your Technitium DNS is up to date:

curl -sSL https://download.technitium.com/dns/install.sh | sudo bash

Install Certbot and Cloudflare Plugin

You'll need a valid SSL certificate for DoH to work. To automate Let's Encrypt certificates with Cloudflare, install Certbot and its Cloudflare plugin:

sudo apt update && sudo apt install certbot python3-certbot-dns-cloudflare -y

Set Up a Cloudflare API Token

Log in to Cloudflare Dashboard.

Navigate to API Tokens.

Click Create Token and select the Edit zone DNS template.

Assign Zone:DNS:Edit permission for your domain

Generate the API token and copy it.

Save this token:

mkdir -p ~/.secrets/certbot
echo "dns_cloudflare_api_token = YOUR_API_TOKEN" > ~/.secrets/certbot/cloudflare.ini
chmod 600 ~/.secrets/certbot/cloudflare.ini

Issue an SSL Cert

Run the following command to request a wildcard SSL certificate:

sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini -d yourdomain.com -d *.yourdomain.com --agree-tos --email your@email.com --non-interactive

Once the certificate is issued, it will be stored in:

/etc/letsencrypt/live/yourdomain.com/

Convert the SSL Certificate to PFX Format

Technitium requires a .pfx certificate, so you'll need to convert the issued Let's Encrypt certificate:

openssl pkcs12 -export \
-out /etc/letsencrypt/live/yourdomain.com/cert.pfx \
-inkey /etc/letsencrypt/live/yourdomain.com/privkey.pem \
-in /etc/letsencrypt/live/yourdomain.com/fullchain.pem \
-passout pass:yourpassword

Configure Technitium for DoH

Open Technitium DNS Web UI: http://Technitium-IP:5380

Navigate to Settings → Optional Protocols → DNS-over-HTTPS & DNS-over-TLS.

In TLS Certificate File Path, enter:

/etc/letsencrypt/live/yourdomain.com/cert.pfx

Enter the PKCS #12 password (the one set in -passout pass:yourpassword).

Save the settings and restart the Technitium service.

Automate Certificate Renewal

Since Let's Encrypt certificates expire every 90 days, automation is required. The cert itself will auto-renew, but we need to automate the conversion to .pfx:

Create a Renewal Script

Create a script to renew the certificate, convert it, and restart Technitium:

sudo nano /usr/local/bin/renew-technitium.sh

Paste the following:

#!/bin/bash
certbot renew --quiet
openssl pkcs12 -export -out /etc/letsencrypt/live/yourdomain.com/cert.pfx \
-inkey /etc/letsencrypt/live/yourdomain.com/privkey.pem \
-in /etc/letsencrypt/live/yourdomain.com/fullchain.pem \
-passout pass:yourpassword
systemctl restart dns

Make it executable:

sudo chmod +x /usr/local/bin/renew-technitium.sh

Schedule Renewal with Cron

Edit the root crontab:

sudo crontab -e

Add this line to run the script daily at 2 AM:

0 2 * * * /usr/local/bin/renew-technitium.sh >/dev/null 2>&1

Test the Renewal Process

Instead of waiting for cron, manually run the script:

sudo /usr/local/bin/renew-technitium.sh

Verify that the certificate was updated:

ls -l /etc/letsencrypt/live/yourdomain.com/cert.pfx
systemctl status dns

If the .pfx file has a new timestamp, the renewal worked. If Technitium restarted successfully, everything is good to go.

Configure Technitium to Use Cloudflare DoH

Open Technitium DNS Web UI.

Navigate to Settings → Proxy & Forwarders.

Ensure the Protocol is set to DoH and select Cloudflare's DoH under Forwarders:

https://cloudflare-dns.com/dns-query (1.1.1.1)
https://cloudflare-dns.com/dns-query (1.0.0.1)

Save and restart the service.

Access DoH via Your Reverse Proxy

If you have a reverse proxy (e.g., Nginx, Traefik, Caddy), you can assign a domain to make it simpler to remember the path.

Assign a domain like dns.yourdomain.com to your Technitium instance.

Configure your proxy to route HTTPS traffic to Technitium on port 443.

Test your setup by visiting:

https://1.1.1.1/help

If everything is set up correctly, your queries should now be securely resolved over DNS-over-HTTPS via Cloudflare and Using DNS over HTTPS (DoH) should say Yes.