Skip to content

jstoneky/nextdns-medic

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

216 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DNS Medic

See exactly what your DNS blocker is blocking — and why it matters.

A browser extension for Chrome, Firefox, Firefox for Android, and Safari that watches your network traffic in real-time, identifies domains blocked by NextDNS, Pi-hole, or Control D, and tells you the functional impact — whether a block might break login, stop videos from loading, prevent checkout, hide maps, or silence support chat.

Chrome Firefox Firefox Android Safari

DNS Medic


The Problem

NextDNS, Pi-hole, and other DNS-level blockers work great for privacy, but they can cause subtle breakage on websites. A feature flag service gets blocked, and suddenly an inventory page won't load. An auth provider is blocked, and login silently fails. A payment processor is blocked, and checkout never completes. You reload the page six times wondering what's wrong, never knowing DNS was the culprit.

This extension makes that visible — and tells you exactly what's at stake.


How It Works

  1. Monitors network errors on every tab using the browser's webRequest API
  2. Identifies DNS-block signatures — certificate issuer failures, name resolution errors, and other patterns that indicate a DNS-level block (not a server error or timeout)
  3. Classifies every blocked domain against a database of 561 known services across 27 categories, grouped by how likely they are to break site functionality:
    • 🔴 High — Feature flags, authentication, payment processors, search APIs, core CDNs, CAPTCHA. These break sites.
    • 🟡 Medium — Support chat, video players, maps, image CDNs, error monitoring, e-commerce. May affect functionality depending on the site.
    • 🟢 Low — Pure analytics and advertising. Almost never affects how a site works.
  4. Shows a functional impact badge on every blocked domain — so you know at a glance what breaks, not just that something broke
  5. Attributes the block to a specific blocklist — works for both NextDNS (from the logs API) and Pi-hole v6 (via the gravity search API, with pretty names for 30+ common lists)
  6. Confirms DNS routing — a live status chip in the header shows whether your browser is actually sending DNS through your selected provider (green = active, red = not routing)
  7. Unknown domains fall back to Medium — worth reviewing, but not necessarily critical
  8. Badge updates on the extension icon: count of blocked domains, red = high-risk detected

Popup UI

Click the extension icon on any page to see:

  • Stats bar — counts of High / Medium / Low blocked domains; click any level to filter
  • Impact badge — color-coded tag on every domain showing the functional consequence of blocking it (see Impact Badges below)
  • Blocklist attribution — which blocklist rule flagged the domain (HaGeZi, AdGuard, uBlock Origin, etc.)
  • Grouped list — blocked domains sorted by risk, showing service name, error type, and hit count
  • 📋 Copy button — copies the domain to clipboard; works with NextDNS, Pi-hole, AdGuard, or any DNS blocker
  • + Allowlist button — one click adds the domain to your NextDNS, Pi-hole, or Control D allowlist (requires credentials)
  • DNS flush reminder — appears after every allowlist/copy action with the exact command for your OS
  • DNS routing status chip — green/red indicator in the header confirming your DNS is actually going through the selected provider
  • Profile indicator — NextDNS profiles are fingerprint-matched; your current device's profile is labeled "This device"

Impact Badges

Every blocked domain carries a color-coded badge showing the functional impact of the block — not just how risky it is, but specifically what it might break:

Badge Color What it means Example categories
login/forms 🔴 Red Could prevent login, registration, or form submission Auth, payments, CAPTCHA
media/maps/assets 🔵 Blue Could break video playback, maps, or page assets Video players, maps, image CDNs, CDN
chat 🟢 Green Could hide or disable support chat widgets Support chat, real-time
feature flags 🟣 Purple Could silently change or disable site features Feature flags
search 🩵 Cyan Could break search or autocomplete Search APIs
monitoring ⚫ Black Could disable error reporting or observability Error monitoring

These badges are independent of the High/Medium/Low risk rating — a "Low" domain can still carry a monitoring badge so you know what's affected.


Setup

Install

Chrome: Load unpacked via chrome://extensions → Developer mode → Load unpacked (select the folder)

Firefox: Load via about:debugging → This Firefox → Load Temporary Add-on (select the zip)

Firefox for Android: Install Firefox Nightly → open about:config → set xpinstall.signatures.required to false → open about:Firefox → tap the logo 5× to unlock debug menu → Install Extension from File → select the .xpi

