Skip to content
acchuangPublic

About

Browser-based network diagnostics: DNS security (8 resolvers probed over RFC 8484 wire format, ECS leak + DNSSEC checks), speed/bufferbloat test, ad blocker analysis, security header scanning. No installs, no accounts — Cloudflare Workers + TypeScript + Vite.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

NetCheck

Browser-based network diagnostics toolkit — DNS security, speed test, ad blocker analysis, and HTTP security header scanning. No installs, no accounts; every check runs client-side against Cloudflare's edge network.

Live: netcheck.oilygold.xyz

Features

DNS Check

  • Public IP detection with geolocation, ISP/ASN, and Cloudflare PoP
  • Reachability and latency testing across 8 public resolvers (Cloudflare, Google, Quad9, OpenDNS, AdGuard DNS, Cloudflare Families, NextDNS, Mullvad), probed over RFC 8484 DoH wire format so every resolver that supports DoH answers
  • Security assessment: DNSSEC validation, DNS-over-HTTPS, malware/tracker filtering, WebRTC IP leak detection
  • Encrypted-DNS verdict takes the worst hop, not the best one: a router that forwards to your ISP's resolver, which forwards to Cloudflare, is reported as plaintext on the first hop rather than as encrypted because a recognised operator appeared somewhere in the chain
  • ECS leak detection — flags resolvers that forward your client subnet upstream, and (with the probe below enabled) reports the subnet a hop actually forwarded about you, encrypted path or not
  • Interactive lookup tool for A, AAAA, MX, NS, TXT, CNAME, SOA, SRV records

Speed Test

  • Download/upload bandwidth, latency, and jitter against Cloudflare's edge, speed.cloudflare.com, Netflix's fast.com, or Ookla Speedtest servers (nearest found via your city — proxies only the tiny discovery call; speed traffic goes browser → server direct)
  • Bufferbloat / loaded-latency grading — latency increase under a saturated link, taken from whichever direction queued worse, with loaded pings capped at 3s so a stalled probe counts instead of vanishing
  • Progressive chunk sizing that adapts to connection speed: steps under 5 MB are warm-up only (TCP slow start is excluded from the clock), and the measured steps run 4 connections wide so a fast link isn't bounded by a single stream's window
  • Letter grades (A+ to F) for both raw speed and bufferbloat

Ad Block Test

  • 25+ tests across 6 categories: contextual ads, analytics & tracking, banner/display ads, error monitoring, social trackers, cookie/consent annoyances
  • Fingerprint surface reported in its own panel, outside the score: clock precision, canvas readback stability, unmasked GPU model, core count, device memory and time zone, read from the APIs a fingerprinter would call
  • Scores your blocker 0–100 with per-category breakdowns and per-test "why blocked" detail; categories are weighted by importance (high/medium/low) so blocking serious trackers counts more than cosmetic ads
  • Detects 10 filter lists (EasyList, EasyPrivacy, Fanboy's Annoyances/Social, Peter Lowe's, Malware Domains, uBlock Filters, AdGuard Base/Tracking) plus Acceptable Ads whitelist status
  • Identifies which blocker you're likely running (Brave Shields, uBlock Origin, AdGuard, browser-native, etc.)
  • Test any custom URL as script + image

Security Headers

  • Scans any URL's HTTP response and grades it A–F against 10 security headers (HSTS, CSP, X-Frame-Options, COOP/COEP/CORP, etc.)
  • Multi-hop SSRF guard with private/loopback/link-local/multicast IP filtering (IPv4, IPv6, and IPv4-mapped IPv6) and redirect destination re-validation, rate-limited per IP
  • Explains what each header protects against and flags what's missing

Also

  • Speed and ad-block results snapshot to local storage, with color-coded deltas between runs
  • Memory-efficient streaming speed downloads via ReadableStream
  • PWA with offline precaching and responsive Linear-inspired dark/light theme
  • Export a full diagnostic report as Markdown or printable PDF — nothing leaves your device
  • Bilingual UI (English / Traditional Chinese) with full keyboard accessibility
  • Worker API endpoints that fan out server-side (headers scan, resolver checks, DNS compare) are per-IP rate-limited via Cloudflare's Rate Limiting binding, which counts across isolates; an in-worker counter is the fallback for wrangler dev
  • Speed-test endpoints are limited by bytes moved per IP per minute, not by request count — egress is the cost there

