zig build -Doptimize=ReleaseFast && ./zig-out/bin/zigscanner -p 1-65535 -sV 192.168.1.1 — copy the binary. run it. that's it.
▸ Live output preview
zigscanner v0.1.0 — scanning 192.168.1.100 100 threads · 1000ms timeout · TCP connect
[*] Target: 192.168.1.100
[*] Port range: 1-1024
[*] Threads: 100  Timeout: 1000ms

[*] Resolved 192.168.1.100 -> 192.168.1.100
[*] Scanning 1024 ports with 100 threads...

  [+] 22/tcp   open  ssh
  [+] 80/tcp   open  http
  [+] 443/tcp  open  https
  [+] 3306/tcp open  mysql  

──────────────────────────────────────────────────────────
  Scan Results for: 192.168.1.100
──────────────────────────────────────────────────────────

  Host Status  : UP (2.31ms latency)
  OS Guess     : Linux (web server stack) (confidence: low-medium)
  Ports Scanned: 1024
  Open Ports   : 4
  Scan Time    : 3842ms

  PORT     STATE        SERVICE              VERSION/INFO
  ─────────────────────────────────────────────────────
  22/tcp   open         ssh                  | OpenSSH_8.9p1
  80/tcp   open         http                 | Apache/2.4.54
  443/tcp  open         https
  3306/tcp open         mysql               

  ⚠  SECURITY NOTES:
    Port 3306 (mysql): Databases exposed to the network.
     Verify this is intentional and access is restricted.
zigscanner is a network port scanner and reconnaissance tool. You point it at a host, it tells you what's listening. TCP connect, SYN stealth, UDP — with banner grabbing, OS fingerprinting, service version detection, and security warnings for dangerous exposures. Single static binary. Zero external dependencies. Copy it somewhere, run it. Done.
▸ Installation
$ git clone https://github.com/YOUR_USERNAME/zigscanner && cd zigscanner
$ zig build -Doptimize=ReleaseFast # requires Zig 0.13+
$ ./zig-out/bin/zigscanner 192.168.1.1
$ sudo cp ./zig-out/bin/zigscanner /usr/local/bin/ # optional: install globally

Requires Zig 0.13+. No other dependencies — not even libpcap. Get Zig at ziglang.org/download. The binary is fully static: copy it to any machine and it runs. SYN scan requires root or CAP_NET_RAW.

Cross-compile from any platform →
Windows x64zig build -Dtarget=x86_64-windows -Doptimize=ReleaseFast
Linux ARM64zig build -Dtarget=aarch64-linux -Doptimize=ReleaseFast
macOS Apple Siliconzig build -Dtarget=aarch64-macos -Doptimize=ReleaseFast
32-bit Linuxzig build -Dtarget=x86-linux -Doptimize=ReleaseFast
▸ Features
  • [+] TCP Connect scan — full handshake, no root required, reliable
  • [+] TCP SYN scan — half-open stealth scan (root / CAP_NET_RAW)
  • [+] UDP scan — probes common UDP services with protocol payloads
  • [+] Ping / host discovery mode — liveness check without port scan
  • [+] Atomic work-stealing thread pool — up to 5000 concurrent threads
  • [+] Banner grabbing — reads what services say when you connect
  • [+] Version detection — parses SSH, HTTP, FTP banners into clean strings
  • [+] OS fingerprinting — heuristic from port patterns + banner content
  • [+] Web framework detection — Apache, nginx, IIS, Express, Flask, Tomcat
  • [+] ~70 port → service name mappings (Redis, Docker, K8s, Kafka…)
  • [+] Security warnings for dangerously exposed services
  • [+] Real-time port discovery output during scan
  • [+] JSON export — full structured output for SIEM / pipeline use
  • [+] Flexible port ranges — 80, 1-1024, top, all
  • [+] Hostname resolution — shows resolved IP alongside target
  • [+] Zero external dependencies — entire tool is Zig stdlib
  • [+] Single static binary — no runtime, no interpreter, no install
  • [ ] IPv6 support — planned
  • [ ] CIDR range scanning — planned
  • [ ] NSE-style scripting — not planned (use nmap for that)