Safari (macOS): Download dns-medic-safari-macOS-v*.zip from Releases → unzip → drag DNS Medic.app to Applications → right-click → Open (required once to bypass Gatekeeper) → Safari → Develop → Allow Unsigned Extensions → Safari → Settings → Extensions → enable DNS Medic.

Note: "Allow Unsigned Extensions" resets every time Safari quits — re-enable it each session until the Mac App Store version is available.

Chrome and Firefox desktop will be available on their respective extension stores once reviewed.

Configure your DNS provider (optional)

Click the extension icon → ⚙️ Settings → select your provider:

NextDNS

  • API Key — found at my.nextdns.io → Account → API; hit → to load profiles
  • The extension fingerprint-matches your device to the right profile and labels it "This device"

Pi-hole

  • URL — e.g. http://pi.hole or your Pi-hole's IP address
  • API Token — Pi-hole v6: your web UI password · Pi-hole v5: Settings → API
  • Both Pi-hole v5 and v6 are auto-detected

Control D

  • API Token — generate at controld.com → Account → API Tokens (use Write permission)
  • Hit → to load your profiles and select the one to allowlist into

Without credentials the extension still monitors and classifies — you just won't have the one-click allowlist button. Use the 📋 copy button to manually add domains in your DNS blocker's dashboard.


Browser Compatibility

Browser Manifest Background Status
Chrome 109+ MV3 Service Worker ✅ Supported
Firefox 140+ MV2 Background Scripts ✅ Supported
Firefox for Android MV2 Background Scripts ✅ Supported
Safari (macOS) MV2 Background Scripts ✅ Supported (Beta)
Edge MV3 Service Worker ✅ Should work (untested)

Firefox note: Requires Firefox 140+ due to use of the data_collection_permissions manifest field. NextDNS blocks appear as certificate issuer errors in Firefox (e.g. "Peer's Certificate issuer is not recognized"). The extension detects these correctly, including the curly-apostrophe variant (U+2019) that Firefox uses internally.

Firefox for Android: Install via Firefox Nightly. Enable debug mode: about:Firefox → tap the logo 5× → Install Extension from File. The popup is fully responsive and fills the panel width on mobile.

Safari (macOS): Detects blocked requests using Safari's ERR_ABORTED signal. Known tracker domains are classified immediately; unknown aborted domains appear in a separate ⚪ Unverified section. For NextDNS users, unverified domains are automatically confirmed using the NextDNS logs API when the popup is opened. Note: "Allow Unsigned Extensions" resets every time Safari quits — re-enable it each session until the Mac App Store version is available.


Domain Classification Database

The extension ships with a bundled database of 561 entries across 27 categories and automatically fetches updates from this repository. The database is cached locally for 7 days and can be force-refreshed from the Settings panel at any time.

Coverage

