Add: description in help message
This commit is contained in:
37
README.md
37
README.md
@@ -73,41 +73,8 @@ wtfn calc overlap 10.0.0.0/24 10.0.1.0/24
|
|||||||
wtfn calc summarize 10.0.0.0/24 10.0.1.0/24
|
wtfn calc summarize 10.0.0.0/24 10.0.1.0/24
|
||||||
```
|
```
|
||||||
|
|
||||||
## Supported flags
|
## Command reference
|
||||||
Global flags:
|
See `docs/COMMANDS.md` for the full list of commands and flags (with descriptions).
|
||||||
- `--json` / `--pretty`
|
|
||||||
- `--no-color` / `--quiet`
|
|
||||||
- `-v` / `-vv` / `--verbose`
|
|
||||||
- `--log-level <error|warn|info|debug|trace>`
|
|
||||||
- `--log-format <text|json>`
|
|
||||||
- `--log-file <path>`
|
|
||||||
- `NETTOOL_LOG_FILTER` or `RUST_LOG` can override log filters (ex: `maxminddb::decoder=debug`)
|
|
||||||
|
|
||||||
Command flags (implemented):
|
|
||||||
- `sys ip`: `--all`, `--iface <name>`
|
|
||||||
- `sys route`: `--ipv4`, `--ipv6`, `--to <ip>`
|
|
||||||
- `ports listen`: `--tcp`, `--udp`, `--port <n>`
|
|
||||||
- `neigh list`: `--ipv4`, `--ipv6`, `--iface <name>`
|
|
||||||
- `ports conns`: `--top <n>`, `--by-process`
|
|
||||||
- `cert baseline`: `<path>`
|
|
||||||
- `cert diff`: `<path>`
|
|
||||||
- `probe ping`: `--count <n>`, `--timeout-ms <n>`, `--interval-ms <n>`, `--no-geoip`
|
|
||||||
- `probe tcping`: `--count <n>`, `--timeout-ms <n>`, `--socks5 <url>`, `--prefer-ipv4`, `--no-geoip`
|
|
||||||
- `probe trace`: `--max-hops <n>`, `--per-hop <n>`, `--timeout-ms <n>`, `--udp`, `--port <n>`, `--rdns`, `--no-geoip`
|
|
||||||
- `dns query`: `--server <ip[:port]>`, `--transport <udp|tcp|dot|doh>`, `--tls-name <name>`, `--socks5 <url>`, `--prefer-ipv4`, `--timeout-ms <n>`
|
|
||||||
- `dns detect`: `--servers <csv>`, `--transport <udp|tcp|dot|doh>`, `--tls-name <name>`, `--socks5 <url>`, `--prefer-ipv4`, `--repeat <n>`, `--timeout-ms <n>`
|
|
||||||
- `dns watch`: `--duration <Ns|Nms>`, `--iface <name>`, `--filter <pattern>`
|
|
||||||
- `dns leak status`: `--profile <full-tunnel|proxy-stub|split>`, `--policy <path>`
|
|
||||||
- `dns leak watch`: `--duration <Ns|Nms>`, `--iface <name>`, `--profile <full-tunnel|proxy-stub|split>`, `--policy <path>`, `--privacy <full|redacted|minimal>`, `--out <path>`, `--summary-only`
|
|
||||||
- `dns leak watch`: `--iface-diag` (prints capture-capable interfaces)
|
|
||||||
- `dns leak report`: `<path>`, `--privacy <full|redacted|minimal>`
|
|
||||||
- `http head|get`: `--timeout-ms <n>`, `--follow-redirects <n>`, `--show-headers`, `--show-body`, `--max-body-bytes <n>`, `--http1-only`, `--http2-only`, `--http3` (feature `http3`), `--http3-only` (feature `http3`), `--geoip`, `--socks5 <url>`
|
|
||||||
- `tls handshake|cert|verify|alpn`: `--sni <name>`, `--alpn <csv>`, `--timeout-ms <n>`, `--insecure`, `--socks5 <url>`, `--prefer-ipv4`, `--show-extensions`, `--ocsp`
|
|
||||||
- `discover mdns`: `--duration <Ns|Nms>`, `--service <type>`
|
|
||||||
- `discover ssdp`: `--duration <Ns|Nms>`
|
|
||||||
- `discover llmnr`: `--duration <Ns|Nms>`, `--name <host>`
|
|
||||||
- `discover nbns`: `--duration <Ns|Nms>`
|
|
||||||
- `diag`: `--out <path>`, `--bundle <path>`, `--dns-detect <domain>`, `--dns-timeout-ms <n>`, `--dns-repeat <n>`
|
|
||||||
|
|
||||||
## GeoIP data files
|
## GeoIP data files
|
||||||
GeoLite2 mmdb files should live in `data/`.
|
GeoLite2 mmdb files should live in `data/`.
|
||||||
|
|||||||
@@ -16,21 +16,21 @@ use wtfnet_platform::{Platform, PlatformError};
|
|||||||
arg_required_else_help = true
|
arg_required_else_help = true
|
||||||
)]
|
)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
#[arg(long)]
|
#[arg(long, help = "Emit JSON output")]
|
||||||
json: bool,
|
json: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Pretty-print JSON output")]
|
||||||
pretty: bool,
|
pretty: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Disable ANSI colors")]
|
||||||
no_color: bool,
|
no_color: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Reduce stdout output")]
|
||||||
quiet: bool,
|
quiet: bool,
|
||||||
#[arg(short = 'v', long = "verbose", action = clap::ArgAction::Count)]
|
#[arg(short = 'v', long = "verbose", action = clap::ArgAction::Count, help = "Increase log verbosity (-v, -vv)")]
|
||||||
verbose: u8,
|
verbose: u8,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Set log level (error|warn|info|debug|trace)")]
|
||||||
log_level: Option<String>,
|
log_level: Option<String>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Set log format (text|json)")]
|
||||||
log_format: Option<String>,
|
log_format: Option<String>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Write logs to a file")]
|
||||||
log_file: Option<PathBuf>,
|
log_file: Option<PathBuf>,
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: Commands,
|
command: Commands,
|
||||||
@@ -38,98 +38,130 @@ struct Cli {
|
|||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum Commands {
|
enum Commands {
|
||||||
|
/// System snapshot: interfaces, IPs, routes, DNS
|
||||||
Sys {
|
Sys {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: SysCommand,
|
command: SysCommand,
|
||||||
},
|
},
|
||||||
|
/// Ports and socket ownership
|
||||||
Ports {
|
Ports {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: PortsCommand,
|
command: PortsCommand,
|
||||||
},
|
},
|
||||||
|
/// Neighbor table (ARP/NDP)
|
||||||
Neigh {
|
Neigh {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: NeighCommand,
|
command: NeighCommand,
|
||||||
},
|
},
|
||||||
|
/// Certificate roots and baselines
|
||||||
Cert {
|
Cert {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: CertCommand,
|
command: CertCommand,
|
||||||
},
|
},
|
||||||
|
/// GeoIP lookup helpers
|
||||||
Geoip {
|
Geoip {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: GeoIpCommand,
|
command: GeoIpCommand,
|
||||||
},
|
},
|
||||||
|
/// Probing tools (ping/tcping/trace)
|
||||||
Probe {
|
Probe {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: ProbeCommand,
|
command: ProbeCommand,
|
||||||
},
|
},
|
||||||
|
/// DNS query, detect, watch, and leak detection
|
||||||
Dns {
|
Dns {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: DnsCommand,
|
command: DnsCommand,
|
||||||
},
|
},
|
||||||
|
/// Subnet calculator
|
||||||
Calc {
|
Calc {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: CalcCommand,
|
command: CalcCommand,
|
||||||
},
|
},
|
||||||
|
/// HTTP head/get diagnostics
|
||||||
Http {
|
Http {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: HttpCommand,
|
command: HttpCommand,
|
||||||
},
|
},
|
||||||
|
/// TLS handshake and certificate analysis
|
||||||
Tls {
|
Tls {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: TlsCommand,
|
command: TlsCommand,
|
||||||
},
|
},
|
||||||
|
/// Local network discovery (mDNS/SSDP/LLMNR/NBNS)
|
||||||
Discover {
|
Discover {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: DiscoverCommand,
|
command: DiscoverCommand,
|
||||||
},
|
},
|
||||||
|
/// Bundle a diagnostic report
|
||||||
Diag(DiagArgs),
|
Diag(DiagArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum SysCommand {
|
enum SysCommand {
|
||||||
|
/// List network interfaces
|
||||||
Ifaces,
|
Ifaces,
|
||||||
|
/// Show IP addresses
|
||||||
Ip(SysIpArgs),
|
Ip(SysIpArgs),
|
||||||
|
/// Show route table
|
||||||
Route(SysRouteArgs),
|
Route(SysRouteArgs),
|
||||||
|
/// Show DNS configuration
|
||||||
Dns,
|
Dns,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum PortsCommand {
|
enum PortsCommand {
|
||||||
|
/// List listening sockets
|
||||||
Listen(PortsListenArgs),
|
Listen(PortsListenArgs),
|
||||||
|
/// Find socket owners for a port
|
||||||
Who(PortsWhoArgs),
|
Who(PortsWhoArgs),
|
||||||
|
/// List active TCP connections
|
||||||
Conns(PortsConnsArgs),
|
Conns(PortsConnsArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum NeighCommand {
|
enum NeighCommand {
|
||||||
|
/// List ARP/NDP neighbors
|
||||||
List(NeighListArgs),
|
List(NeighListArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum CertCommand {
|
enum CertCommand {
|
||||||
|
/// List trusted root certificates
|
||||||
Roots,
|
Roots,
|
||||||
|
/// Write a baseline file of trusted roots
|
||||||
Baseline(CertBaselineArgs),
|
Baseline(CertBaselineArgs),
|
||||||
|
/// Diff trusted roots against a baseline
|
||||||
Diff(CertDiffArgs),
|
Diff(CertDiffArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum GeoIpCommand {
|
enum GeoIpCommand {
|
||||||
|
/// Lookup GeoIP for an IP address
|
||||||
Lookup(GeoIpLookupArgs),
|
Lookup(GeoIpLookupArgs),
|
||||||
|
/// Show GeoIP database status
|
||||||
Status,
|
Status,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum ProbeCommand {
|
enum ProbeCommand {
|
||||||
|
/// ICMP ping
|
||||||
Ping(ProbePingArgs),
|
Ping(ProbePingArgs),
|
||||||
|
/// TCP ping (connect timing)
|
||||||
Tcping(ProbeTcpingArgs),
|
Tcping(ProbeTcpingArgs),
|
||||||
|
/// Traceroute
|
||||||
Trace(ProbeTraceArgs),
|
Trace(ProbeTraceArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum DnsCommand {
|
enum DnsCommand {
|
||||||
|
/// DNS query
|
||||||
Query(DnsQueryArgs),
|
Query(DnsQueryArgs),
|
||||||
|
/// DNS poisoning detection (active)
|
||||||
Detect(DnsDetectArgs),
|
Detect(DnsDetectArgs),
|
||||||
|
/// DNS passive watch (pcap)
|
||||||
Watch(DnsWatchArgs),
|
Watch(DnsWatchArgs),
|
||||||
|
/// DNS leak detection
|
||||||
Leak {
|
Leak {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: DnsLeakCommand,
|
command: DnsLeakCommand,
|
||||||
@@ -138,345 +170,381 @@ enum DnsCommand {
|
|||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum DnsLeakCommand {
|
enum DnsLeakCommand {
|
||||||
|
/// Show current policy and interface snapshot
|
||||||
Status(DnsLeakStatusArgs),
|
Status(DnsLeakStatusArgs),
|
||||||
|
/// Passive leak detection watch
|
||||||
Watch(DnsLeakWatchArgs),
|
Watch(DnsLeakWatchArgs),
|
||||||
|
/// Summarize a saved leak report
|
||||||
Report(DnsLeakReportArgs),
|
Report(DnsLeakReportArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum CalcCommand {
|
enum CalcCommand {
|
||||||
|
/// Subnet info
|
||||||
Subnet(CalcSubnetArgs),
|
Subnet(CalcSubnetArgs),
|
||||||
|
/// Check CIDR containment
|
||||||
Contains(CalcContainsArgs),
|
Contains(CalcContainsArgs),
|
||||||
|
/// Check CIDR overlap
|
||||||
Overlap(CalcOverlapArgs),
|
Overlap(CalcOverlapArgs),
|
||||||
|
/// Summarize CIDRs
|
||||||
Summarize(CalcSummarizeArgs),
|
Summarize(CalcSummarizeArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum HttpCommand {
|
enum HttpCommand {
|
||||||
|
/// HTTP HEAD request
|
||||||
Head(HttpRequestArgs),
|
Head(HttpRequestArgs),
|
||||||
|
/// HTTP GET request
|
||||||
Get(HttpRequestArgs),
|
Get(HttpRequestArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum TlsCommand {
|
enum TlsCommand {
|
||||||
|
/// TLS handshake summary
|
||||||
Handshake(TlsArgs),
|
Handshake(TlsArgs),
|
||||||
|
/// TLS certificate details
|
||||||
Cert(TlsArgs),
|
Cert(TlsArgs),
|
||||||
|
/// TLS verification
|
||||||
Verify(TlsArgs),
|
Verify(TlsArgs),
|
||||||
|
/// TLS ALPN negotiation
|
||||||
Alpn(TlsArgs),
|
Alpn(TlsArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum DiscoverCommand {
|
enum DiscoverCommand {
|
||||||
|
/// mDNS discovery
|
||||||
Mdns(DiscoverMdnsArgs),
|
Mdns(DiscoverMdnsArgs),
|
||||||
|
/// SSDP discovery
|
||||||
Ssdp(DiscoverSsdpArgs),
|
Ssdp(DiscoverSsdpArgs),
|
||||||
|
/// LLMNR discovery
|
||||||
Llmnr(DiscoverLlmnrArgs),
|
Llmnr(DiscoverLlmnrArgs),
|
||||||
|
/// NBNS discovery
|
||||||
Nbns(DiscoverNbnsArgs),
|
Nbns(DiscoverNbnsArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct SysIpArgs {
|
struct SysIpArgs {
|
||||||
#[arg(long)]
|
#[arg(long, help = "Show all addresses (including link-local)")]
|
||||||
all: bool,
|
all: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Filter by interface name")]
|
||||||
iface: Option<String>,
|
iface: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct SysRouteArgs {
|
struct SysRouteArgs {
|
||||||
#[arg(long)]
|
#[arg(long, help = "Show IPv4 routes")]
|
||||||
ipv4: bool,
|
ipv4: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Show IPv6 routes")]
|
||||||
ipv6: bool,
|
ipv6: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Filter routes by destination")]
|
||||||
to: Option<String>,
|
to: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct PortsListenArgs {
|
struct PortsListenArgs {
|
||||||
#[arg(long)]
|
#[arg(long, help = "Show TCP listeners")]
|
||||||
tcp: bool,
|
tcp: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Show UDP listeners")]
|
||||||
udp: bool,
|
udp: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Filter by port")]
|
||||||
port: Option<u16>,
|
port: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct PortsWhoArgs {
|
struct PortsWhoArgs {
|
||||||
|
#[arg(help = "Target port number")]
|
||||||
target: String,
|
target: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct PortsConnsArgs {
|
struct PortsConnsArgs {
|
||||||
#[arg(long)]
|
#[arg(long, help = "Show top N remote endpoints")]
|
||||||
top: Option<usize>,
|
top: Option<usize>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Group by process")]
|
||||||
by_process: bool,
|
by_process: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct NeighListArgs {
|
struct NeighListArgs {
|
||||||
#[arg(long)]
|
#[arg(long, help = "Show IPv4 neighbors")]
|
||||||
ipv4: bool,
|
ipv4: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Show IPv6 neighbors")]
|
||||||
ipv6: bool,
|
ipv6: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Filter by interface name")]
|
||||||
iface: Option<String>,
|
iface: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct GeoIpLookupArgs {
|
struct GeoIpLookupArgs {
|
||||||
|
#[arg(help = "Target IP address")]
|
||||||
target: String,
|
target: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct CertBaselineArgs {
|
struct CertBaselineArgs {
|
||||||
|
#[arg(help = "Path to write baseline JSON")]
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct CertDiffArgs {
|
struct CertDiffArgs {
|
||||||
|
#[arg(help = "Path to baseline JSON")]
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct ProbePingArgs {
|
struct ProbePingArgs {
|
||||||
|
#[arg(help = "Target hostname or IP")]
|
||||||
target: String,
|
target: String,
|
||||||
#[arg(long, default_value_t = 4)]
|
#[arg(long, default_value_t = 4, help = "Ping count")]
|
||||||
count: u32,
|
count: u32,
|
||||||
#[arg(long, default_value_t = 800)]
|
#[arg(long, default_value_t = 800, help = "Timeout per ping (ms)")]
|
||||||
timeout_ms: u64,
|
timeout_ms: u64,
|
||||||
#[arg(long, default_value_t = 200)]
|
#[arg(long, default_value_t = 200, help = "Interval between pings (ms)")]
|
||||||
interval_ms: u64,
|
interval_ms: u64,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Disable GeoIP enrichment")]
|
||||||
no_geoip: bool,
|
no_geoip: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct ProbeTcpingArgs {
|
struct ProbeTcpingArgs {
|
||||||
|
#[arg(help = "Target host:port")]
|
||||||
target: String,
|
target: String,
|
||||||
#[arg(long, default_value_t = 4)]
|
#[arg(long, default_value_t = 4, help = "Ping count")]
|
||||||
count: u32,
|
count: u32,
|
||||||
#[arg(long, default_value_t = 800)]
|
#[arg(long, default_value_t = 800, help = "Timeout per connect (ms)")]
|
||||||
timeout_ms: u64,
|
timeout_ms: u64,
|
||||||
#[arg(long)]
|
#[arg(long, help = "SOCKS5 proxy URL")]
|
||||||
socks5: Option<String>,
|
socks5: Option<String>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Prefer IPv4 resolution")]
|
||||||
prefer_ipv4: bool,
|
prefer_ipv4: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Disable GeoIP enrichment")]
|
||||||
no_geoip: bool,
|
no_geoip: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct ProbeTraceArgs {
|
struct ProbeTraceArgs {
|
||||||
|
#[arg(help = "Target host:port")]
|
||||||
target: String,
|
target: String,
|
||||||
#[arg(long, default_value_t = 30)]
|
#[arg(long, default_value_t = 30, help = "Maximum hops")]
|
||||||
max_hops: u8,
|
max_hops: u8,
|
||||||
#[arg(long, default_value_t = 3)]
|
#[arg(long, default_value_t = 3, help = "Probes per hop")]
|
||||||
per_hop: u32,
|
per_hop: u32,
|
||||||
#[arg(long, default_value_t = 800)]
|
#[arg(long, default_value_t = 800, help = "Timeout per hop (ms)")]
|
||||||
timeout_ms: u64,
|
timeout_ms: u64,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Use UDP traceroute")]
|
||||||
udp: bool,
|
udp: bool,
|
||||||
#[arg(long, default_value_t = 33434)]
|
#[arg(long, default_value_t = 33434, help = "Destination port for UDP/TCP trace")]
|
||||||
port: u16,
|
port: u16,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Reverse DNS lookup per hop")]
|
||||||
rdns: bool,
|
rdns: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Disable GeoIP enrichment")]
|
||||||
no_geoip: bool,
|
no_geoip: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct DnsQueryArgs {
|
struct DnsQueryArgs {
|
||||||
|
#[arg(help = "Domain name to query")]
|
||||||
domain: String,
|
domain: String,
|
||||||
|
#[arg(help = "Record type (A, AAAA, MX, TXT, ...)")]
|
||||||
record_type: String,
|
record_type: String,
|
||||||
#[arg(long)]
|
#[arg(long, help = "DNS server IP[:port]")]
|
||||||
server: Option<String>,
|
server: Option<String>,
|
||||||
#[arg(long, default_value = "udp")]
|
#[arg(long, default_value = "udp", help = "Transport (udp|tcp|dot|doh)")]
|
||||||
transport: String,
|
transport: String,
|
||||||
#[arg(long)]
|
#[arg(long, help = "TLS server name for DoT/DoH")]
|
||||||
tls_name: Option<String>,
|
tls_name: Option<String>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "SOCKS5 proxy URL")]
|
||||||
socks5: Option<String>,
|
socks5: Option<String>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Prefer IPv4 resolution")]
|
||||||
prefer_ipv4: bool,
|
prefer_ipv4: bool,
|
||||||
#[arg(long, default_value_t = 2000)]
|
#[arg(long, default_value_t = 2000, help = "Timeout (ms)")]
|
||||||
timeout_ms: u64,
|
timeout_ms: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct DnsDetectArgs {
|
struct DnsDetectArgs {
|
||||||
|
#[arg(help = "Domain name to test")]
|
||||||
domain: String,
|
domain: String,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Comma-separated DNS servers")]
|
||||||
servers: Option<String>,
|
servers: Option<String>,
|
||||||
#[arg(long, default_value = "udp")]
|
#[arg(long, default_value = "udp", help = "Transport (udp|tcp|dot|doh)")]
|
||||||
transport: String,
|
transport: String,
|
||||||
#[arg(long)]
|
#[arg(long, help = "TLS server name for DoT/DoH")]
|
||||||
tls_name: Option<String>,
|
tls_name: Option<String>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "SOCKS5 proxy URL")]
|
||||||
socks5: Option<String>,
|
socks5: Option<String>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Prefer IPv4 resolution")]
|
||||||
prefer_ipv4: bool,
|
prefer_ipv4: bool,
|
||||||
#[arg(long, default_value_t = 3)]
|
#[arg(long, default_value_t = 3, help = "Repeat count per server")]
|
||||||
repeat: u32,
|
repeat: u32,
|
||||||
#[arg(long, default_value_t = 2000)]
|
#[arg(long, default_value_t = 2000, help = "Timeout (ms)")]
|
||||||
timeout_ms: u64,
|
timeout_ms: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct DnsWatchArgs {
|
struct DnsWatchArgs {
|
||||||
#[arg(long, default_value = "30s")]
|
#[arg(long, default_value = "30s", help = "Capture duration")]
|
||||||
duration: String,
|
duration: String,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Capture interface name")]
|
||||||
iface: Option<String>,
|
iface: Option<String>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Filter by domain substring")]
|
||||||
filter: Option<String>,
|
filter: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct DnsLeakStatusArgs {
|
struct DnsLeakStatusArgs {
|
||||||
#[arg(long)]
|
#[arg(long, help = "Policy profile (full-tunnel|proxy-stub|split)")]
|
||||||
profile: Option<String>,
|
profile: Option<String>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Path to policy JSON")]
|
||||||
policy: Option<PathBuf>,
|
policy: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct DnsLeakWatchArgs {
|
struct DnsLeakWatchArgs {
|
||||||
#[arg(long, default_value = "10s")]
|
#[arg(long, default_value = "10s", help = "Capture duration")]
|
||||||
duration: String,
|
duration: String,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Capture interface name")]
|
||||||
iface: Option<String>,
|
iface: Option<String>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Policy profile (full-tunnel|proxy-stub|split)")]
|
||||||
profile: Option<String>,
|
profile: Option<String>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Path to policy JSON")]
|
||||||
policy: Option<PathBuf>,
|
policy: Option<PathBuf>,
|
||||||
#[arg(long, default_value = "redacted")]
|
#[arg(long, default_value = "redacted", help = "Privacy mode (full|redacted|minimal)")]
|
||||||
privacy: String,
|
privacy: String,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Write JSON report to file")]
|
||||||
out: Option<PathBuf>,
|
out: Option<PathBuf>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Only print summary (no events)")]
|
||||||
summary_only: bool,
|
summary_only: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "List capture-capable interfaces and exit")]
|
||||||
iface_diag: bool,
|
iface_diag: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct DnsLeakReportArgs {
|
struct DnsLeakReportArgs {
|
||||||
|
#[arg(help = "Path to leak report JSON")]
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
#[arg(long, default_value = "redacted")]
|
#[arg(long, default_value = "redacted", help = "Privacy mode (full|redacted|minimal)")]
|
||||||
privacy: String,
|
privacy: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct CalcSubnetArgs {
|
struct CalcSubnetArgs {
|
||||||
|
#[arg(help = "CIDR or IP + mask")]
|
||||||
input: Vec<String>,
|
input: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct CalcContainsArgs {
|
struct CalcContainsArgs {
|
||||||
|
#[arg(help = "CIDR A")]
|
||||||
a: String,
|
a: String,
|
||||||
|
#[arg(help = "CIDR B")]
|
||||||
b: String,
|
b: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct CalcOverlapArgs {
|
struct CalcOverlapArgs {
|
||||||
|
#[arg(help = "CIDR A")]
|
||||||
a: String,
|
a: String,
|
||||||
|
#[arg(help = "CIDR B")]
|
||||||
b: String,
|
b: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct CalcSummarizeArgs {
|
struct CalcSummarizeArgs {
|
||||||
|
#[arg(help = "CIDR list to summarize")]
|
||||||
cidrs: Vec<String>,
|
cidrs: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct HttpRequestArgs {
|
struct HttpRequestArgs {
|
||||||
|
#[arg(help = "Target URL")]
|
||||||
url: String,
|
url: String,
|
||||||
#[arg(long, default_value_t = 3000)]
|
#[arg(long, default_value_t = 3000, help = "Request timeout (ms)")]
|
||||||
timeout_ms: u64,
|
timeout_ms: u64,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Follow redirects (limit)")]
|
||||||
follow_redirects: Option<u32>,
|
follow_redirects: Option<u32>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Include response headers")]
|
||||||
show_headers: bool,
|
show_headers: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Include response body")]
|
||||||
show_body: bool,
|
show_body: bool,
|
||||||
#[arg(long, default_value_t = 8192)]
|
#[arg(long, default_value_t = 8192, help = "Max body bytes")]
|
||||||
max_body_bytes: usize,
|
max_body_bytes: usize,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Force HTTP/1.1 only")]
|
||||||
http1_only: bool,
|
http1_only: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Force HTTP/2 prior knowledge")]
|
||||||
http2_only: bool,
|
http2_only: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Enable HTTP/3 (feature gated)")]
|
||||||
http3: bool,
|
http3: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Require HTTP/3 (feature gated)")]
|
||||||
http3_only: bool,
|
http3_only: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Enable GeoIP enrichment")]
|
||||||
geoip: bool,
|
geoip: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "SOCKS5 proxy URL")]
|
||||||
socks5: Option<String>,
|
socks5: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct TlsArgs {
|
struct TlsArgs {
|
||||||
|
#[arg(help = "Target host:port")]
|
||||||
target: String,
|
target: String,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Override SNI")]
|
||||||
sni: Option<String>,
|
sni: Option<String>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "ALPN protocols (comma-separated)")]
|
||||||
alpn: Option<String>,
|
alpn: Option<String>,
|
||||||
#[arg(long, default_value_t = 3000)]
|
#[arg(long, default_value_t = 3000, help = "Timeout (ms)")]
|
||||||
timeout_ms: u64,
|
timeout_ms: u64,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Skip TLS verification")]
|
||||||
insecure: bool,
|
insecure: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "SOCKS5 proxy URL")]
|
||||||
socks5: Option<String>,
|
socks5: Option<String>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Prefer IPv4 resolution")]
|
||||||
prefer_ipv4: bool,
|
prefer_ipv4: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Show X.509 extensions")]
|
||||||
show_extensions: bool,
|
show_extensions: bool,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Show OCSP stapling if available")]
|
||||||
ocsp: bool,
|
ocsp: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct DiscoverMdnsArgs {
|
struct DiscoverMdnsArgs {
|
||||||
#[arg(long, default_value = "3s")]
|
#[arg(long, default_value = "3s", help = "Capture duration")]
|
||||||
duration: String,
|
duration: String,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Service type filter")]
|
||||||
service: Option<String>,
|
service: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct DiscoverSsdpArgs {
|
struct DiscoverSsdpArgs {
|
||||||
#[arg(long, default_value = "3s")]
|
#[arg(long, default_value = "3s", help = "Capture duration")]
|
||||||
duration: String,
|
duration: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct DiscoverLlmnrArgs {
|
struct DiscoverLlmnrArgs {
|
||||||
#[arg(long, default_value = "3s")]
|
#[arg(long, default_value = "3s", help = "Capture duration")]
|
||||||
duration: String,
|
duration: String,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Query name (default: wpad)")]
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct DiscoverNbnsArgs {
|
struct DiscoverNbnsArgs {
|
||||||
#[arg(long, default_value = "3s")]
|
#[arg(long, default_value = "3s", help = "Capture duration")]
|
||||||
duration: String,
|
duration: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct DiagArgs {
|
struct DiagArgs {
|
||||||
#[arg(long)]
|
#[arg(long, help = "Write JSON report to file")]
|
||||||
out: Option<PathBuf>,
|
out: Option<PathBuf>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Write zip bundle to file")]
|
||||||
bundle: Option<PathBuf>,
|
bundle: Option<PathBuf>,
|
||||||
#[arg(long)]
|
#[arg(long, help = "Run DNS detect on domain")]
|
||||||
dns_detect: Option<String>,
|
dns_detect: Option<String>,
|
||||||
#[arg(long, default_value_t = 2000)]
|
#[arg(long, default_value_t = 2000, help = "DNS detect timeout (ms)")]
|
||||||
dns_timeout_ms: u64,
|
dns_timeout_ms: u64,
|
||||||
#[arg(long, default_value_t = 3)]
|
#[arg(long, default_value_t = 3, help = "DNS detect repeat count")]
|
||||||
dns_repeat: u32,
|
dns_repeat: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,36 +3,36 @@
|
|||||||
This document lists CLI commands and supported flags. Output defaults to text; use `--json` for structured output.
|
This document lists CLI commands and supported flags. Output defaults to text; use `--json` for structured output.
|
||||||
|
|
||||||
## Global flags
|
## Global flags
|
||||||
- `--json` / `--pretty`
|
- `--json` / `--pretty`: emit JSON output (pretty-print if requested)
|
||||||
- `--no-color` / `--quiet`
|
- `--no-color` / `--quiet`: disable ANSI colors / reduce stdout output
|
||||||
- `-v` / `-vv` / `--verbose`
|
- `-v` / `-vv` / `--verbose`: increase log verbosity
|
||||||
- `--log-level <error|warn|info|debug|trace>`
|
- `--log-level <error|warn|info|debug|trace>`: set log level
|
||||||
- `--log-format <text|json>`
|
- `--log-format <text|json>`: set log format
|
||||||
- `--log-file <path>`
|
- `--log-file <path>`: write logs to file
|
||||||
- `NETTOOL_LOG_FILTER` or `RUST_LOG` can override log filters (ex: `maxminddb::decoder=debug`)
|
- `NETTOOL_LOG_FILTER` or `RUST_LOG` can override log filters (ex: `maxminddb::decoder=debug`)
|
||||||
|
|
||||||
## sys
|
## sys
|
||||||
- `sys ifaces`
|
- `sys ifaces`: list network interfaces
|
||||||
- `sys ip` flags: `--all`, `--iface <name>`
|
- `sys ip` flags: `--all` (include link-local), `--iface <name>` (filter by interface)
|
||||||
- `sys route` flags: `--ipv4`, `--ipv6`, `--to <ip>`
|
- `sys route` flags: `--ipv4`, `--ipv6`, `--to <ip>` (filter by destination)
|
||||||
- `sys dns`
|
- `sys dns`: show DNS configuration
|
||||||
|
|
||||||
## ports
|
## ports
|
||||||
- `ports listen` flags: `--tcp`, `--udp`, `--port <n>`
|
- `ports listen` flags: `--tcp`, `--udp`, `--port <n>` (filter by port)
|
||||||
- `ports who <port>`
|
- `ports who <port>`: find owning processes for a port
|
||||||
- `ports conns` flags: `--top <n>`, `--by-process`
|
- `ports conns` flags: `--top <n>`, `--by-process` (summaries)
|
||||||
|
|
||||||
## neigh
|
## neigh
|
||||||
- `neigh list` flags: `--ipv4`, `--ipv6`, `--iface <name>`
|
- `neigh list` flags: `--ipv4`, `--ipv6`, `--iface <name>`
|
||||||
|
|
||||||
## cert
|
## cert
|
||||||
- `cert roots`
|
- `cert roots`: list trusted root certificates
|
||||||
- `cert baseline <path>`
|
- `cert baseline <path>`: write baseline JSON
|
||||||
- `cert diff <path>`
|
- `cert diff <path>`: diff against baseline JSON
|
||||||
|
|
||||||
## geoip
|
## geoip
|
||||||
- `geoip lookup <ip>`
|
- `geoip lookup <ip>`: lookup GeoIP
|
||||||
- `geoip status`
|
- `geoip status`: show GeoIP database status
|
||||||
|
|
||||||
## probe
|
## probe
|
||||||
- `probe ping <host>` flags: `--count <n>`, `--timeout-ms <n>`, `--interval-ms <n>`, `--no-geoip`
|
- `probe ping <host>` flags: `--count <n>`, `--timeout-ms <n>`, `--interval-ms <n>`, `--no-geoip`
|
||||||
@@ -44,7 +44,7 @@ This document lists CLI commands and supported flags. Output defaults to text; u
|
|||||||
- `dns detect <domain>` flags: `--servers <csv>`, `--transport <udp|tcp|dot|doh>`, `--tls-name <name>`, `--socks5 <url>`, `--prefer-ipv4`, `--repeat <n>`, `--timeout-ms <n>`
|
- `dns detect <domain>` flags: `--servers <csv>`, `--transport <udp|tcp|dot|doh>`, `--tls-name <name>`, `--socks5 <url>`, `--prefer-ipv4`, `--repeat <n>`, `--timeout-ms <n>`
|
||||||
- `dns watch` flags: `--duration <Ns|Nms>`, `--iface <name>`, `--filter <pattern>`
|
- `dns watch` flags: `--duration <Ns|Nms>`, `--iface <name>`, `--filter <pattern>`
|
||||||
- `dns leak status` flags: `--profile <full-tunnel|proxy-stub|split>`, `--policy <path>`
|
- `dns leak status` flags: `--profile <full-tunnel|proxy-stub|split>`, `--policy <path>`
|
||||||
- `dns leak watch` flags: `--duration <Ns|Nms>`, `--iface <name>`, `--profile <full-tunnel|proxy-stub|split>`, `--policy <path>`, `--privacy <full|redacted|minimal>`, `--out <path>`, `--summary-only`, `--iface-diag`
|
- `dns leak watch` flags: `--duration <Ns|Nms>`, `--iface <name>`, `--profile <full-tunnel|proxy-stub|split>`, `--policy <path>`, `--privacy <full|redacted|minimal>`, `--out <path>`, `--summary-only`, `--iface-diag` (list capture-capable interfaces)
|
||||||
- `dns leak report` flags: `<path>`, `--privacy <full|redacted|minimal>`
|
- `dns leak report` flags: `<path>`, `--privacy <full|redacted|minimal>`
|
||||||
|
|
||||||
## http
|
## http
|
||||||
|
|||||||
Reference in New Issue
Block a user