Commit graph

9 commits

Author SHA1 Message Date
Andrew Pimenov
76cfd4605c detect CGNAT, NAT64, and first-hop-vs-path issues separately
- net.cgnat: three evidence paths (local IP, gateway, traceroute hop) for
  RFC 6598 100.64.0.0/10, since the local address alone misses the common
  home-router case
- net.nat64: RFC 7050 ipv4only.arpa AAAA probe (new probes/nat64.py) instead
  of checking the client's own address against 64:ff9b::/96, which never
  fires since that prefix is a synthesis target, not something the client's
  egress address falls into
- path.first_hop_loss/slow/unexpected: path_findings() takes an optional
  LocalNet/Thresholds so loss or latency at hop 1 is attributed to the
  user's own router/Wi-Fi instead of blending into the ISP-facing mid-path
  logic

All four findings are always-on additions to existing report sections, no
new CLI flags. Part of the larger extension batch tracked in
plans/zesty-zooming-wilkinson.md (gitignored, local planning doc).
2026-08-12 21:06:01 +03:00
Andrew Pimenov
3a0f95c793 document L4-L7 diagnostic modules and the python 3.14 bump 2026-08-10 21:26:46 +03:00
Andrew Pimenov
fd72604240 add --interface flag to force outbound probing through a specific adapter
Every probe used to follow whatever the OS default route picked, with no way
to point the tool at a specific adapter for comparison (VPN vs raw) or to
confirm which one actually carries traffic on a multi-adapter machine.

New iface.py resolves an adapter name or IP to a BindTarget (pure, tested):
exact/case-insensitive/unique-substring name match, rejects APIPA-only,
link-local-only and down adapters. Wired through every httpx provider client,
the Ookla binary tier, ndt7, and the whole ping/traceroute cascade (icmplib,
mtr, unix traceroute, TCP connect, scapy) plus --watch. Windows icmp_win now
uses IcmpSendEcho2Ex (adds SourceAddress) only when a bind is forced, so the
unforced path is unchanged. Windows tracert has no IPv4 source-address option
(verified from its own usage text) so that tier is dropped when forced,
noted in the report rather than silently measuring the wrong path.

An unresolvable/down adapter aborts with every adapter listed; a resolvable
adapter with no route to the internet degrades gracefully instead of
aborting - that's a real diagnostic answer, not an error. netinfo's
observation of the OS's actual default route stays untouched, so the report
can show the forced adapter and the OS default side by side.

Verified live: forcing Tailscale (no internet route on this box) triggered
the preflight warning and degraded correctly; forcing Ethernet ran clean
end-to-end including a full speedtest+MTR cycle.

Also noted, not fixed: probes/traceroute.py's icmplib tier imports
async_traceroute, which doesn't exist in icmplib 3.0.4 - that tier has
always raised ImportError and silently fallen through. Found while
verifying the icmplib source-binding wiring live.
2026-08-09 13:36:06 +03:00
Andrew Pimenov
4ffc39906b add --format/--ru/--json flags to control which report artifacts get written
Every run used to write all three files (en.md, ru.md, json) unconditionally.
Default is now English Markdown only, sourced from output.formats in
config.yaml; --format/--ru/--json pick exactly what a run writes, and any
explicit --format replaces the default rather than adding to it (all/none
supported). write_report() moved from a fixed 3-positional-arg signature to
a {format: text} mapping so writes are conditional instead of always-three.
The en/ru Markdown cross-link header is now only set when both languages are
actually being written.
2026-08-09 13:00:13 +03:00
Andrew Pimenov
031f85df5e netsleuth in docs, license, env example and release workflow 2026-08-09 11:43:03 +03:00
Andrew Pimenov
b4c541aecf docs: sync readme, architecture and tasks with the russian report feature 2026-08-09 11:14:56 +03:00
Andrew Pimenov
4497e2a871 docs: sync readme and architecture with the final module and flag set
readme's sample console output showed a multi-line summary table
(connection/egress/vpn/latency) the tool has never printed; the real
stdout is three lines (banner, verdict, file paths). also documented:
the tcptrace/ndt7 extras install command, bare-asn --target syntax,
ndt7's interactive consent prompt, tcp-trace's cascade fallback, and
that --watch writes one artifact per session rather than per tick.

architecture's storage section had the peeringdb cache path wrong
(.cache/peeringdb/*.json vs the real .cache/pdb-net-*.json) and never
mentioned the watch_*.json artifact from task 39. the file-size
exceptions note only covered exporter.py; interpret.py, cli.py,
models.py, bgp.py, ip_geo.py, netinfo.py, speed.py, reputation.py and
probes/traceroute.py all cleared ~200 lines too and are now listed
with the reason each stayed one file. test count updated from ~120
(written before a single module existed) to the real ~385.
2026-08-09 03:58:54 +03:00
Andrew Pimenov
879b974e57 exporter: markdown rendering with sparklines and hop bars 2026-08-09 02:44:43 +03:00
Andrew Pimenov
2a3020cdb9 bilingual readme and architecture docs 2026-08-08 21:21:29 +03:00