Category Examples Risk Impact Badge
Feature Flags Statsig, LaunchDarkly, Split.io, Optimizely, PostHog, GrowthBook, ConfigCat 🔴 High 🟣 feature flags
Authentication Auth0, Okta, Clerk, Kinde, Stytch, WorkOS, Firebase Auth, AWS Cognito, Azure AD 🔴 High 🔴 login/forms
Payment Processors Stripe, Braintree, PayPal, Klarna, Adyen, Affirm, Afterpay, Square 🔴 High 🔴 login/forms
Search APIs Algolia, Constructor.io, Searchspring, Klevu, Bloomreach, Coveo, Yext 🔴 High 🩵 search
CDN Cloudflare, Fastly, Akamai, jsDelivr, unpkg, Google APIs, AWS 🔴 High 🔵 media/maps/assets
Real-time / WebSocket Pusher, Ably, Twilio, LiveKit, Daily.co, Agora 🔴 High 🟢 chat
CAPTCHA reCAPTCHA, hCaptcha, Turnstile, FunCAPTCHA, GeeTest 🔴 High 🔴 login/forms
A/B Testing VWO, AB Tasty, Convert.com, Kameleoon, Optimizely Web 🔴 High 🟣 feature flags
Video Players YouTube Embed, Vimeo, Wistia, Mux, Brightcove, JW Player, Kaltura 🟡 Medium 🔵 media/maps/assets
Maps Google Maps, Mapbox, HERE Maps, MapTiler, OpenStreetMap tiles 🟡 Medium 🔵 media/maps/assets
Support Chat Intercom, Zendesk, HubSpot, Drift, Crisp, Freshchat, LiveChat 🟡 Medium 🟢 chat
Notifications OneSignal, Pushwoosh, Airship, Braze, Iterable, Attentive, Klaviyo 🟡 Medium 🟢 chat
Image CDNs Cloudinary, Imgix, Fastly Image Optimizer, Thumbor, ImageKit 🟡 Medium 🔵 media/maps/assets
Error Monitoring Sentry, Datadog RUM, New Relic, Bugsnag, Rollbar, Raygun 🟡 Medium ⚫ monitoring
Session Replay Hotjar, FullStory, LogRocket, Mouseflow, Lucky Orange, Contentsquare 🟡 Medium ⚫ monitoring
E-commerce Shopify, Affirm, Klarna widgets, Yotpo, Bazaarvoice, Stamped 🟡 Medium 🔴 login/forms
Reviews Yotpo, Bazaarvoice, Trustpilot, Okendo 🟡 Medium 🔵 media/maps/assets
Headless CMS Contentful (ctfassets.net), Storyblok, Sanity, DatoCMS 🟡 Medium 🔵 media/maps/assets
Tag Manager Google Tag Manager, Tealium, Ensighten, Segment 🟡 Medium ⚫ monitoring
Consent Cookiebot, Quantcast Choice, OneTrust, TrustArc 🟡 Medium 🔴 login/forms
Analytics Google Analytics, Mixpanel, Amplitude, Segment, Heap, Chartbeat 🟢 Low ⚫ monitoring
Advertising Google Ads, Facebook Pixel, AdRoll, Taboola, Outbrain 🟢 Low ⚫ monitoring
Animation LottieFiles (lottie.host) 🟡 Medium 🔵 media/maps/assets
Localization Crowdin CDN 🟡 Medium 🔵 media/maps/assets
Call Tracking CallRail, CallTrackingMetrics, WhatConverts 🟢 Low ⚫ monitoring
SEO Semrush, Moz, similar SEO toolbars 🟢 Low ⚫ monitoring

Dynamic updates

The database is maintained in domain-db.json in this repo. On first load the extension fetches the latest version and caches it for 7 days. If the fetch fails for any reason, the bundled fallback is used transparently. No version bump required — the DB updates silently in the background.

Security: The remote DB is fetched as JSON only — never eval'd or executed. Every entry is validated against a strict schema (pattern allowlist, length caps, confidence enum) before being compiled into RegExp objects. Each regex test is wrapped in try/catch for ReDoS isolation.


Supported DNS Blockers

Provider One-click Allowlist Blocklist Attribution Profile Auto-detect Routing Detection
NextDNS ✅ via REST API ✅ (HaGeZi, AdGuard, etc.) ✅ "This device" fingerprint ✅ test.nextdns.io
Pi-hole v5 ✅ via API Token ✅ pi.hole magic domain
Pi-hole v6 ✅ via API Token ✅ (HaGeZi, OISD, Steven Black, etc.) ✅ pi.hole magic domain
Control D ✅ via API Token ✅ profile picker ✅ dns.controld.com
Any other 📋 Copy to clipboard

Building

# Build both Chrome and Firefox (runs tests first)
./build.sh all

# Build for a specific browser
./build.sh chrome
./build.sh firefox

# Remove old artifacts from store/dist/
./build.sh clean

The build script runs the full test suite before building. If any test fails, the build is aborted. Old version artifacts are automatically cleaned from store/dist/ before each build.

Output goes to store/dist/.


Testing

# Run all tests
npm test

# Run specific suites
npm run test:domain   # Domain classification (561 entries, 27 categories)
npm run test:errors   # Error string detection (24 tests)
npm run test:build    # Build artifact validation (41 tests)

No dependencies — uses Node's built-in node:test runner. Tests cover:

  • Domain classification accuracy across all 27 categories
  • Chrome and Firefox error string matching (including curly-apostrophe edge case)
  • False-positive rejection (NS_BINDING_ABORTED, ERR_TIMED_OUT, etc.)
  • extractHostname() edge cases
  • Manifest schema validation (MV3 and MV2)
  • Build artifact existence and size

Privacy

This extension:

  • Does not collect or transmit any personal data
  • Does not store browsing history — all data is session-only and cleared on navigation
  • Only stores hostnames, never full URLs or page content
  • Fetches domain-db.json from GitHub on first load and every 7 days (no user data sent)
  • Your NextDNS API key is stored locally in browser sync storage

Full privacy policy: store/PRIVACY.md


