7.3 KiB
Pi-hole v6 Diagnostics
Quick-start for diagnosing "is Pi-hole causing my network issues?" questions. Pi-hole v6 changed the API, CLI, and database schema — the old pihole -c (chronometer), /admin/api.php, and v5 commands don't work.
Decision Flow
- Check if Pi-hole is even the problem before digging in. If DNS resolves through Pi-hole and no essential domains are blocked, the issue is at the WiFi/router/IP level — not Pi-hole.
- If Pi-hole might be the culprit, query its SQLite database directly.
Docker Status
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep pihole
Pi-hole v6 container info:
- Status should show
healthy - Binds port 53 TCP+UDP to host IP (typically
192.168.50.X:53) - Web UI on port 80 inside container, mapped to host (e.g.,
8090:80)
Pi-hole Process Check
docker exec pihole pihole status
Expected output:
[✓] FTL is listening on port 53
[✓] UDP (IPv4)
[✓] TCP (IPv4)
[✓] UDP (IPv6)
[✓] TCP (IPv6)
[✓] Pi-hole blocking is enabled
Querying the Database (When Web UI Is Locked)
Pi-hole v6's web API at /api requires authentication (session or app password). When locked out, query the SQLite database directly.
Database Location
- Inside container:
/etc/pihole/pihole-FTL.db - On host (Docker volume):
/var/lib/docker/volumes/pihole_etc/_data/pihole-FTL.db
Access Pattern
The /var/lib/docker directory has drwx--x--- permissions — regular users can't traverse it. Copy the DB to a readable location:
sudo cp /var/lib/docker/volumes/pihole_etc/_data/pihole-FTL.db /tmp/pihole-FTL.db
sudo cp /var/lib/docker/volumes/pihole_etc/_data/pihole-FTL.db-wal /tmp/pihole-FTL.db-wal
sudo cp /var/lib/docker/volumes/pihole_etc/_data/pihole-FTL.db-shm /tmp/pihole-FTL.db-shm
sudo chown $USER:$USER /tmp/pihole-FTL.db*
Then query with Python (the Pi-hole container has no Python/sqlite3):
import sqlite3
conn = sqlite3.connect('/tmp/pihole-FTL.db')
cur = conn.cursor()
# Recent queries
cur.execute("""
SELECT datetime(timestamp, 'unixepoch', 'localtime'), domain, client, status
FROM queries ORDER BY id DESC LIMIT 30
""")
Pi-hole v6 Status Codes
Status codes in the queries table:
| Code | Meaning | Notes |
|---|---|---|
| 1 | GRAVITY_BLOCKED | Domain in blocklist |
| 2 | FORWARDED | Sent to upstream DNS |
| 3 | CACHE | Answered from cache |
| 4 | REGEX_BLOCKED | Matched regex block rule |
| 5 | EXACT_BLOCKED | Exact-match block |
| 6 | UPSTREAM_BLOCKED | Blocked by upstream DNS |
| 9 | CACHE_STALE | Stale cache entry |
| 12 | ALREADY_FORWARDED | Duplicate suppressed |
| 14 | CACHED_BLOCKED | Cached as blocked (from prior CNAME-chain inspection) — this is the dangerous one for false positives |
| 16 | ALREADY_BLOCKED (variant) | Gravity already known |
| 17 | RETRIED | First attempt failed, retry succeeded |
Status 17 is normal — it's the dominant status in v6 and means the query succeeded on retry. It does NOT indicate a problem.
Only status 1, 4, 5, 6 are actual blocks. Everything else = allowed.
Key Diagnostic Queries
Blocked vs Allowed Ratio (last hour)
SELECT CASE WHEN status IN (1,4,5,6) THEN 'BLOCKED' ELSE 'ALLOWED' END, count(*)
FROM queries WHERE timestamp > strftime('%s','now','-1 hour')
GROUP BY 1
Which Clients Are Using Pi-hole
SELECT client, count(*) FROM queries
WHERE timestamp > strftime('%s','now','-1 hour')
GROUP BY client ORDER BY count(*) DESC
Recent Blocked Domains
SELECT domain, count(*) FROM queries
WHERE timestamp > strftime('%s','now','-1 hour') AND status IN (1,4,5)
GROUP BY domain ORDER BY count(*) DESC LIMIT 10
Windows NCSI Pattern (Connectivity Check)
Windows devices query dns.msftncsi.com every ~60 seconds to verify internet connectivity. If this shows status 17 (RETRIED), the device may be reporting "no internet" even though DNS eventually resolves. This is typically an upstream DNS slowness issue, not a Pi-hole problem.
🔥 Primary Pitfall: Deep CNAME Inspection False Positives
This is the #1 cause of "some devices have no internet after DNS change to Pi-hole."
When CNAMEdeepInspect = true (default in v6), Pi-hole follows CNAME chains. If ANY domain in the chain matches a blocklist entry, the ENTIRE chain is cached as blocked (status 14). The blocklist (e.g., StevenBlack) includes subdomains like pagead.l.google.com — these are ad-specific, but CNAME inspection propagates the block to the PARENT l.google.com, which kills ALL services on Google infrastructure.
Affected domains (false positives):
connectivitycheck.gstatic.com— Android TV/Shield connectivity checkdns.msftncsi.com— Windows NCSI connectivity checkgoogle.com— basic connectivityota.nvidia.com— Shield TV updatesclients3.google.com,android.apis.google.com— Google Play Services
Detection: Look for status 14 on these domains:
SELECT domain, count(*) FROM queries WHERE status=14
GROUP BY domain ORDER BY count(*) DESC LIMIT 20;
Fix — whitelist critical domains (preferred):
docker exec pihole pihole -w connectivitycheck.gstatic.com
docker exec pihole pihole -w dns.msftncsi.com
docker exec pihole pihole -w clients3.google.com
docker exec pihole pihole -w ota.nvidia.com
Alternative — disable deep CNAME inspection:
Set CNAMEdeepInspect = false in /etc/pihole/pihole.toml (may allow some CNAME-cloaked ads through).
See also: pihole-troubleshooting skill for full diagnostic workflow.
Red Flags (Pi-hole IS the Problem)
- Essential domains (google.com, microsoft.com, apple.com) appearing with status 1, 4, or 5
- Status 14 on connectivity-check domains (connectivitycheck.gstatic.com, dns.msftncsi.com) — indicates deep CNAME inspection false positive
- Large block percentage (>50%) in last hour
- DNS resolution fails from other hosts:
dig @192.168.50.X google.comtimes out - Pi-hole container unhealthy or in restart loop
Red Herrings (Pi-hole is NOT the Problem)
- Tracking/analytics domains blocked (app-measurement.com, newrelic.com, doubleclick.net) — these are working as intended
- Status 17 (RETRIED) on queries — normal v6 behavior, queries succeed
- Some devices working while others don't — if Pi-hole DNS resolves for any device, the DNS layer is fine; connectivity issues are at WiFi/router/IP level (but FIRST rule out deep CNAME inspection false positives above)
Router Investigation (When Pi-hole Is Ruled Out)
Check the ASUS router at 192.168.50.1:
- System Log → Wireless Log — are affected devices connected?
- Network Map → Clients — do they have valid IPs?
- WiFi Settings — Smart Connect / band steering can confuse some devices. Try separating 2.4 GHz and 5 GHz SSIDs.
Pi-hole v6 API (When You Have the Password)
# Get session
curl -s -X POST "http://192.168.50.X:8090/api/auth" \
-H "Content-Type: application/json" \
-d '{"password":"YOUR_PASSWORD"}'
# Get summary (after auth)
curl -s "http://192.168.50.X:8090/api/stats/summary" \
-H "Authorization: Bearer SESSION_TOKEN"
Other v6 Changes from v5
pihole -c(chronometer) → removed, use PADD/admin/api.php→/api(different path, authentication required)gravity.db→ replaced bygravitytable inpihole-FTL.db- Container has no Python or sqlite3 — query from host