A DNS Block That Looks Like a TLS Error (HTTPS-First vs Pi-hole)¶
🛑 Problem¶
A site that unquestionably supports HTTPS — gemini.google.com, say — refuses to load, and the browser shows:
This site doesn't support a secure connection Attackers can see and change information you send or receive from the site.
The message points squarely at TLS. There is a "Continue to site" button, implying an HTTP fallback exists. Neither is true: the site's TLS is fine, and continuing will not help. The domain is being blocked at DNS, and the browser is misreporting why.
This is the modern counterpart to the older ERR_CONNECTION_REFUSED symptom (see Pi-hole AI Blocklist Blocks Claude Desktop) — same root cause, different-looking error, because browsers changed.
🔁 Why This Happens¶
Pi-hole in NULL blocking mode answers blocked domains with 0.0.0.0.
Browsers now default to HTTPS-First (Chrome, Edge, Helium, and Chromium forks generally). The sequence:
- Browser resolves
gemini.google.com→0.0.0.0from the blocking resolver. - HTTPS-First insists on
https://and opens a TCP connection to0.0.0.0. - That connection cannot complete a TLS handshake — there is nothing there.
- The browser cannot distinguish "no TLS at this address" from "this server doesn't do HTTPS," so it emits its generic insecure-connection interstitial.
The DNS block is never surfaced. The browser has no idea the resolver lied to it — 0.0.0.0 is a perfectly well-formed DNS answer.
Important
Treat "doesn't support a secure connection" on a site that obviously supports HTTPS as a DNS block until proven otherwise. Reach for dig before you touch certificates, clocks, or TLS settings. Chasing this as a TLS problem is a dead end — there is no certificate to inspect, because there is no server.
🔍 Diagnosis¶
The tell is a disagreement between your resolver and a public one. One command:
dig +short example-blocked-domain.com # your resolver
dig +short @1.1.1.1 example-blocked-domain.com # public resolver
| Result | Meaning |
|---|---|
Local → 0.0.0.0, public → real IPs |
DNS block. Continue below. |
| Both → real IPs | Not a DNS block; it may genuinely be a TLS problem. |
Both → NXDOMAIN |
The domain really is gone. |
Confirm which resolver you're actually using — a VPN or tailnet may be supplying one you didn't expect:
Ask Pi-hole what blocked it¶
The single most useful command, run on the Pi-hole host:
It names the offending adlist directly:
Found 1 lists exactly matching 'example-blocked-domain.com'.
- https://raw.githubusercontent.com/NotaInutilis/Super-SEO-Spam-Suppressor/main/hosts.txt (block)
✅ Fix¶
Add an exact allowlist entry (domainlist type 0), which overrides any gravity/adlist block:
Verify it landed, and that the domain now resolves:
sudo sqlite3 /etc/pihole/gravity.db \
"SELECT id, type, enabled, domain FROM domainlist WHERE domain = 'example-blocked-domain.com';"
# → 427|0|1|example-blocked-domain.com (type 0 = exact allow, enabled)
dig +short @<pihole-ip> example-blocked-domain.com # → real IPs, not 0.0.0.0
Then hard-reload the page (Ctrl/Cmd + Shift + R). The browser caches the failed HTTPS attempt and will keep showing the interstitial against a now-working domain otherwise.
Note
Prefer allowlisting the specific domain over dropping the adlist. A list can be simultaneously wrong about one domain and valuable for the other several hundred thousand.
🎯 Why Broad Adlists Cause This¶
The lists most likely to catch a legitimate service are the largest ones, and AI/SEO-oriented lists are the usual suspects — they enumerate AI endpoints and scraper hostnames by domain, sweeping up the consumer-facing product alongside them.
| List | Scale | Notes |
|---|---|---|
| HaGeZi TIF | ~1.6M | Most aggressive; first suspect for any unexpected block |
| Super-SEO-Spam-Suppressor | ~815k | Mostly typosquat/phishing, but blocks gemini.google.com and ai.google |
| OISD | ~485k | Broad |
| uBlockOrigin HUGE AI | ~2.2k | Targets AI endpoints by design; blocks claude.ai |
If you run several of these, expect a steady trickle of false positives on AI services specifically. That is a reason to keep an allowlist, not necessarily to drop the lists.
🔧 Make It Survive a Rebuild¶
An allowlist entry added with pihole allow lives only in gravity.db. Rebuild the host, or restore a Teleporter backup, and it is gone — and the failure returns wearing the same misleading TLS costume.
Declare allowlisted domains in configuration management instead. An Ansible sketch:
# reconcile gravity.db against the declared list
- name: Read existing exact allowlist entries
ansible.builtin.command:
cmd: sqlite3 /etc/pihole/gravity.db "SELECT domain FROM domainlist WHERE type=0;"
register: existing_allow
changed_when: false
check_mode: false # must run under --check so the task below evaluates honestly
- name: Add missing allowlist domains
ansible.builtin.command:
cmd: "pihole allow {{ item }}"
loop: "{{ pihole_allowlist }}"
when: item not in (existing_allow.stdout_lines | default([]))
changed_when: true
notify: reload pihole lists
Warning
command tasks are skipped in check mode by default. Without check_mode: false on the read task, a --check run reports a pending change on a host that is already correct — and, worse, tells you nothing about whether the reconcile logic works. Verify idempotency with a real run, not a dry one.
Run the allowlist step on its own with --tags allowlist.
🔎 Quick Reference¶
# 1. Is it DNS? (resolver disagreement = yes)
dig +short blocked.example.com
dig +short @1.1.1.1 blocked.example.com
# 2. What blocked it?
ssh <pihole-host> 'pihole -q blocked.example.com'
# 3. Allow it
ssh <pihole-host> 'sudo pihole allow blocked.example.com'
# 4. Confirm
dig +short @<pihole-ip> blocked.example.com
# 5. Hard-reload the browser (Cmd/Ctrl + Shift + R)
See Also¶
- Pi-hole AI Blocklist Blocks Claude Desktop (ERR_CONNECTION_REFUSED) — same root cause, pre-HTTPS-First symptom
- A Pi-hole Block Reaches an AI Agent as an SSRF-Guard Error — same root cause, surfaces inside an AI agent's fetch tool
- Pi-hole v6 Adlist Management via SQL
- Pi-hole v6 Group Management — Per-Client DNS Rules