Tech Stack

  • Browser Extension (Chrome MV3 / Firefox MV2)
  • Vanilla JS — no build step, no framework dependencies
  • webRequest.onErrorOccurred — request error monitoring
  • webNavigation.onCommitted — tab lifecycle management
  • storage.local — DB caching
  • storage.sync — settings sync across devices
  • navigator.clipboard — copy to clipboard
  • NextDNS REST API — allowlist management
  • browser-compat.js — cross-browser API shim (chrome.*browser.*)
  • db-loader.js — remote DB fetch, validation, and cache management

Store Assets

store/
├── PRIVACY.md              # Shared privacy policy
├── chrome/
│   ├── LISTING.md          # Chrome Web Store listing copy
│   ├── icon-128-store.png  # 128×128 store icon
│   ├── promo-tile-440x280.jpg
│   ├── marquee-1400x560-v2.3.jpg
│   └── screenshots/        # 1280×800 PNG (5 screenshots)
└── firefox/
    ├── LISTING.md          # Firefox Add-ons listing copy
    └── screenshots/        # Same screenshots, Firefox-compatible

Contributing

PRs welcome. Most useful contributions:

  • New entries in domain-db.json — add real hostnames with correct confidence, category, and impact badge
  • Confidence corrections — if a domain is miscategorized, open a PR with justification
  • Impact badge corrections — if the functional impact label is wrong, fix it with reasoning
  • Blocklist attribution data — if you know which blocklist targets a domain, add it
  • New categories — e.g. identity verification, streaming infrastructure, live events
  • Safari iOS port — currently macOS only; iOS needs a content script heuristic approach
  • Edge port
  • Automated integration tests

When adding entries to domain-db.json, match the schema:

{ "pattern": "exact\\.domain\\.com", "flags": "", "label": "Category (Service Name)", "confidence": "HIGH", "category": "feature-flags" }

Run npm test before submitting — the test suite validates every entry and will catch malformed patterns or invalid confidence values.


Changelog

v2.5.0

  • Flush banner copy button — visible styled button with "Copied!" confirmation state
  • Android flush banner — removed Reload button; shows full plain-English instructions with proper text wrapping

v2.4.0

  • Firefox for Android support — responsive layout fills the full panel width on mobile
  • API key validation — entering a bad key on the → button now shows a red error; nothing is saved
  • Cookie bypass fix — all NextDNS API calls now use credentials: omit; browser session cookies can no longer silently authenticate garbage keys
  • Android DNS flush — replaced shell command with mobile-friendly instructions and a Reload button
  • Popup width — 440px on desktop, fluid on mobile; height grows with content

v2.3.1

  • Fixed popup icon — replaced hardcoded 🛡️ emoji with the actual extension icon

v2.3.0

  • Pi-hole blocklist attribution — blocked domains now show which gravity list flagged them (uses /api/search/{domain}). Pretty-name map for 30+ popular lists: HaGeZi, Steven Black, OISD, AdGuard DNS filter, EasyList/EasyPrivacy, Disconnect.me, Energized, URLhaus, and more. Unknown lists fall back to their hostname.
  • Previously only available for NextDNS users — now works for Pi-hole v6 too

v2.1.0

  • Expanded domain database — 492 entries across 13 categories (+146 new entries: CAPTCHA, video players, maps, support chat, image CDNs, error monitoring)
  • Functional impact badges — every blocked domain now shows a color-coded badge describing the specific consequence (login, media, maps, chat, features, assets, monitoring, notifications)
  • New extension icon — dark shield with cyan medical cross and pulse line

v2.0.0

  • Pi-hole support — allowlist directly to Pi-hole v5 or v6 (auto-detected)
  • NextDNS profile auto-detect — fingerprints your device against your profiles; no manual profile ID needed
  • DNS provider toggle — switch between NextDNS and Pi-hole in settings

v1.4.0 – v1.4.1

  • Risk-level filter — click HIGH / MEDIUM / LOW stats bar to filter the block list
  • DNS flush reminder banner — shows exact OS-aware command after every allowlist/copy action

v1.3.0

  • DNS flush banner after allowlist actions

v1.2.0

  • Copy to clipboard button
  • Remote domain database with 7-day cache and force-refresh

v1.1.0

  • Firefox support (MV2)
  • Dynamic remote domain database

Support

If DNS Medic saved you a headache, buy me a coffee ☕ — it's appreciated but never expected.

License

MIT


This application was built with the help of AI.

About

See exactly what your DNS blocker is blocking — and why it matters.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors