Skip to content

Instantly share code, notes, and snippets.

@0x48piraj
Created February 8, 2026 05:39
Show Gist options
  • Select an option

  • Save 0x48piraj/0afb9cbf1abef0aac1591c834ea9f3c4 to your computer and use it in GitHub Desktop.

Select an option

Save 0x48piraj/0afb9cbf1abef0aac1591c834ea9f3c4 to your computer and use it in GitHub Desktop.
Pi-hole + DoH: Secure DNS and Ad Blocking on Android 12+ (and iOS devices) on locked down routers.

Pi-hole + DoH (cloudflared) Notes

Why this was needed

  • Android 12+ aggressively uses DoH (Private DNS) and may bypass local DNS

  • Plain Pi-hole blocks ads, but upstream DNS is unencrypted

  • We wanted:

    • Ad blocking on home Wi-Fi
    • Encrypted DNS upstream
    • No VPNs, no router access, no apps

Cloudflared breaking change

Solution

  • Use last supported version:

    cloudflared 2025.11.1
    
  • This version still supports:

    cloudflared proxy-dns
    

Cloudflared DoH setup

On Raspberry Pi 3 Model B+ v1.2 (Debian Bookworm, ARM)

Download correct binary (ARM)

wget https://github.com/cloudflare/cloudflared/releases/download/2025.11.1/cloudflared-linux-arm
sudo mv cloudflared-linux-arm /usr/local/bin/cloudflared
sudo chmod +x /usr/local/bin/cloudflared
cloudflared -v

Expected:

cloudflared version 2025.11.1

Create service user

sudo useradd -s /usr/sbin/nologin -r -M cloudflared
sudo chown cloudflared:cloudflared /usr/local/bin/cloudflared

Create systemd service

sudo nano /etc/systemd/system/cloudflared.service

Paste:

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

[Service]
User=cloudflared
ExecStart=/usr/local/bin/cloudflared proxy-dns \
  --port 5053 \
  --upstream https://1.1.1.1/dns-query \
  --upstream https://1.0.0.1/dns-query
Restart=on-failure

[Install]
WantedBy=multi-user.target

Enable + start:

sudo systemctl daemon-reexec
sudo systemctl enable cloudflared
sudo systemctl start cloudflared
sudo systemctl status cloudflared

Verify DoH proxy works

dig @127.0.0.1 -p 5053 google.com

If you get an answer, DoH is working.

Pi-hole configuration

Admin → Settings → DNS

  • Disable all built-in upstreams (Google, Cloudflare, etc.)
  • Custom DNS server:
127.0.0.1#5053

Pi-hole now sends all DNS encrypted via HTTPS

Android gotchas

Problem

  • Android ignores Wi-Fi DNS if Private DNS is ON
  • Android may race DNS 2 over DNS 1
  • This causes Pi-hole bypass

Hopping through the hoops

  • Wi-Fi → IP settings → Static
  • DNS 1:
192.168.1.x
  • DNS 2:
(empty, DO NOT SET)
  • Private DNS: OFF

Why DNS 2 breaks things

  • Android may race DNS servers
  • If DNS 2 = Google/Cloudflare = ads leak through
  • iOS does not do this (based)

What DoH gives you

Pi-hole blocks ads locally. Cloudflared encrypts all DNS queries leaving your house using HTTPS. Your ISP cannot see, log, inject or tamper with DNS requests. Only Pi-hole sees domains; upstream sees encrypted traffic only.

No ports forwarded. No inbound exposure. Clean outbound encryption.

Architecture

flowchart LR
    A[Android / iOS] --> B[Pi-hole]
    B --> C[cloudflared]
    C --> D[Cloudflare DNS]
Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment