NetRecon
Concurrent TCP port scanner with banner grabbing β the network discovery workhorse of the toolkit.
NetRecon
Concurrent TCP port scanner with banner grabbing β the network discovery workhorse of the toolkit.
Overview
NetRecon probes TCP ports across a target using a fixed worker pool with atomic work-stealing. Each probe performs a timed connect plus an optional banner read. Results are printed as they are found and can be emitted as JSON-lines for pipeline integration.
Key design points:
- Fixed worker pool (default 128 threads) with a shared
Mutex<VecDeque>work queue TcpStream::connect_timeoutβ no OS-level connect hangs- Deterministic service-name mapping for 50+ well-known ports
- Best-effort banner grab: sends a bare
\r\n, reads up to 200 bytes of the reply (works for HTTP, SMTP, FTP, SSH, and more)
Usage
netrecon <target> [ports] [--threads N] [--timeout MS] [--json]
ARGUMENTS:
target IP address, hostname, or CIDR (e.g. 10.0.0.0/24)
ports comma list and/or ranges (default 1-1024)
OPTIONS:
--threads N worker threads (default 128)
--timeout MS connect timeout ms (default 1000)
--top N scan the N most common ports (nmap-style preset)
--json JSON-lines output (includes detected product)Banner-based product detection is built in: HTTP Server: headers,
SSH-2.0 implementation strings, and SMTP/FTP greetings are parsed and
reported for every open port (plain table and --json).
Examples
# Scan localhost for common services
netrecon 127.0.0.1 22,80,443
# Scan a /24 subnet's top ports with 64 threads
netrecon 192.168.1.0/24 1-1024 --threads 64
# Quick sweep: the 50 most common ports with product detection
netrecon 10.0.0.7 --top 50
# Hostname resolution
netrecon example.com 80,443
# JSON output for jq pipelines
netrecon 10.0.0.5 22,80,443,3306 --json | jq .Target expansion
| Input | Expansion |
|---|---|
| Single IP | 127.0.0.1 β one address |
| Hostname | example.com β resolved via ToSocketAddrs (all returned addresses) |
| CIDR | 10.0.0.0/24 β 256 addresses |
| CIDR guard | /0β/7 refused (more than 16M hosts is impractical) |
| IPv6 | Not supported for CIDR (explicit error) |
Port parsing
Ports accept comma-separated lists and lo-hi ranges:
22,80,443 β 22, 80, 443
1-1024 β 1..=1024
22,80,8000-8100 β mixed list and rangeBanner grabbing
After a successful connect, NetRecon:
- Sets read timeout (1.5 s) and write timeout (500 ms)
- Sends a generic
\r\nprobe - Reads up to 512 bytes, keeps the first 200 as UTF-8 (lossy), trims
- Reports the banner alongside the service name
Output
Human-readable:
10.0.0.5:22 ssh OpenSSH_9.2p1 Debian-2+deb12u1
10.0.0.5:80 http
10.0.0.5:443 httpsJSON-lines (--json):
{"addr":"10.0.0.5","port":22,"service":"ssh","banner":"OpenSSH_9.2p1"}Service map (selection)
ftp (20/21) Β· ssh (22) Β· smtp (25) Β· dns (53) Β· http (80) Β·
pop3 (110) Β· msrpc (135) Β· netbios-ssn (139) Β· imap (143) Β·
snmp (161/162) Β· ldap (389) Β· https (443) Β· microsoft-ds (445) Β·
mysql (3306) Β· rdp (3389) Β· postgresql (5432) Β· redis (6379) Β·
kubernetes (6443) Β· mongodb (27017) and 40+ more.
Implementation notes
parse_cidrguards against shift overflow and OOM for huge prefixes- Results are sorted by (address, port) before printing
- The banner field escapes
"for safe JSON embedding