A tablet on a healthy network could not resolve anything. The DNS server answered the bare name correctly — NOERROR, two records, A and AAAA, with and without EDNS0 — so the earlier finding blamed the device's resolver. It was wrong. The network advertised hudelist.local as a search domain and the server silently dropped every query under it: not NXDOMAIN, nothing at all. Resolvers append search domains, so they waited for a reply that was never coming. Silence is the part that makes this vicious. A negative answer moves a resolver on; no answer looks like packet loss, so it retries, and some give up on the lookup entirely. It also explains how two devices on one network can disagree about whether DNS works — the phone tried the plain name first and never noticed. The probe now asks about a nonce name under each advertised search domain, where the wanted answer is NXDOMAIN and only silence is a fault. The finding is ordered ahead of dns.system_resolver_broken so the two cannot both fire: without that, this exact network gets told its device is broken. Severity follows the harm rather than the shape. HIGH when resolution is actually failing, MEDIUM when the domain is a black hole but this resolver happens to try the plain name first — calling that HIGH would be crying wolf on a network that works. The message names the fix and notes that .local is reserved for mDNS by RFC 6762 and widely dropped by design, while home.arpa (RFC 8375) is the name reserved for this. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Echolot
Free software for detecting and debugging local network issues from an Android phone — built for people who actually know what a neighbor table is.
Most "wifi analyzer" apps show you signal bars. Echolot aims at the layer where home and office networks actually break: duplicate DHCP servers, broken IPv6 RAs, MTU black holes, NAT64 weirdness, multicast that dies at the AP, DNS that answers differently than it should. It records what it observed, separates observation from interpretation, and exports the whole run so you can argue with it later.
Status: pre-release. The capability prober runs on real hardware; the production app and the probe server are not built yet.
Repository layout
docs/ design docs — the contract for everything below
echolot-prober/ capability prober: validates the no-root feasibility matrix on real devices
The Go probe server and the production app land here as siblings.
Design docs
The three specs are draft-complete and reviewed; treat them as the contract.
| Doc | What it defines |
|---|---|
| docs/feature-catalog-and-feasibility.md | Full feature list + the no-root feasibility matrix |
| docs/measurement-schema.md | Archived/exportable measurement JSON (observation vs finding, two-clock rule, anonymization) |
| docs/probe-protocol.md | Client↔server wire protocol (pinned TLS control plane, binary UDP data plane, STUN, canary DNS) |
| docs/build-status.md | Running log of decisions and next steps |
Privilege tiers
Every result records which tier produced it:
app— no root, no special setup. The bulk of the functionality.shizuku— ADB-shell privileges via wireless pairing, no root. Shipped in v1.root— future optional module.
Licensing
| Part | License | Why |
|---|---|---|
| All code (app, prober, server) | GPL-3.0-or-later | The value here is the platform-API research; copyleft keeps derivative apps free |
docs/ (the specs) |
CC-BY-4.0 | A wire protocol and a measurement format should be implementable by anyone, without license anxiety |
Full texts: LICENSE (GPLv3) and docs/LICENSE (CC BY 4.0).
Sources carry SPDX-License-Identifier headers.
If you want to build a compatible server or client, the protocol and schema docs are deliberately permissive — go ahead.
Building
See echolot-prober/README.md. Short version, from echolot-prober/:
echo "sdk.dir=/path/to/Android/sdk" > local.properties
./gradlew :app:assembleDebug