Add base subcrates
This commit is contained in:
660
docs/implementation_notes.md
Normal file
660
docs/implementation_notes.md
Normal file
@@ -0,0 +1,660 @@
|
||||
# IMPLEMENTATION.md
|
||||
|
||||
## 0) Project identity
|
||||
|
||||
* **Project name:** WTFnet
|
||||
* **Binary name:** `wtfn`
|
||||
* **Tagline:** *“What the f*ck is my networking doing?”*
|
||||
|
||||
Target OS (first-class):
|
||||
|
||||
* ✅ Linux (Debian/Ubuntu)
|
||||
* ✅ Windows 10/11 + Windows Server
|
||||
|
||||
---
|
||||
|
||||
## 1) Workspace layout (Cargo)
|
||||
|
||||
Recommended workspace structure: keep the CLI thin, keep logic reusable, and isolate OS-specific code.
|
||||
|
||||
```
|
||||
wtfnet/
|
||||
├─ Cargo.toml
|
||||
├─ crates/
|
||||
│ ├─ wtfnet-cli/ # bin: clap parsing + output formatting
|
||||
│ ├─ wtfnet-core/ # shared types: errors, output schema, config, logging init
|
||||
│ ├─ wtfnet-platform/ # platform traits + OS dispatch
|
||||
│ ├─ wtfnet-platform-linux/ # Linux implementations (netlink/procfs)
|
||||
│ ├─ wtfnet-platform-windows/ # Windows implementations (Win32 APIs)
|
||||
│ ├─ wtfnet-geoip/ # GeoLite2 Country+ASN mmdb
|
||||
│ ├─ wtfnet-probe/ # ping/tcping/trace + geoip enrichment
|
||||
│ ├─ wtfnet-dns/ # query/detect/watch
|
||||
│ ├─ wtfnet-http/ # HTTP/1.1, HTTP/2, optional HTTP/3
|
||||
│ ├─ wtfnet-tls/ # TLS handshake/cert/verify/alpn
|
||||
│ ├─ wtfnet-discover/ # mdns/ssdp discovery
|
||||
│ └─ wtfnet-diag/ # diag bundle orchestrator
|
||||
└─ docs/ # design/usage docs (optional)
|
||||
```
|
||||
|
||||
### Root `Cargo.toml` (workspace)
|
||||
|
||||
```toml
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
"crates/wtfnet-cli",
|
||||
"crates/wtfnet-core",
|
||||
"crates/wtfnet-platform",
|
||||
"crates/wtfnet-platform-linux",
|
||||
"crates/wtfnet-platform-windows",
|
||||
"crates/wtfnet-geoip",
|
||||
"crates/wtfnet-probe",
|
||||
"crates/wtfnet-dns",
|
||||
"crates/wtfnet-http",
|
||||
"crates/wtfnet-tls",
|
||||
"crates/wtfnet-discover",
|
||||
"crates/wtfnet-diag",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2) Subcrate responsibilities
|
||||
|
||||
### 2.1 `wtfnet-cli` (binary)
|
||||
|
||||
**Purpose**
|
||||
|
||||
* Defines `clap` subcommands & global flags (`--json`, `--pretty`, logging flags, timeouts)
|
||||
* Calls into library crates
|
||||
* Converts results → human tables OR JSON
|
||||
|
||||
**Strict rule**
|
||||
|
||||
* No OS-specific code here.
|
||||
* No heavy logic here.
|
||||
|
||||
---
|
||||
|
||||
### 2.2 `wtfnet-core` (shared kernel)
|
||||
|
||||
**Owns**
|
||||
|
||||
* Output schema wrapper (`meta`, `command`, `data`, `warnings`, `errors`)
|
||||
* Error taxonomy + exit code mapping
|
||||
* Config loading (flags/env/config.json)
|
||||
* Logging initialization (`tracing`)
|
||||
* Formatting helpers (durations, bytes, IP formatting)
|
||||
* “human table renderer” utilities (optional)
|
||||
|
||||
---
|
||||
|
||||
### 2.3 `wtfnet-platform` (traits + dispatch)
|
||||
|
||||
**Purpose**
|
||||
Expose a stable interface for sysadmin-ish data:
|
||||
|
||||
* sys: interfaces/IP/route/DNS config snapshot
|
||||
* ports: listening sockets + PID/process info
|
||||
* cert roots: enumerate trusted roots
|
||||
* neigh: ARP/NDP cache
|
||||
|
||||
**Pattern**
|
||||
|
||||
* Define Rust traits like `SysProvider`, `PortsProvider`, `CertProvider`, `NeighProvider`
|
||||
* Provide a `Platform` object that selects implementation by target OS
|
||||
|
||||
---
|
||||
|
||||
### 2.4 `wtfnet-platform-linux`
|
||||
|
||||
Linux implementations:
|
||||
|
||||
* netlink-based route/IP/neigh: use `rtnetlink` ([Docs.rs][1])
|
||||
* ports/process mapping:
|
||||
|
||||
* either use `listeners` (cross-platform) or Linux procfs parsing
|
||||
* DNS snapshot: parse `/etc/resolv.conf` + detect `systemd-resolved` best-effort
|
||||
|
||||
---
|
||||
|
||||
### 2.5 `wtfnet-platform-windows`
|
||||
|
||||
Windows implementations:
|
||||
|
||||
* use `windows` crate / Win32 APIs
|
||||
|
||||
* interfaces/routes/neigh via IP Helper APIs
|
||||
* ports/process via Windows socket/process APIs
|
||||
* trusted roots via Windows cert store APIs
|
||||
|
||||
---
|
||||
|
||||
### 2.6 `wtfnet-geoip`
|
||||
|
||||
* Loads **local** GeoLite2 Country + ASN mmdb
|
||||
* Provides one `GeoIpService` with `lookup(ip)` returning:
|
||||
|
||||
* country + ISO
|
||||
* ASN + org
|
||||
|
||||
---
|
||||
|
||||
### 2.7 `wtfnet-probe`
|
||||
|
||||
Implements:
|
||||
|
||||
* ping (v4/v6)
|
||||
* tcping (connect latency)
|
||||
* trace (traceroute-like)
|
||||
* optional `--geoip` enrichment
|
||||
|
||||
For ping, you can start with `surge-ping` ([Crates][2]) or `ping-async` ([Docs.rs][3]) (both async-oriented).
|
||||
|
||||
---
|
||||
|
||||
### 2.8 `wtfnet-dns`
|
||||
|
||||
Implements:
|
||||
|
||||
* `dns query` (dig-like)
|
||||
* `dns detect` (poisoning compare)
|
||||
* `dns watch` (passive, best-effort)
|
||||
|
||||
Use **Hickory DNS** (Trust-DNS rebrand) ([Docs.rs][4]) for a solid resolver/client base.
|
||||
|
||||
---
|
||||
|
||||
### 2.9 `wtfnet-http`
|
||||
|
||||
Implements:
|
||||
|
||||
* `http head|get`
|
||||
* HTTP/2 support is required (via `reqwest`/`hyper`)
|
||||
* HTTP/3 optional behind feature flag:
|
||||
|
||||
* `h3` + `h3-quinn` + `quinn` ([GitHub][5])
|
||||
|
||||
---
|
||||
|
||||
### 2.10 `wtfnet-tls`
|
||||
|
||||
Implements:
|
||||
|
||||
* `tls handshake|cert|verify|alpn`
|
||||
* Use `rustls` for handshake parsing
|
||||
* For system trust verification:
|
||||
|
||||
* `rustls-native-certs` for loading OS roots ([Crates][6])
|
||||
* optionally `rustls-platform-verifier` for “verify like the OS” behavior ([GitHub][7])
|
||||
|
||||
---
|
||||
|
||||
### 2.11 `wtfnet-discover`
|
||||
|
||||
Implements bounded local discovery:
|
||||
|
||||
* mDNS service discovery: `mdns-sd` ([Crates][8])
|
||||
* SSDP discovery: `ssdp-client` ([Crates][9])
|
||||
|
||||
---
|
||||
|
||||
### 2.12 `wtfnet-diag`
|
||||
|
||||
Orchestrates:
|
||||
|
||||
* sys snapshot
|
||||
* routes
|
||||
* ports listen
|
||||
* neigh list
|
||||
* optional quick checks: DNS detect, TLS handshake, HTTP head
|
||||
* bundle export to zip
|
||||
|
||||
---
|
||||
|
||||
## 3) Dependency map (crate graph)
|
||||
|
||||
**High-level dependency graph:**
|
||||
|
||||
```
|
||||
wtfnet-cli
|
||||
├─ wtfnet-core
|
||||
├─ wtfnet-platform
|
||||
│ ├─ wtfnet-platform-linux (cfg linux)
|
||||
│ └─ wtfnet-platform-windows (cfg windows)
|
||||
├─ wtfnet-geoip
|
||||
├─ wtfnet-probe
|
||||
├─ wtfnet-dns
|
||||
├─ wtfnet-http
|
||||
├─ wtfnet-tls
|
||||
├─ wtfnet-discover
|
||||
└─ wtfnet-diag
|
||||
```
|
||||
|
||||
**Rule of thumb**
|
||||
|
||||
* `wtfnet-core` should not depend on OS crates.
|
||||
* feature crates should depend on `wtfnet-core` + minimal extras.
|
||||
|
||||
---
|
||||
|
||||
## 4) Shared libraries / crate dependencies (recommended)
|
||||
|
||||
### 4.1 Core stack (almost everywhere)
|
||||
|
||||
* **CLI**: `clap` (+ `clap_complete` optional)
|
||||
* **Async runtime**: `tokio`
|
||||
* **Serialization**: `serde`, `serde_json`
|
||||
* **Errors**: `thiserror` (libs), `anyhow` (CLI glue)
|
||||
* **URLs**: `url`
|
||||
* **Time**: `time` (or `chrono`), `humantime`
|
||||
* **Tables (human output)**: `tabled` or `comfy-table`
|
||||
* **Zip bundles**: `zip` (diag bundle)
|
||||
|
||||
### 4.2 Logging / tracing
|
||||
|
||||
Use `tracing` + `tracing-subscriber`:
|
||||
|
||||
* `tracing`
|
||||
* `tracing-subscriber` (fmt + env filter)
|
||||
* optional: `tracing-appender` (log file)
|
||||
|
||||
**Why this choice**
|
||||
|
||||
* structured logs
|
||||
* spans for timing each probe stage
|
||||
* easy JSON logs to stderr
|
||||
|
||||
---
|
||||
|
||||
### 4.3 Sys/platform related crates
|
||||
|
||||
* Interfaces: `network-interface` ([Crates][10]) (good for standardized interface listing)
|
||||
* Linux netlink: `rtnetlink` ([Docs.rs][1])
|
||||
* Ports:
|
||||
|
||||
* `listeners` (cross-platform “listening process mapping”) ([GitHub][11])
|
||||
* fallback: `netstat2` (cross-platform sockets info) ([Docs.rs][12])
|
||||
* Windows APIs: `windows` crate
|
||||
|
||||
> Suggestion: start with `listeners` for `ports listen/who` (it directly targets your use-case). ([GitHub][11])
|
||||
|
||||
---
|
||||
|
||||
### 4.4 GeoIP
|
||||
|
||||
* `maxminddb` (read GeoLite2 mmdb)
|
||||
|
||||
---
|
||||
|
||||
### 4.5 DNS
|
||||
|
||||
* `hickory-resolver` / Hickory ecosystem ([Docs.rs][4])
|
||||
|
||||
Passive `dns watch` (optional):
|
||||
|
||||
* `pcap` or `pnet` (feature-gated)
|
||||
|
||||
---
|
||||
|
||||
### 4.6 HTTP / TLS
|
||||
|
||||
HTTP:
|
||||
|
||||
* `reqwest` (easy HTTP/1.1 + HTTP/2)
|
||||
* or `hyper` if you want lower-level control
|
||||
|
||||
HTTP/3 (optional feature):
|
||||
|
||||
* `h3` + `h3-quinn` + `quinn` ([GitHub][5])
|
||||
|
||||
TLS:
|
||||
|
||||
* `rustls`
|
||||
* `rustls-native-certs` ([Crates][6])
|
||||
* `rustls-platform-verifier` (optional) ([GitHub][7])
|
||||
|
||||
---
|
||||
|
||||
### 4.7 Probing
|
||||
|
||||
* ping:
|
||||
|
||||
* `surge-ping` ([Crates][2])
|
||||
* or `ping-async` ([Docs.rs][3])
|
||||
* tcping: plain `tokio::net::TcpStream::connect` + `timeout`
|
||||
* trace: start simple (UDP/ICMP-based approaches are trickier & permission-sensitive)
|
||||
|
||||
---
|
||||
|
||||
### 4.8 Discovery
|
||||
|
||||
* mDNS: `mdns-sd` ([Crates][8])
|
||||
* SSDP: `ssdp-client` ([Crates][9])
|
||||
|
||||
---
|
||||
|
||||
## 5) Feature flags & compile-time options
|
||||
|
||||
In root design, define optional features to avoid heavy deps by default.
|
||||
|
||||
Suggested features:
|
||||
|
||||
* `http3` → enables `h3`, `h3-quinn`, `quinn`
|
||||
* `pcap` → enables passive DNS watch with packet capture
|
||||
* `discover` → enable mdns/ssdp features (if you want a “minimal build”)
|
||||
|
||||
Example snippet (in `wtfnet-http/Cargo.toml`):
|
||||
|
||||
```toml
|
||||
[features]
|
||||
default = ["http2"]
|
||||
http2 = []
|
||||
http3 = ["dep:h3", "dep:h3-quinn", "dep:quinn"]
|
||||
|
||||
[dependencies]
|
||||
reqwest = { version = "*", features = ["rustls-tls", "http2"] }
|
||||
h3 = { version = "*", optional = true }
|
||||
h3-quinn = { version = "*", optional = true }
|
||||
quinn = { version = "*", optional = true }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6) Core data model + output schema (do this early)
|
||||
|
||||
### 6.1 Unified JSON wrapper (recommended)
|
||||
|
||||
Every command returns:
|
||||
|
||||
```rust
|
||||
pub struct CommandEnvelope<T> {
|
||||
pub meta: Meta,
|
||||
pub command: CommandInfo,
|
||||
pub data: T,
|
||||
pub warnings: Vec<Warn>,
|
||||
pub errors: Vec<ErrItem>,
|
||||
}
|
||||
```
|
||||
|
||||
Key principles:
|
||||
|
||||
* stable keys
|
||||
* additive schema evolution
|
||||
* logs never pollute stdout JSON
|
||||
|
||||
### 6.2 Exit code mapping
|
||||
|
||||
Put this in `wtfnet-core` and make CLI enforce it:
|
||||
|
||||
```rust
|
||||
pub enum ExitKind {
|
||||
Ok,
|
||||
Failed,
|
||||
Usage,
|
||||
Permission,
|
||||
Timeout,
|
||||
Partial,
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7) Logging design (`tracing`)
|
||||
|
||||
### 7.1 Init once in `main()`
|
||||
|
||||
`wtfnet-core::logging::init(...)` should:
|
||||
|
||||
* respect CLI flags + env vars
|
||||
* print to stderr
|
||||
* support `text|json` formats
|
||||
|
||||
### 7.2 Use spans for “timing breakdown”
|
||||
|
||||
Example: HTTP diagnostics
|
||||
|
||||
```rust
|
||||
#[tracing::instrument(skip(client))]
|
||||
async fn http_head(client: &Client, url: &Url) -> Result<HttpReport, Error> {
|
||||
let _span = tracing::info_span!("http_head", %url).entered();
|
||||
// measure dns/connect/tls/ttfb where possible
|
||||
Ok(report)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8) Platform abstraction pattern (Rust traits)
|
||||
|
||||
In `wtfnet-platform`:
|
||||
|
||||
```rust
|
||||
pub trait SysProvider {
|
||||
async fn interfaces(&self) -> Result<Vec<NetInterface>, PlatformError>;
|
||||
async fn routes(&self) -> Result<Vec<RouteEntry>, PlatformError>;
|
||||
async fn dns_config(&self) -> Result<DnsConfig, PlatformError>;
|
||||
}
|
||||
|
||||
pub trait PortsProvider {
|
||||
async fn listening(&self) -> Result<Vec<ListenSocket>, PlatformError>;
|
||||
async fn who_owns(&self, port: u16) -> Result<Vec<ListenSocket>, PlatformError>;
|
||||
}
|
||||
|
||||
pub trait CertProvider {
|
||||
async fn trusted_roots(&self) -> Result<Vec<RootCert>, PlatformError>;
|
||||
}
|
||||
|
||||
pub trait NeighProvider {
|
||||
async fn neighbors(&self) -> Result<Vec<NeighborEntry>, PlatformError>;
|
||||
}
|
||||
```
|
||||
|
||||
Then provide:
|
||||
|
||||
```rust
|
||||
pub struct Platform {
|
||||
pub sys: Arc<dyn SysProvider + Send + Sync>,
|
||||
pub ports: Arc<dyn PortsProvider + Send + Sync>,
|
||||
pub cert: Arc<dyn CertProvider + Send + Sync>,
|
||||
pub neigh: Arc<dyn NeighProvider + Send + Sync>,
|
||||
}
|
||||
```
|
||||
|
||||
OS dispatch:
|
||||
|
||||
* `cfg(target_os = "linux")` → `wtfnet-platform-linux`
|
||||
* `cfg(target_os = "windows")` → `wtfnet-platform-windows`
|
||||
|
||||
---
|
||||
|
||||
## 9) Implementation notes per command area
|
||||
|
||||
### 9.1 sys (interfaces/routes/dns)
|
||||
|
||||
**Interfaces**
|
||||
|
||||
* start with `network-interface` ([Crates][10]) for a normalized list
|
||||
* if you need MTU / gateway details not exposed, add platform-native calls
|
||||
|
||||
**Linux routes/neigh**
|
||||
|
||||
* `rtnetlink` can manage links/addresses/ARP/route tables ([Docs.rs][1])
|
||||
|
||||
**Windows routes/neigh**
|
||||
|
||||
* use Win32 IP helper APIs via `windows` crate
|
||||
|
||||
---
|
||||
|
||||
### 9.2 ports (listen/who)
|
||||
|
||||
Best path:
|
||||
|
||||
* use `listeners` crate for cross-platform “listening sockets → process” mapping ([GitHub][11])
|
||||
|
||||
Fallback:
|
||||
|
||||
* `netstat2` provides cross-platform socket information ([Docs.rs][12])
|
||||
|
||||
---
|
||||
|
||||
### 9.3 cert roots
|
||||
|
||||
Use:
|
||||
|
||||
* `rustls-native-certs` to load roots from OS trust store ([Crates][6])
|
||||
|
||||
Filtering:
|
||||
|
||||
* by subject substring
|
||||
* by fingerprint sha256
|
||||
* expired/not-yet-valid
|
||||
|
||||
Diff:
|
||||
|
||||
* export stable JSON
|
||||
* compare by fingerprint (sha256)
|
||||
|
||||
---
|
||||
|
||||
### 9.4 geoip (local mmdb)
|
||||
|
||||
Use:
|
||||
|
||||
* `maxminddb`
|
||||
Expose:
|
||||
* `GeoIpService::new(country_path, asn_path)`
|
||||
* `lookup(IpAddr) -> GeoInfo`
|
||||
|
||||
---
|
||||
|
||||
### 9.5 dns (query/detect/watch)
|
||||
|
||||
Resolver:
|
||||
|
||||
* Hickory DNS ecosystem ([Docs.rs][4])
|
||||
|
||||
Detect logic (keep deterministic):
|
||||
|
||||
* Query multiple resolvers
|
||||
* Normalize answers (A/AAAA/CNAME)
|
||||
* “suspicious” if major divergence, NXDOMAIN mismatch, private IP injection patterns
|
||||
|
||||
Watch:
|
||||
|
||||
* feature-gate packet capture
|
||||
* document privilege needs clearly
|
||||
|
||||
---
|
||||
|
||||
### 9.6 http (head/get)
|
||||
|
||||
HTTP/2:
|
||||
|
||||
* `reqwest` makes this trivial
|
||||
|
||||
HTTP/3 (optional):
|
||||
|
||||
* use `h3` + `h3-quinn` + `quinn` ([GitHub][5])
|
||||
Keep it behind `--http3` and fallback to HTTP/2 when UDP is blocked.
|
||||
|
||||
Timing breakdown:
|
||||
|
||||
* you’ll get total time easily
|
||||
* fine-grained DNS/connect/TLS timing may need deeper client hooks (ok to be best-effort)
|
||||
|
||||
---
|
||||
|
||||
### 9.7 tls (handshake/cert/verify)
|
||||
|
||||
Handshake:
|
||||
|
||||
* use `rustls` to connect and extract:
|
||||
|
||||
* version, cipher suite, ALPN
|
||||
* peer cert chain
|
||||
|
||||
Verify:
|
||||
|
||||
* use `rustls-platform-verifier` if you want OS-like verification ([GitHub][7])
|
||||
* otherwise load roots via `rustls-native-certs` ([Crates][6]) and verify with webpki
|
||||
|
||||
---
|
||||
|
||||
### 9.8 neigh (ARP/NDP)
|
||||
|
||||
Linux:
|
||||
|
||||
* `rtnetlink` includes ARP/neighbor operations ([Docs.rs][1])
|
||||
|
||||
Windows:
|
||||
|
||||
* IP Helper API provides neighbor cache info (implementation detail)
|
||||
|
||||
---
|
||||
|
||||
### 9.9 discover (mDNS + SSDP)
|
||||
|
||||
mDNS:
|
||||
|
||||
* `mdns-sd` ([Crates][8])
|
||||
Bounded `--duration`, no spam.
|
||||
|
||||
SSDP:
|
||||
|
||||
* `ssdp-client` ([Crates][9])
|
||||
Send M-SEARCH, collect responses, parse location/server/usn.
|
||||
|
||||
---
|
||||
|
||||
## 10) Testing strategy
|
||||
|
||||
### 10.1 Unit tests (fast, pure)
|
||||
|
||||
* subnet math (`calc`)
|
||||
* parsing/formatting
|
||||
* DNS comparison heuristics (test vectors)
|
||||
|
||||
### 10.2 Snapshot tests (JSON stability)
|
||||
|
||||
Use `insta`:
|
||||
|
||||
* ensure `--json` schema doesn’t drift accidentally
|
||||
|
||||
### 10.3 Integration tests (CI)
|
||||
|
||||
* run non-privileged commands only:
|
||||
|
||||
* `sys ifaces`
|
||||
* `calc subnet`
|
||||
* `dns query example.com A`
|
||||
* `http head https://example.com`
|
||||
|
||||
---
|
||||
|
||||
## 11) Coding conventions
|
||||
|
||||
* Every command handler returns a structured `CommandEnvelope<T>`
|
||||
* Never `println!` from libs; return data → CLI prints it
|
||||
* `--json` must be clean stdout (no logs mixed in)
|
||||
* Use timeouts everywhere in probe/dns/http/tls
|
||||
* Prefer “best-effort + warnings” over hard failure
|
||||
|
||||
---
|
||||
|
||||
## 12) Minimal “first coding milestone” plan
|
||||
|
||||
1. `wtfnet-core`: envelope + logging init + exit mapping
|
||||
2. `wtfnet-cli`: clap skeleton + `sys ifaces`
|
||||
3. `wtfnet-geoip`: load mmdb + `geoip <ip>`
|
||||
4. `ports listen/who` using `listeners` ([GitHub][11])
|
||||
5. `dns query` via Hickory ([Docs.rs][4])
|
||||
6. `http head` and `tls handshake` basic success path
|
||||
7. `diag` orchestration + zip bundle
|
||||
|
||||
---
|
||||
938
docs/requirement_docs.md
Normal file
938
docs/requirement_docs.md
Normal file
@@ -0,0 +1,938 @@
|
||||
|
||||
---
|
||||
|
||||
# README.md
|
||||
|
||||
````markdown
|
||||
# WTFnet
|
||||
|
||||
**WTFnet** is a pure CLI toolbox for diagnosing network problems on **Linux (Debian/Ubuntu)** and **Windows**.
|
||||
|
||||
> _"What the f\*ck is my networking doing?"_
|
||||
|
||||
It combines system network inspection, port/process visibility, DNS poisoning checks, HTTP/TLS diagnostics, GeoIP enrichment, ARP/NDP neighbor tables, and lightweight discovery tools — all in one consistent CLI.
|
||||
|
||||
## Goals
|
||||
|
||||
- **Pure CLI** (no REPL / no TUI)
|
||||
- **Fast + scriptable** output (`--json` supported everywhere)
|
||||
- **First-class support:** Linux (Debian/Ubuntu), Windows
|
||||
- **Rust implementation**
|
||||
- **Graceful degradation** when OS APIs differ or privileges are missing
|
||||
|
||||
## Quickstart
|
||||
|
||||
### Show interfaces & IPs
|
||||
```bash
|
||||
wtfnet sys ifaces
|
||||
wtfnet sys ip --all
|
||||
wtfnet sys route
|
||||
````
|
||||
|
||||
### Find which process owns port 443
|
||||
|
||||
```bash
|
||||
wtfnet ports who 443
|
||||
wtfnet ports listen --tcp
|
||||
```
|
||||
|
||||
### DNS poisoning detection (multi-resolver compare)
|
||||
|
||||
```bash
|
||||
wtfnet dns detect example.com
|
||||
wtfnet dns detect example.com --servers 1.1.1.1,8.8.8.8,9.9.9.9 --repeat 3
|
||||
```
|
||||
|
||||
### HTTP + TLS diagnostics
|
||||
|
||||
```bash
|
||||
wtfnet http head https://example.com --show-headers --http2-only
|
||||
wtfnet tls handshake example.com:443 --show-chain
|
||||
wtfnet tls verify example.com:443
|
||||
```
|
||||
|
||||
### GeoIP lookup (local GeoLite2 DBs)
|
||||
|
||||
```bash
|
||||
wtfnet geoip 8.8.8.8
|
||||
wtfnet probe tcping example.com:443 --geoip
|
||||
```
|
||||
|
||||
### Neighbor table (ARP / NDP)
|
||||
|
||||
```bash
|
||||
wtfnet neigh list
|
||||
wtfnet neigh list --ipv4
|
||||
wtfnet neigh list --ipv6
|
||||
```
|
||||
|
||||
### Generate a diagnostic report bundle
|
||||
|
||||
```bash
|
||||
wtfnet diag --bundle out.zip
|
||||
```
|
||||
|
||||
## Output modes
|
||||
|
||||
* Default: readable tables / summaries
|
||||
* Machine-readable: `--json`
|
||||
* Pretty JSON: `--json --pretty`
|
||||
* Logs go to **stderr** (JSON output stays clean)
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
wtfnet sys ip --json --pretty > ip.json
|
||||
```
|
||||
|
||||
## Logging
|
||||
|
||||
```bash
|
||||
wtfnet --log-level debug sys route
|
||||
wtfnet --log-format json sys dns
|
||||
wtfnet --log-file wtfnet.log diag
|
||||
```
|
||||
|
||||
Environment variables:
|
||||
|
||||
* `NETTOOL_LOG_LEVEL`
|
||||
* `NETTOOL_LOG_FORMAT`
|
||||
* `NETTOOL_LOG_FILE`
|
||||
|
||||
## License
|
||||
|
||||
TBD
|
||||
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
# REQUIREMENTS.md
|
||||
|
||||
```markdown
|
||||
# WTFnet — Requirements (v0.2)
|
||||
|
||||
## 1. Product overview
|
||||
|
||||
### 1.1 Purpose
|
||||
WTFnet is a **single-executable CLI toolbox** for diagnosing network problems:
|
||||
- inspect IP/interface/route/DNS
|
||||
- probe connectivity (ICMP/TCP/path)
|
||||
- detect **DNS poisoning**
|
||||
- inspect **trusted root certificates**
|
||||
- map **listening ports → processes**
|
||||
- run **HTTP/TLS diagnostics**
|
||||
- view **ARP/NDP neighbor cache**
|
||||
- perform lightweight **service discovery**
|
||||
- export a consistent report bundle for incident response
|
||||
|
||||
### 1.2 Design goals
|
||||
- Pure CLI: no REPL / no TUI
|
||||
- Script-friendly: stable output & exit codes
|
||||
- First-class support: **Linux (Debian/Ubuntu)** + **Windows**
|
||||
- Rust implementation
|
||||
- Works without admin where possible; warns clearly when privileges required
|
||||
|
||||
---
|
||||
|
||||
## 2. Platform support
|
||||
|
||||
### 2.1 First-class OS targets
|
||||
- Linux: Debian / Ubuntu
|
||||
- Windows 10/11 + Windows Server
|
||||
|
||||
### 2.2 Best-effort targets
|
||||
- macOS (not required for v0.x)
|
||||
|
||||
---
|
||||
|
||||
## 3. CLI UX requirements
|
||||
|
||||
### 3.1 Global flags
|
||||
All commands MUST support:
|
||||
- `--json` (machine output)
|
||||
- `--pretty` (pretty JSON)
|
||||
- `--no-color`
|
||||
- `--quiet`
|
||||
- `-v`, `-vv` (verbosity)
|
||||
- logging flags (see §4)
|
||||
|
||||
### 3.2 Exit codes
|
||||
- `0`: success
|
||||
- `1`: generic failure
|
||||
- `2`: invalid args
|
||||
- `3`: insufficient permissions
|
||||
- `4`: timeout/unreachable category
|
||||
- `5`: partial success (some checks failed; still produced results)
|
||||
|
||||
---
|
||||
|
||||
## 4. Logging requirements
|
||||
|
||||
### 4.1 Goals
|
||||
- Debug WTFnet itself in production environments
|
||||
- Preserve clean stdout for piping / JSON mode
|
||||
|
||||
### 4.2 Behavior
|
||||
- Logs MUST go to **stderr**
|
||||
- Command output MUST go to **stdout**
|
||||
- JSON output must remain valid even with debug logs enabled
|
||||
|
||||
### 4.3 Controls
|
||||
Flags:
|
||||
- `--log-level <error|warn|info|debug|trace>` (default `info`)
|
||||
- `--log-format <text|json>` (default `text`)
|
||||
- `--log-file <path>` (optional; write logs there; may also tee stderr)
|
||||
|
||||
Env vars:
|
||||
- `NETTOOL_LOG_LEVEL`
|
||||
- `NETTOOL_LOG_FORMAT`
|
||||
- `NETTOOL_LOG_FILE`
|
||||
|
||||
### 4.4 Sensitive logging policy
|
||||
- Do NOT log secrets by default (tokens, cookies, passwords)
|
||||
- HTTP response bodies are hidden by default
|
||||
- Provide explicit `--show-secrets` / `--show-body` gates where relevant
|
||||
|
||||
---
|
||||
|
||||
## 5. Functional requirements
|
||||
|
||||
### 5.1 System inspection (`sys`)
|
||||
#### 5.1.1 Interfaces & addresses
|
||||
Must provide:
|
||||
- interface name/index, state, MTU, MAC
|
||||
- IPv4/IPv6 addresses with prefix + scope
|
||||
- DNS servers + search domains (best-effort)
|
||||
- default gateway mapping (best-effort)
|
||||
|
||||
Commands:
|
||||
- `wtfnet sys ifaces`
|
||||
- `wtfnet sys ip --all`
|
||||
- `wtfnet sys route`
|
||||
- `wtfnet sys dns`
|
||||
|
||||
#### 5.1.2 Routing table
|
||||
Outputs:
|
||||
- destination/prefix, gateway/next hop, interface, metric
|
||||
|
||||
---
|
||||
|
||||
### 5.2 Certificate inspection (`cert`)
|
||||
Must list system-wide trusted roots:
|
||||
- subject, issuer
|
||||
- validity range
|
||||
- serial number
|
||||
- SHA1 + SHA256 fingerprint
|
||||
- key algorithm + size
|
||||
- OS store origin (Windows store / Linux path)
|
||||
|
||||
Commands:
|
||||
- `wtfnet cert roots`
|
||||
- `wtfnet cert roots --filter subject="DigiCert"`
|
||||
- `wtfnet cert roots --export baseline.json`
|
||||
- `wtfnet cert roots --diff baseline.json`
|
||||
|
||||
---
|
||||
|
||||
### 5.3 Active probing (`probe`)
|
||||
#### 5.3.1 ping
|
||||
- IPv4/IPv6
|
||||
- count/timeout/interval
|
||||
- summary: min/avg/max latency, packet loss
|
||||
|
||||
#### 5.3.2 tcping
|
||||
- hostname or IP:port
|
||||
- resolution result
|
||||
- connect latency
|
||||
- failure classification
|
||||
|
||||
#### 5.3.3 trace
|
||||
- hop list with RTT and IP
|
||||
- IPv4/IPv6 best-effort
|
||||
|
||||
#### 5.3.4 GeoIP enrichment integration
|
||||
All probe commands must support:
|
||||
- `--geoip` to attach GeoIP info to targets/resolved IPs/hops
|
||||
|
||||
---
|
||||
|
||||
### 5.4 GeoIP (`geoip`)
|
||||
#### 5.4.1 Local DB support (GeoLite2 Country + ASN)
|
||||
- Country DB + ASN DB used offline
|
||||
- degrade gracefully if missing
|
||||
|
||||
DB configuration:
|
||||
- flags:
|
||||
- `--country-db <path>`
|
||||
- `--asn-db <path>`
|
||||
- env vars:
|
||||
- `NETTOOL_GEOIP_COUNTRY_DB`
|
||||
- `NETTOOL_GEOIP_ASN_DB`
|
||||
|
||||
Commands:
|
||||
- `wtfnet geoip <ip>`
|
||||
- `wtfnet geoip status`
|
||||
|
||||
Outputs:
|
||||
- country + ISO code if available
|
||||
- ASN number + org name
|
||||
- DB source/version timestamp if detectable
|
||||
|
||||
---
|
||||
|
||||
### 5.5 DNS diagnostics (`dns`)
|
||||
#### 5.5.1 Query
|
||||
Commands:
|
||||
- `wtfnet dns query <domain> <type> [--server <ip>] [--tcp]`
|
||||
|
||||
Outputs:
|
||||
- rcode, answer set + TTL, timing, server used
|
||||
|
||||
#### 5.5.2 Active poisoning detection
|
||||
Commands:
|
||||
- `wtfnet dns detect example.com`
|
||||
- `wtfnet dns detect example.com --servers 1.1.1.1,8.8.8.8 --repeat 5`
|
||||
|
||||
Heuristics to flag suspicious:
|
||||
- major answer divergence across resolvers
|
||||
- abnormal TTL patterns
|
||||
- unexpected private/reserved results
|
||||
- NXDOMAIN injection patterns
|
||||
|
||||
Output verdict:
|
||||
- `clean | suspicious | inconclusive`
|
||||
with evidence list
|
||||
|
||||
#### 5.5.3 Passive watch (best-effort)
|
||||
Commands:
|
||||
- `wtfnet dns watch --duration 30s [--iface eth0] [--filter example.com]`
|
||||
|
||||
Must:
|
||||
- be time-bounded
|
||||
- clearly document privilege requirements (pcap)
|
||||
|
||||
---
|
||||
|
||||
### 5.6 Ports & processes (`ports`)
|
||||
Must show listening sockets and owners:
|
||||
- proto, local addr:port, state
|
||||
- PID, PPID (best-effort), process name/path
|
||||
- user/owner (best-effort)
|
||||
|
||||
Commands:
|
||||
- `wtfnet ports listen --tcp|--udp`
|
||||
- `wtfnet ports who <port>`
|
||||
|
||||
(Optional)
|
||||
- `wtfnet ports conns`
|
||||
|
||||
---
|
||||
|
||||
### 5.7 Subnet calculator (`calc`)
|
||||
Commands:
|
||||
- `wtfnet calc subnet <cidr|ip mask>`
|
||||
- `wtfnet calc contains <cidrA> <cidrB>`
|
||||
- `wtfnet calc overlap <cidrA> <cidrB>`
|
||||
- `wtfnet calc summarize <cidr1> <cidr2> ...`
|
||||
|
||||
---
|
||||
|
||||
### 5.8 HTTP diagnostics (`http`)
|
||||
Goals:
|
||||
- verify endpoint health and protocol negotiation
|
||||
- help debug redirect loops, TLS errors, HTTP version issues
|
||||
|
||||
Commands:
|
||||
- `wtfnet http head <url>`
|
||||
- `wtfnet http get <url>`
|
||||
|
||||
Flags:
|
||||
- `--http1-only`
|
||||
- `--http2-only`
|
||||
- `--http3` (best-effort optional)
|
||||
- `--timeout 3s`
|
||||
- `--follow-redirects [N]`
|
||||
- `--header "K: V"` (repeatable)
|
||||
- `--show-headers`
|
||||
- `--show-body` (off by default)
|
||||
- `--max-body <bytes>`
|
||||
- `--geoip`
|
||||
|
||||
Required outputs:
|
||||
- resolved IP(s)
|
||||
- negotiated HTTP version (1.1/2/3)
|
||||
- status code
|
||||
- optional headers/body
|
||||
- timing breakdown (best-effort):
|
||||
- DNS
|
||||
- connect / QUIC handshake
|
||||
- TLS handshake
|
||||
- TTFB
|
||||
- total
|
||||
|
||||
---
|
||||
|
||||
### 5.9 TLS diagnostics (`tls`)
|
||||
Commands:
|
||||
- `wtfnet tls handshake <host:port>`
|
||||
- `wtfnet tls cert <host:port>`
|
||||
- `wtfnet tls verify <host:port>`
|
||||
- `wtfnet tls alpn <host:port>`
|
||||
|
||||
Flags:
|
||||
- `--sni <hostname>`
|
||||
- `--alpn h2,http/1.1`
|
||||
- `--insecure`
|
||||
- `--show-chain`
|
||||
- `--geoip`
|
||||
|
||||
Outputs:
|
||||
- TLS version + cipher
|
||||
- ALPN negotiated
|
||||
- chain summary (subject/issuer/validity/SAN best-effort)
|
||||
- verification verdict + error category
|
||||
|
||||
---
|
||||
|
||||
### 5.10 Neighbor table (`neigh`)
|
||||
Commands:
|
||||
- `wtfnet neigh list [--ipv4|--ipv6] [--iface eth0]`
|
||||
|
||||
Outputs:
|
||||
- IP → MAC/LLADDR mapping
|
||||
- interface
|
||||
- state (reachable/stale/failed if available)
|
||||
|
||||
---
|
||||
|
||||
### 5.11 Discovery services (`discover`)
|
||||
Purpose: lightweight local discovery, bounded and safe.
|
||||
|
||||
Commands:
|
||||
- `wtfnet discover mdns --duration 3s`
|
||||
- `wtfnet discover ssdp --duration 3s`
|
||||
(optional)
|
||||
- `wtfnet discover llmnr --duration 3s`
|
||||
- `wtfnet discover nbns --duration 3s`
|
||||
|
||||
Outputs:
|
||||
- service/device name
|
||||
- IP/port if present
|
||||
- protocol and service type
|
||||
|
||||
---
|
||||
|
||||
### 5.12 Diagnostic bundle (`diag`)
|
||||
Commands:
|
||||
- `wtfnet diag`
|
||||
- `wtfnet diag --out report.json --json`
|
||||
- `wtfnet diag --bundle out.zip`
|
||||
|
||||
Bundle must include:
|
||||
- sys snapshot
|
||||
- routes
|
||||
- dns config + optional detect check
|
||||
- ports listen
|
||||
- neighbor snapshot
|
||||
- meta.json (OS, version, timestamp, privilege hints)
|
||||
|
||||
---
|
||||
|
||||
## 6. Non-functional requirements
|
||||
|
||||
- robust error handling (no panics)
|
||||
- partial results allowed (exit code `5`)
|
||||
- no indefinite hangs (timeouts everywhere)
|
||||
- privacy: never exfiltrate data; don’t log secrets by default
|
||||
|
||||
---
|
||||
|
||||
## 7. Acceptance criteria (v0.2)
|
||||
On Linux (Debian/Ubuntu) and Windows:
|
||||
- sys inspection works
|
||||
- cert roots listing/filter works
|
||||
- ping + tcping works (IPv4/IPv6 best-effort)
|
||||
- dns query + detect works with verdict+evidence
|
||||
- ports listen/who works (best-effort PID mapping)
|
||||
- http head/get works with HTTP/2 support
|
||||
- tls handshake/verify works with clear output
|
||||
- neigh list works (ARP/NDP snapshot)
|
||||
- logging behaves correctly without breaking JSON output
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
# COMMANDS.md
|
||||
|
||||
````markdown
|
||||
# WTFnet — Command Reference
|
||||
|
||||
This file documents WTFnet CLI commands and flags.
|
||||
|
||||
## Global flags
|
||||
|
||||
Applies to all commands:
|
||||
|
||||
- `--json` : machine-readable output
|
||||
- `--pretty` : pretty JSON (requires `--json`)
|
||||
- `--no-color` : disable ANSI color
|
||||
- `--quiet` : minimal output
|
||||
- `-v`, `-vv` : verbose output
|
||||
- `--log-level <error|warn|info|debug|trace>`
|
||||
- `--log-format <text|json>`
|
||||
- `--log-file <path>`
|
||||
|
||||
Exit codes: see `REQUIREMENTS.md`
|
||||
|
||||
---
|
||||
|
||||
## sys
|
||||
|
||||
### `wtfnet sys ifaces`
|
||||
Show interface inventory.
|
||||
|
||||
### `wtfnet sys ip [--all] [--iface <name>]`
|
||||
Show IP addresses.
|
||||
|
||||
### `wtfnet sys route [--ipv4|--ipv6] [--to <ip>]`
|
||||
Show routing table; optionally “route-to target”.
|
||||
|
||||
### `wtfnet sys dns`
|
||||
Show resolver configuration snapshot.
|
||||
|
||||
---
|
||||
|
||||
## cert
|
||||
|
||||
### `wtfnet cert roots`
|
||||
List trusted root certificates.
|
||||
|
||||
Common filters:
|
||||
- `--filter subject="..."`
|
||||
- `--expired`
|
||||
- `--fingerprint <sha256>`
|
||||
|
||||
Baseline tools:
|
||||
- `--export <file.json>`
|
||||
- `--diff <baseline.json>`
|
||||
|
||||
---
|
||||
|
||||
## probe
|
||||
|
||||
### `wtfnet probe ping <host|ip> [--count N] [--timeout 800ms] [--interval 200ms] [--geoip]`
|
||||
ICMP echo with stats.
|
||||
|
||||
### `wtfnet probe tcping <host:port> [--count N] [--timeout 800ms] [--geoip]`
|
||||
TCP connect timing.
|
||||
|
||||
### `wtfnet probe trace <host|ip> [--max-hops N] [--timeout 800ms] [--geoip]`
|
||||
Traceroute-like path discovery.
|
||||
|
||||
---
|
||||
|
||||
## geoip
|
||||
|
||||
### `wtfnet geoip <ip|host> [--resolve]`
|
||||
Geo lookup (offline DB).
|
||||
|
||||
### `wtfnet geoip status`
|
||||
Show DB presence and detected paths.
|
||||
|
||||
DB flags:
|
||||
- `--country-db <path>`
|
||||
- `--asn-db <path>`
|
||||
|
||||
Env vars:
|
||||
- `NETTOOL_GEOIP_COUNTRY_DB`
|
||||
- `NETTOOL_GEOIP_ASN_DB`
|
||||
|
||||
---
|
||||
|
||||
## dns
|
||||
|
||||
### `wtfnet dns query <domain> <TYPE> [--server <ip>] [--tcp] [--timeout 2s]`
|
||||
Dig-like query.
|
||||
|
||||
Examples:
|
||||
```bash
|
||||
wtfnet dns query example.com A
|
||||
wtfnet dns query example.com AAAA --server 1.1.1.1
|
||||
wtfnet dns query example.com A --tcp
|
||||
````
|
||||
|
||||
### `wtfnet dns detect <domain> [--servers <csv>] [--repeat N] [--timeout 2s]`
|
||||
|
||||
Compare across resolvers and detect anomalies.
|
||||
|
||||
### `wtfnet dns watch [--iface <name>] [--duration 30s] [--filter <pattern>]`
|
||||
|
||||
Passive watch (best-effort; may require privileges).
|
||||
|
||||
---
|
||||
|
||||
## ports
|
||||
|
||||
### `wtfnet ports listen [--tcp|--udp] [--port N]`
|
||||
|
||||
Show listening sockets.
|
||||
|
||||
### `wtfnet ports who <port|ip:port>`
|
||||
|
||||
Find owning process.
|
||||
|
||||
(Optional)
|
||||
|
||||
### `wtfnet ports conns [--top N]`
|
||||
|
||||
Show active connections.
|
||||
|
||||
---
|
||||
|
||||
## calc
|
||||
|
||||
### `wtfnet calc subnet <CIDR|ip mask>`
|
||||
|
||||
Subnet information.
|
||||
|
||||
### `wtfnet calc contains <CIDR-A> <CIDR-B>`
|
||||
|
||||
Containment check.
|
||||
|
||||
### `wtfnet calc overlap <CIDR-A> <CIDR-B>`
|
||||
|
||||
Overlap check.
|
||||
|
||||
### `wtfnet calc summarize <CIDR...>`
|
||||
|
||||
Summarize multiple networks.
|
||||
|
||||
---
|
||||
|
||||
## http
|
||||
|
||||
### `wtfnet http head <url>`
|
||||
|
||||
### `wtfnet http get <url>`
|
||||
|
||||
Core flags:
|
||||
|
||||
* `--http1-only`
|
||||
* `--http2-only`
|
||||
* `--http3` (best-effort)
|
||||
* `--timeout 3s`
|
||||
* `--follow-redirects [N]`
|
||||
* `--header "K: V"` (repeatable)
|
||||
* `--show-headers`
|
||||
* `--show-body`
|
||||
* `--max-body <bytes>`
|
||||
* `--geoip`
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
wtfnet http head https://example.com --http2-only --show-headers
|
||||
wtfnet http get https://example.com --follow-redirects 5
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## tls
|
||||
|
||||
### `wtfnet tls handshake <host:port>`
|
||||
|
||||
### `wtfnet tls cert <host:port>`
|
||||
|
||||
### `wtfnet tls verify <host:port>`
|
||||
|
||||
### `wtfnet tls alpn <host:port>`
|
||||
|
||||
Flags:
|
||||
|
||||
* `--sni <hostname>`
|
||||
* `--alpn h2,http/1.1`
|
||||
* `--insecure`
|
||||
* `--show-chain`
|
||||
* `--geoip`
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
wtfnet tls handshake example.com:443 --show-chain
|
||||
wtfnet tls verify example.com:443
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## neigh
|
||||
|
||||
### `wtfnet neigh list [--ipv4|--ipv6] [--iface <name>]`
|
||||
|
||||
Show neighbor table (ARP/NDP).
|
||||
|
||||
---
|
||||
|
||||
## discover
|
||||
|
||||
### `wtfnet discover mdns --duration 3s`
|
||||
|
||||
### `wtfnet discover ssdp --duration 3s`
|
||||
|
||||
(Optional)
|
||||
|
||||
### `wtfnet discover llmnr --duration 3s`
|
||||
|
||||
### `wtfnet discover nbns --duration 3s`
|
||||
|
||||
---
|
||||
|
||||
## diag
|
||||
|
||||
### `wtfnet diag [--json] [--out <file>]`
|
||||
|
||||
Generate report.
|
||||
|
||||
### `wtfnet diag --bundle <zip>`
|
||||
|
||||
Export support bundle.
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
wtfnet diag --json --pretty --out report.json
|
||||
wtfnet diag --bundle out.zip
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
# CONFIG.md
|
||||
|
||||
```markdown
|
||||
# WTFnet — Configuration
|
||||
|
||||
WTFnet supports configuration via:
|
||||
|
||||
Priority order:
|
||||
1) CLI flags
|
||||
2) Environment variables
|
||||
3) Config file (optional)
|
||||
4) Built-in defaults
|
||||
|
||||
## Config file location (proposed)
|
||||
|
||||
Linux:
|
||||
- `$XDG_CONFIG_HOME/wtfnet/config.json`
|
||||
- fallback: `~/.config/wtfnet/config.json`
|
||||
|
||||
Windows:
|
||||
- `%APPDATA%\wtfnet\config.json`
|
||||
|
||||
## Example config.json
|
||||
|
||||
```json
|
||||
{
|
||||
"geoip": {
|
||||
"country_db": "/opt/geoip/GeoLite2-Country.mmdb",
|
||||
"asn_db": "/opt/geoip/GeoLite2-ASN.mmdb"
|
||||
},
|
||||
"dns": {
|
||||
"detect_servers": ["1.1.1.1", "8.8.8.8", "9.9.9.9"],
|
||||
"timeout_ms": 2000,
|
||||
"repeat": 3
|
||||
},
|
||||
"probe": {
|
||||
"timeout_ms": 800,
|
||||
"count": 4
|
||||
},
|
||||
"http": {
|
||||
"timeout_ms": 3000,
|
||||
"follow_redirects": 3,
|
||||
"max_body_bytes": 8192
|
||||
},
|
||||
"logging": {
|
||||
"level": "info",
|
||||
"format": "text",
|
||||
"file": null
|
||||
}
|
||||
}
|
||||
````
|
||||
|
||||
## Environment variables
|
||||
|
||||
GeoIP:
|
||||
|
||||
* `NETTOOL_GEOIP_COUNTRY_DB`
|
||||
* `NETTOOL_GEOIP_ASN_DB`
|
||||
|
||||
Logging:
|
||||
|
||||
* `NETTOOL_LOG_LEVEL`
|
||||
* `NETTOOL_LOG_FORMAT`
|
||||
* `NETTOOL_LOG_FILE`
|
||||
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
# OUTPUT_SCHEMA.md
|
||||
|
||||
```markdown
|
||||
# WTFnet — JSON Output Conventions
|
||||
|
||||
All commands support `--json`.
|
||||
|
||||
## General rules
|
||||
|
||||
- Output must be valid JSON to stdout
|
||||
- Logs always go to stderr
|
||||
- Prefer stable keys; changes should be additive
|
||||
- Include metadata about tool version + timestamp
|
||||
|
||||
## Common wrapper schema (recommended)
|
||||
|
||||
```json
|
||||
{
|
||||
"meta": {
|
||||
"tool": "wtfnet",
|
||||
"version": "0.2.0",
|
||||
"timestamp": "2026-01-15T22:01:00-05:00",
|
||||
"os": "linux|windows",
|
||||
"arch": "x86_64",
|
||||
"privileges": {
|
||||
"is_admin": false,
|
||||
"notes": ["pcap capture requires elevated privileges"]
|
||||
}
|
||||
},
|
||||
"command": {
|
||||
"name": "sys ip",
|
||||
"args": ["--all"]
|
||||
},
|
||||
"data": {},
|
||||
"warnings": [],
|
||||
"errors": []
|
||||
}
|
||||
````
|
||||
|
||||
## Error representation
|
||||
|
||||
* `errors[]` should contain structured objects:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "PERMISSION_DENIED|TIMEOUT|NOT_SUPPORTED|IO_ERROR",
|
||||
"message": "Human readable explanation",
|
||||
"details": { "hint": "Try running as admin" }
|
||||
}
|
||||
```
|
||||
|
||||
## Timing fields (for probe/http/tls)
|
||||
|
||||
Use milliseconds:
|
||||
|
||||
```json
|
||||
{
|
||||
"timing_ms": {
|
||||
"dns_resolve": 12,
|
||||
"connect": 40,
|
||||
"tls_handshake": 55,
|
||||
"ttfb": 70,
|
||||
"total": 120
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
# ROADMAP.md
|
||||
|
||||
```markdown
|
||||
# WTFnet — Roadmap
|
||||
|
||||
## v0.1 (MVP)
|
||||
Focus: core sysadmin essentials
|
||||
- sys: ifaces/ip/route/dns
|
||||
- ports: listen/who
|
||||
- probe: ping + tcping
|
||||
- calc: subnet/contains/overlap
|
||||
- basic logging + --json everywhere
|
||||
|
||||
## v0.2 (this requirements set)
|
||||
- dns: query + detect + watch (best-effort)
|
||||
- geoip: local Country+ASN mmdb integration
|
||||
- http: head/get (HTTP/2 required; HTTP/3 best-effort optional)
|
||||
- tls: handshake/verify/cert/alpn
|
||||
- neigh: ARP/NDP snapshot
|
||||
- discover: mdns + ssdp (bounded)
|
||||
- diag: bundle export (zip)
|
||||
|
||||
## v0.3 (future upgrades)
|
||||
- richer trace output (reverse lookup, per-hop loss)
|
||||
- TLS extras: OCSP stapling indicator, more chain parsing
|
||||
- ports conns improvements (top talkers / summary)
|
||||
- better baseline/diff for system roots
|
||||
- smarter “diagnose <domain>” workflow mode
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
# SECURITY.md
|
||||
|
||||
```markdown
|
||||
# WTFnet — Security & Privacy Notes
|
||||
|
||||
## Data handling
|
||||
- WTFnet performs local inspections and probes.
|
||||
- It does not upload anything automatically.
|
||||
|
||||
## Sensitive output defaults
|
||||
- HTTP bodies are not printed by default.
|
||||
- Secrets (Authorization/Cookies) are never logged by default.
|
||||
|
||||
## Capture-based features
|
||||
Some features (e.g. passive DNS watch) may require elevated privileges.
|
||||
WTFnet must clearly indicate when a feature is:
|
||||
- unavailable
|
||||
- permission-limited
|
||||
- OS-limited
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# docs/platform-notes.md
|
||||
|
||||
```markdown
|
||||
# Platform Notes
|
||||
|
||||
## Linux (Debian/Ubuntu)
|
||||
- sys: netlink (/proc, /sys) sources
|
||||
- neigh: `ip neigh` equivalent via netlink
|
||||
- ports: `/proc/net/*` + process mapping
|
||||
|
||||
## Windows
|
||||
- sys: Win32 APIs (IP Helper API etc.)
|
||||
- ports/process mapping: Windows APIs (best-effort)
|
||||
- cert roots: Windows certificate store APIs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# docs/troubleshooting.md
|
||||
|
||||
```markdown
|
||||
# Troubleshooting
|
||||
|
||||
## `dns watch` shows permission errors
|
||||
Passive capture may require elevated privileges or pcap capabilities.
|
||||
Run as admin/root or configure capture permissions appropriately.
|
||||
|
||||
## `ping` not working without admin
|
||||
Some OS configurations restrict ICMP sockets. Use:
|
||||
- `wtfnet probe tcping <host:port>` as an alternative reachability test.
|
||||
```
|
||||
|
||||
---
|
||||
53
docs/status.md
Normal file
53
docs/status.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# WTFnet Roadmap and Status
|
||||
|
||||
This document tracks the planned roadmap alongside the current implementation status.
|
||||
|
||||
## Roadmap (from docs/requirement_docs.md)
|
||||
|
||||
### v0.1 (MVP)
|
||||
- sys: ifaces/ip/route/dns
|
||||
- ports: listen/who
|
||||
- probe: ping + tcping
|
||||
- calc: subnet/contains/overlap
|
||||
- basic logging + --json everywhere
|
||||
|
||||
### v0.2 (current requirements)
|
||||
- dns: query + detect + watch (best-effort)
|
||||
- geoip: local Country+ASN mmdb integration
|
||||
- http: head/get (HTTP/2 required; HTTP/3 best-effort optional)
|
||||
- tls: handshake/verify/cert/alpn
|
||||
- neigh: ARP/NDP snapshot
|
||||
- discover: mdns + ssdp (bounded)
|
||||
- diag: bundle export (zip)
|
||||
|
||||
### v0.3 (future upgrades)
|
||||
- richer trace output (reverse lookup, per-hop loss)
|
||||
- TLS extras: OCSP stapling indicator, more chain parsing
|
||||
- ports conns improvements (top talkers / summary)
|
||||
- better baseline/diff for system roots
|
||||
- smarter "diagnose <domain>" workflow mode
|
||||
|
||||
## Current stage
|
||||
|
||||
### Implemented
|
||||
- Workspace and core crate scaffold.
|
||||
- Core data model: command envelope, meta, warnings/errors.
|
||||
- Exit code mapping.
|
||||
- Logging initialization with text/json formats and optional file output.
|
||||
- CLI crate scaffold with global flags and logging config wiring (placeholder `sys ifaces`).
|
||||
- Config/env parsing helpers in core (config file + env overrides).
|
||||
- Platform trait crate and OS-specific stub crates for Windows/Linux.
|
||||
- `sys ifaces` implemented in Windows/Linux providers (via `network-interface`) and wired to CLI.
|
||||
- CLI support for `sys ip` and `sys route` (platform routes still OS-specific work).
|
||||
- Platform `sys route` implementations (Linux via `/proc/net`, Windows via `route print` parsing).
|
||||
- Platform `sys dns` implementations (Linux `/etc/resolv.conf`, Windows `ipconfig /all`) and CLI command.
|
||||
- Platform `ports listen/who` best-effort parsing (Linux `/proc/net`, Windows `netstat -ano`).
|
||||
- Platform `neigh list` best-effort parsing (Linux `/proc/net/arp`, Windows `arp -a`).
|
||||
- Platform `cert roots` implementation via native trust store parsing.
|
||||
- CLI commands for `ports listen/who`, `neigh list`, and `cert roots`.
|
||||
|
||||
### In progress
|
||||
- None.
|
||||
|
||||
### Next
|
||||
- Start additional platform/feature crates per dependency map.
|
||||
Reference in New Issue
Block a user