-
Notifications
You must be signed in to change notification settings - Fork 0
Expand README with worked examples for every command #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,13 @@ | ||
| # netprobe-cli | ||
|
|
||
| A small, dependency-light CLI toolkit for everyday network diagnostics: | ||
| subnet math, port sweeps, latency statistics and MAC vendor lookup. | ||
| [](https://github.com/saeed205/netprobe-cli/actions/workflows/ci.yml) | ||
|  | ||
|  | ||
|
|
||
| Everything runs on the Python standard library. No `pip install` of a | ||
| A small CLI toolkit for everyday network diagnostics: subnet math, port sweeps, | ||
| latency statistics, DNS checks, HTTP health and MAC vendor lookup. | ||
|
|
||
| **Zero dependencies.** Everything runs on the Python standard library. No | ||
| transitive dependency tree just to work out how many hosts fit in a /27. | ||
|
|
||
| ## Install | ||
|
|
@@ -12,12 +16,153 @@ transitive dependency tree just to work out how many hosts fit in a /27. | |
| pip install . | ||
| ``` | ||
|
|
||
| ## Usage | ||
| Or run it straight from a checkout without installing: | ||
|
|
||
| ```bash | ||
| python -m netprobe subnet 10.0.0.0/24 | ||
| ``` | ||
|
|
||
| ## Commands | ||
|
|
||
| ### `subnet` - CIDR math | ||
|
|
||
| ```console | ||
| $ netprobe subnet 10.20.30.0/26 | ||
| network : 10.20.30.0 | ||
| prefix : 26 | ||
| netmask : 255.255.255.192 | ||
| wildcard : 0.0.0.63 | ||
| broadcast : 10.20.30.63 | ||
| total_addresses : 64 | ||
| usable_hosts : 62 | ||
| first_host : 10.20.30.1 | ||
| last_host : 10.20.30.62 | ||
| version : 4 | ||
| is_private : yes | ||
| ``` | ||
|
|
||
| Split a block, or test membership via the exit status: | ||
|
|
||
| ```bash | ||
| netprobe subnet 10.0.0.0/24 --split-into 26 | ||
| netprobe subnet 10.0.0.0/8 --contains 10.4.5.6 && echo "inside" | ||
| ``` | ||
|
|
||
| The `/31` and `/32` cases are handled properly: a `/31` is a two-host | ||
| point-to-point link under RFC 3021 and a `/32` is a single host route, so | ||
| neither reserves a broadcast address. | ||
|
|
||
| ### `scan` - TCP port sweep | ||
|
|
||
| ```bash | ||
| netprobe --help | ||
| netprobe scan 10.0.0.5 # 20 common ports | ||
| netprobe scan 10.0.0.5 -p 22,80,8000-8010 | ||
| netprobe scan 10.0.0.0/28 -p 22 -w 128 # a whole subnet | ||
| ``` | ||
|
|
||
| ### `latency` - connect time, loss and jitter | ||
|
|
||
| ```console | ||
| $ netprobe latency example.com -p 443 -c 10 | ||
| target : example.com:443 | ||
| sent : 10 | ||
| received : 10 | ||
| loss_pct : 0.0 | ||
| min_ms : 18.44 | ||
| avg_ms : 21.07 | ||
| p95_ms : 27.31 | ||
| max_ms : 28.02 | ||
| jitter_ms : 3.19 | ||
| ``` | ||
|
|
||
| TCP handshakes, not ICMP - no root needed, and it is rarely filtered. The | ||
| **p95** is the number to watch; an average hides the tail users complain about. | ||
|
|
||
| ### `dns` - forward, reverse and round-trip | ||
|
|
||
| ```bash | ||
| netprobe dns example.com -f v4 | ||
| netprobe dns 8.8.8.8 -x # PTR | ||
| netprobe dns example.com -r # resolve, then PTR back | ||
| ``` | ||
|
|
||
| Resolution goes through `getaddrinfo`, so it reflects what applications on the | ||
| host actually see - `/etc/hosts` and nsswitch included. | ||
|
|
||
| ### `http` - endpoint health and redirect chains | ||
|
|
||
| ```bash | ||
| netprobe http example.com | ||
| netprobe http example.com -L # walk every redirect hop | ||
| netprobe http internal.lan -k # skip TLS verification | ||
| ``` | ||
|
|
||
| ### `mac` - normalise and identify | ||
|
|
||
| ```console | ||
| $ netprobe mac 000c.29ab.cdef | ||
| mac : 00:0c:29:ab:cd:ef | ||
| oui : 000C29 | ||
| vendor : VMware, Inc. | ||
| locally_administered : no | ||
| multicast : no | ||
| note : - | ||
| cisco : 000c.29ab.cdef | ||
| ``` | ||
|
|
||
| Accepts colon, hyphen, Cisco dotted or bare hex. A locally administered | ||
| address (randomised phone MACs, most virtual NICs) is called out as such | ||
| rather than reported as an unhelpful `unknown` vendor. | ||
|
|
||
| ## JSON output | ||
|
|
||
| Every command takes the global `--json` flag: | ||
|
|
||
| ```bash | ||
| netprobe --json scan 10.0.0.0/28 -p 22 | jq -r '.[].host' | ||
| ``` | ||
|
|
||
| Single-result commands emit a JSON object, list commands emit an array - so | ||
| you never have to index `[0]` to reach a scalar result. | ||
|
|
||
| ## Config file | ||
|
|
||
| Defaults can live in `netprobe.ini` instead of being retyped: | ||
|
|
||
| ```ini | ||
| [defaults] | ||
| json = false | ||
|
|
||
| [scan] | ||
| timeout = 0.4 | ||
| workers = 128 | ||
| ``` | ||
|
|
||
| Search order: `$NETPROBE_CONFIG`, then `./netprobe.ini`, then the platform | ||
| config directory. Anything passed on the command line still wins. See | ||
| [`netprobe.ini.example`](netprobe.ini.example). | ||
|
|
||
| ## Exit status | ||
|
|
||
| | code | meaning | | ||
| |---|---| | ||
| | `0` | success, or the tested condition held | | ||
| | `1` | the check failed - nothing resolved, nothing open, endpoint unhealthy | | ||
| | `2` | usage error | | ||
| | `130` | interrupted | | ||
|
|
||
| That makes the commands usable directly in monitoring checks and shell | ||
| conditionals. | ||
|
|
||
| ## Development | ||
|
|
||
| ```bash | ||
| python -m unittest discover -s tests -v | ||
| python -m ruff check . | ||
| ``` | ||
|
|
||
| 84 tests, no test dependencies to install. See [CONTRIBUTING.md](CONTRIBUTING.md). | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| ## License | ||
|
|
||
| MIT - see [LICENSE](LICENSE). | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For redirect chains longer than ten hops,
follow()stops whenlen(hops) == max_hops(default 10), so-Ldoes not walk every redirect hop or show the terminal response. This comment overpromises the behavior precisely for long or looping chains where complete redirect diagnostics matter; describe the ten-hop limit instead.Useful? React with 👍 / 👎.