ZMap#

Internet-scale port scanner. ZMap sends a stateless single-packet probe per target, processes responses asynchronously, and can sweep the whole IPv4 routable space for a single port in roughly five minutes on a 10 Gbps NIC. Different model from Nmap: ZMap finds who is listening, then a tool like Nmap or ZGrab2 takes that hit-list and asks what is running.

Setup#

Install on Debian-family, confirm the version, and grant the raw-socket capability so ZMap can craft packets without sudo. ZMap relies on the kernel’s routing table; --gateway-mac and --source-ip overrides come up when sending from a host whose egress is non-trivial.

Command

Action

sudo apt install zmap

install on Debian / Ubuntu

zmap --version

confirm version

sudo setcap cap_net_raw=eip "$(command -v zmap)"

grant raw-socket capability for non-root use

zmap --list-probe-modules

print available probe modules

zmap --list-output-modules

print available output modules

zmap --list-output-fields -M tcp_synscan

list fields a given probe module can emit

Single-Port Scans#

The default operation. Pick a port with -p, a target range with --allowlist-file or positional CIDRs, and either let ZMap discover egress automatically or pin source IP / gateway MAC.

Command

Action

zmap -p 443 10.0.0.0/24

scan a /24 on TCP/443

zmap -p 80 -o results.csv 10.0.0.0/16

scan a /16, write CSV

zmap -p 22 --output-file=ssh.csv 0.0.0.0/0

whole IPv4 routable (use a blocklist!)

zmap -p 53 -M udp 0.0.0.0/0

UDP scan

zmap -p 443 -w targets.txt

read CIDRs from a file

zmap -p 443 -b /etc/zmap/blacklist.conf 0.0.0.0/0

apply the system blocklist

zmap -p 443 --source-ip=10.0.0.10 10.0.0.0/24

pin the source IP

zmap -p 443 -i eth0 10.0.0.0/24

pin the egress interface

Output and Fields#

ZMap writes one row per probe response by default. -O csv gives header rows; -O json is the structured form. The fields ZMap emits are configurable per probe module; useful ones include saddr, daddr, sport, dport, classification, and timestamp_str.

Command

Action

zmap -p 443 -O csv 10.0.0.0/24

CSV output module

zmap -p 443 -O json 10.0.0.0/24

JSON-lines output

zmap -p 443 -f saddr,sport,seq,ack 10.0.0.0/24

select fields

zmap -p 443 -u status_updates.csv 10.0.0.0/24

emit periodic progress to a CSV

zmap -p 443 --metadata-file=meta.json 10.0.0.0/24

dump scan metadata after completion

zmap -p 443 --log-file=zmap.log 10.0.0.0/24

write the log to disk

zmap -p 443 -q 10.0.0.0/24

quiet mode (suppress per-probe lines)

zmap -p 443 -v 5 10.0.0.0/24

verbose level (0-5)

Rate and Sampling#

Internet-scale scans require rate control: -r (packets per second) or -B (bandwidth). Sampling lets you scan only a random subset of the address space for surveys.

Command

Action

zmap -p 443 -r 10000 10.0.0.0/24

cap at 10 K packets / second

zmap -p 443 -B 1G 10.0.0.0/24

cap at 1 Gbps

zmap -p 443 --max-targets=1000 10.0.0.0/24

stop after N targets

zmap -p 443 --max-runtime=600 10.0.0.0/24

stop after N seconds

zmap -p 443 --max-results=100 10.0.0.0/24

stop after N positive responses

zmap -p 443 --shards=10 --shard=1 0.0.0.0/0

one of ten shards (parallel hosts)

zmap -p 443 --seed=12345 0.0.0.0/0

deterministic address order

zmap -p 443 --probes=2 10.0.0.0/24

send N probes per target

zmap -p 443 --cooldown-time=10 10.0.0.0/24

extra seconds to wait for stragglers

Probe Modules#

ZMap ships with several probe modules besides the default TCP SYN. icmp_echoscan is the ICMP ping sweep; udp carries an arbitrary payload (use with care); ntp_initiate, dns, and upnp are application-specific.

Command

Action

zmap -p 80 -M tcp_synscan 0.0.0.0/0

default TCP SYN scan (named explicitly)

zmap -M icmp_echoscan 10.0.0.0/16

ICMP echo (ping) sweep

zmap -p 53 -M udp --probe-args=file:/etc/zmap/dns.pkt 0.0.0.0/0

UDP probe with payload from file

zmap -p 123 -M ntp_initiate 0.0.0.0/0

NTP monlist / version

zmap -p 1900 -M upnp 0.0.0.0/0

UPnP discovery

zmap -p 53 -M dns --probe-args=raw:<hex> 0.0.0.0/0

DNS probe with raw hex payload

zmap -M bacnet 0.0.0.0/0

BACnet (ICS) discovery

Safety and Blocklists#

ZMap defaults to send-anywhere. For real Internet-wide scans respect /etc/zmap/blacklist.conf, register a reverse-DNS record for the source IP that explains the activity, and watch for abuse complaints. Many ASes block scanners outright.

Command

Action

cat /etc/zmap/blacklist.conf

read the bundled blocklist (RFC1918, multicast, etc.)

zmap -p 443 -b mylist.conf 0.0.0.0/0

apply a custom blocklist

zmap -p 443 --allowlist-file=allow.conf 0.0.0.0/0

restrict to listed CIDRs only

zmap -p 443 --dryrun 0.0.0.0/0

print packets without sending

zmap -p 443 --notes="ISP-X research scan" 0.0.0.0/0

annotate scan metadata for audit

host <source-ip>

confirm rDNS points at a research / abuse contact

ZGrab2 Pairing#

The standard ZMap workflow: ZMap finds open ports, ZGrab2 grabs the application banner / certificate / response. zgrab2 reads ZMap CSV / JSON, queues TLS handshakes, HTTP GETs, SSH banners, and writes one structured record per host.

Command

Action

zmap -p 443 -o tls.csv 0.0.0.0/0

find TLS-open hosts

zgrab2 tls --port 443 --input-file=tls.csv -o tls.json

grab TLS handshake + certificate

zgrab2 http --port 80 --input-file=http.csv -o http.json

grab HTTP response

zgrab2 ssh --port 22 --input-file=ssh.csv -o ssh.json

grab SSH banner + key exchange

zgrab2 multiple --config-file=zgrab.ini

chain multiple modules per host

ztee parsed.csv < raw.csv | zgrab2 tls

pipe a hit-list directly into zgrab2

jq -r '.data.tls.result.handshake_log.server_certificates.certificate.parsed.subject_dn' tls.json

extract a single field from results

Companion Tools#

The ZMap project ships several helpers that consume scan output.

Command

Action

ztee

tee tool that splits ZMap stdout into a file + a downstream pipe

zblocklist

filter a target list against a blocklist

ziterate

generate the IP iteration order ZMap would use (no scan)

zgrab2

application-layer banner / handshake grabber (see above)

zlint

validate ZGrab2 / Censys TLS observations against the CA / Browser Forum rules