# NetLens (CLI prototype) NetLens is a working prototype that provides TCP port scanning and TCP-connect-based latency probing, both implemented with Go's standard `net` package only. Be explicit: the "ping" command here is a TCP-connect proxy, NOT real ICMP ping. True ICMP echo requires a raw socket, which in turn requires administrator/root privileges on every target platform - incompatible with a portable, dependency-free CLI that should run for any user without elevation. Timing how long a TCP handshake (SYN/SYN-ACK/ACK) takes via net.DialTimeout is the standard, widely used portable substitute, and is what tools like `tcping` and `hping`-in-TCP-mode do as well. The full NetLens product concept also covers per-application bandwidth accounting, live firewall rule visibility, and Windows Filtering Platform (WFP) based route diagnostics. All three need OS-privileged APIs (ETW traces, WFP callout drivers, firewall COM APIs on Windows; comparable privileged interfaces elsewhere) that cannot be reached from a portable, unprivileged, stdlib-only Go binary. Those remain roadmap items - see ../plan.md for the full product plan. ## Build from source Requires Go 1.24+, no external dependencies. go build -o netlens . Cross-compile for another platform: GOOS=windows GOARCH=amd64 go build -o netlens.exe . GOOS=darwin GOARCH=arm64 go build -o netlens . ## Usage netlens [arguments] Commands: scan TCP-connect port scanner ping TCP-connect latency probe (NOT ICMP ping) help Show top-level help ### scan netlens scan --ports [flags] Scans a host for open TCP ports by attempting net.DialTimeout against each port. Scans run concurrently, bounded by a worker pool (not one goroutine per port), so large port ranges do not exhaust resources. Arguments: Hostname or IP address to scan Flags: --ports Comma-separated ports and/or ranges, e.g. "20-25,80,443,8000-8010" (required) --timeout Per-port dial timeout (default 500ms) --concurrency Max concurrent dials (default 100) --json Emit a structured JSON report instead of text -h, --help Show command help Each port is classified as: OPEN dial succeeded; latency is the connect time in ms CLOSED dial failed immediately (connection actively refused) FILTERED dial timed out with no response at all (likely a firewall silently dropping the packet) Text output prints open ports first (ascending by port number) with their connect latency, followed by a summary line with open/closed/ filtered counts and total scan duration. Example: netlens scan example.com --ports 20-25,80,443 --timeout 500ms --concurrency 200 ### ping netlens ping [ ...] [flags] Performs sequential TCP-connect attempts to : for each host given, and reports latency and loss statistics - formatted similarly to a real `ping` summary line, but explicitly labeled as TCP-connect based. The first line of text output always carries a one-line disclaimer: "NetLens ping uses TCP connect timing, not ICMP - see README for why." Arguments: [ ...] One or more hostnames or IP addresses. Every host given gets its own per-host results block. Flags: --port TCP port to connect to (default 80) --count Number of attempts per host (default 4) --timeout Per-attempt dial timeout (default 1s) --interval Delay between attempts (default 200ms) --json Emit a structured JSON report instead of text -h, --help Show command help A connection refusal and a timed-out attempt both count as loss - either way, the probe did not get a completed TCP handshake back in time. After all attempts for a host, NetLens prints min/avg/max latency (over successful attempts only) and the loss percentage. Example: netlens ping example.com api.example.com --port 443 --count 4 ## Prebuilt binaries See ../downloads/ for prebuilt binaries (Windows/macOS/Linux) and CHECKSUMS.txt for their SHA-256 hashes. These are unsigned indie builds - Windows SmartScreen and macOS Gatekeeper will warn on first run, which is expected until a code-signing certificate is in place.