▸ Scan modes
Flag Mode Description Root?
(default) TCP Connect Full three-way handshake. Reliable, logged by target. No
-sS / --syn TCP SYN Half-open scan. Sends SYN, never completes handshake. Faster, less logged. Yes
-sU / --udp UDP Probes common UDP services. Slow by nature — no handshake to confirm open/closed. No
-sn / --ping Ping / Discovery Host liveness only — attempts TCP to ports 80, 443, 22, 8080. No port scan. No
▸ CLI options
Flag Description Default
-p / --portsPort range: 80, 1-1024, top, all / 1-655351-1024
-t / --threadsConcurrent scanning threads (1–5000)100
--timeoutConnection timeout in milliseconds1000ms
-sS / --synTCP SYN stealth scan (root required)
-sU / --udpUDP scan mode
-sn / --pingPing / host discovery only, no port scan
-sV / --service-detectBanner grabbing + version parsing on open ports
-O / --os-detectOS fingerprinting (heuristic — low-medium confidence)
-v / --verboseVerbose output — shows raw banners, extra detail
-o / --outputWrite results as JSON to specified file
-h / --helpShow help and exit
-V / --versionPrint version string and exit
▸ Performance — local 1Gbps network benchmarks
ConfigPort RangeTimeNotes
Default (100t, 1000ms)1-1024~4sGood general use
Fast (500t, 300ms)1-1024~1sMay miss some filtered
Default (100t, 1000ms)1-65535~4.5 minThorough, safe
Fast (500t, 300ms)1-65535~45sFast, potentially noisy
Aggressive (1000t, 200ms)1-65535~20sOnly when you need it
Over WAN: expect 10–30× slower due to latency. Use --timeout 3000 or higher for internet targets. High thread counts on slow links can cause packet loss — tune down threads, tune up timeout.
▸ Security warnings — flagged ports
PortServiceWhy it's flagged
21FTPCredentials transmitted in plaintext
23TelnetEntirely unencrypted. Retire it.
2375Docker APIUnauthenticated = instant full host compromise
2379etcdContains K8s cluster secrets in plaintext
3389RDPFrequent brute force target, many known exploits
5900VNCOften deployed with weak or no authentication
6379RedisDefault install has zero authentication
9200ElasticsearchDefault allows unauthenticated read/write of all data
27017MongoDBDefault install has no auth — infamous for data leaks
3306/5432/1433MySQL/PG/MSSQLDatabases shouldn't be directly network-accessible
6443K8s APIFull cluster administration if reachable without auth
▸ vs nmap — honest comparison
Featurezigscannernmap
TCP Connect scan
TCP SYN scan✓ simplified✓ full
UDP scan✓ basic✓ comprehensive
IPv6✗ planned
CIDR ranges✗ planned
NSE scripting engine✗ by design✓ thousands of scripts
OS fingerprinting✓ heuristic✓ ML-based, accurate
Version detection✓ banner parsing✓ signature database
Zero external deps✗ libpcap, OpenSSL…
Single static binary
Cross-compilation (trivial)
Readable codebase✓ ~1500 lines✗ 100k+ lines C
JSON output native
Years of development127
Use nmap when you need NSE scripts, IPv6, CIDR, XML output, or high-accuracy OS detection. Use zigscanner when you want a zero-dep binary you can drop on any machine, read the source of, and modify freely.
▸ Real-world examples
# Basic scan — ports 1-1024 $ zigscanner 192.168.1.1
# Full port scan with service + OS detection $ zigscanner -p all -sV -O 192.168.1.1
# Fast scan — 500 threads, 300ms timeout $ zigscanner -p 1-65535 -t 500 --timeout 300 192.168.1.1
# Save results as JSON $ zigscanner -p top -sV -O -o results.json 192.168.1.1
# SYN stealth scan (root required) $ sudo zigscanner -sS -p 1-1024 192.168.1.1
# Check if Docker API is exposed (it shouldn't be) $ zigscanner -p 2375,2376 10.0.0.50
# WAN target — increase timeout, lower threads $ zigscanner -p top -sV --timeout 5000 -t 50 203.0.113.10
# Verbose: show raw banners $ zigscanner -v -sV -p top 10.0.0.1
▸ Design notes

The thread model uses an atomic work-stealing counter. Rather than pre-assigning port ranges to threads, each worker calls fetchAdd on a shared atomic u32 to claim the next port. Threads that finish fast keep claiming work; threads blocked on a timeout don't starve other threads. No deadlock possible — the only mutex is on the results list, held only when appending an open port.

Memory management follows Zig's ownership convention: whoever allocates, frees. All allocations go through a GeneralPurposeAllocator which reports leaks in debug builds. Banner strings are heap-allocated (size unknown at compile time). Service names are string literals (static lifetime, no allocation).

The terminal panel in the output is not a PTY. OS fingerprinting is explicitly low-to-medium confidence — containers, Samba on Linux, and custom banners routinely fool heuristics. Treat OS guesses as starting hypotheses, not conclusions.