Optional: recursion-path probing (self-hosted)

Off by default, and off on netcheck.oilygold.xyz. This is the one check that needs a server outside Cloudflare, because Workers cannot serve UDP/53.

probe-server/ is an authoritative nameserver for a zone you delegate to it. The browser resolves <label>.<your-zone>, which forces every recursive resolver in the visitor's real path to query that nameserver directly — so it sees their actual resolver IPs, and any EDNS Client Subnet forwarded. A DoH-only page can never learn this about its visitor, because it only ever talks to the one resolver it picked.

The label is the SHA-256 of a read key the visitor's tab keeps to itself. Every resolver in the path sees the label, and so do the nameserver's own logs, so observing a query must not be enough to read the result back: only the key names the session, and it never travels in a DNS query. The Worker presents the key over TLS to fetch the result.

Enable it by setting all three on the Worker:

Variable Where Example
PROBE_SERVER_URL wrangler.toml [vars] https://ns-probe.example.com:8443
PROBE_ZONE wrangler.toml [vars] p.example.com
PROBE_SECRET wrangler secret put —

The URL must be https:// (localhost excepted): PROBE_SECRET travels in a request header, so a plaintext URL is refused and reported as unconfigured rather than sent in the clear.

With any of them missing, the client is told the probe does not exist here: it skips the lookup entirely, and the DNS card drops both the encrypted-DNS row and the "your recursive resolver" block rather than showing a check it cannot answer.

Running the nameserver — GCP always-free VM, zone delegation, systemd unit, and the reflection-hardening notes — is documented in probe-server/README.md.

Tech Stack

  • Runtime: Cloudflare Workers, static assets via the Workers Assets binding
  • Frontend: Vite + TypeScript, compiled to vanilla JS/CSS (no framework)
  • Build: @cloudflare/vite-plugin — Workers runtime integrated directly into Vite dev/build
  • Design System: Linear-inspired dark theme — Inter Variable, #08090a canvas, indigo-violet accents
  • DNS Lookups: resolvers probed over RFC 8484 DNS wire format (DoH POST) with a hand-rolled encoder/decoder in src/shared/dns-wire.ts; interactive lookups via Cloudflare DNS-over-HTTPS

Project Structure

netcheck-site/
├── wrangler.toml              # Cloudflare Worker config
├── vite.config.ts             # Vite build configuration (Cloudflare plugin)
├── tsconfig.json              # TypeScript configuration
├── index.html                 # Single-page app shell
├── probe-server/              # Authoritative nameserver for recursion-path probing
├── src/
│   ├── client/                # Frontend logic (TypeScript)
│   │   ├── app.ts             # Entry point — tab routing, UI orchestration
│   │   ├── i18n.ts            # Bilingual (en/zh-TW) translation strings
│   │   └── ...                # Domain-specific logic (dns-check, speed-test, adblock-test, etc.)
│   ├── shared/                # Code shared between client, worker and probe server
│   │   ├── dns-wire.ts        # RFC 8484 wire-format encoder/decoder
│   │   └── resolvers.ts       # Public DNS resolver list
│   └── worker/                # Backend logic (TypeScript)
│       └── index.ts           # Worker — API routes
└── public/
    ├── icon.svg, manifest.json, sw.js
    └── css/styles.css         # Linear design system implementation

Development

npm install
npm run dev        # Vite dev server with the Cloudflare Workers runtime
npm run typecheck  # tsc --noEmit
npm test           # node --test — no framework, no browser, no network

To exercise the recursion probe locally, put the three variables in a gitignored .dev.vars and run the nameserver alongside the dev server — see probe-server/README.md for the local port to use (5354; mDNS holds 5353 on macOS).

Deployment

npm run deploy       # vite build && wrangler deploy

License

MIT

About

Browser-based network diagnostics: DNS security (8 resolvers probed over RFC 8484 wire format, ECS leak + DNSSEC checks), speed/bufferbloat test, ad blocker analysis, security header scanning. No installs, no accounts — Cloudflare Workers + TypeScript + Vite.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages