ZGrab2: The Protocol Handshake Scanner Built for Internet-Scale Research
Hook
Most network scanners tell you if a port is open. ZGrab2 records the entire conversation—every TLS negotiation message, every HTTP header, every SSH key exchange—then hands you a transcript for forensic analysis.
Context
Network reconnaissance traditionally happens in two phases: find responsive hosts, then investigate what services they’re running. Tools like ZMap revolutionized the first phase, scanning the entire IPv4 address space in under an hour. But Layer 4 reachability is just the beginning. Security researchers, infrastructure operators, and measurement scientists need to understand what’s actually happening at the application layer—not just that port 443 responds, but which TLS versions a server offers, what certificate chains it presents, and how it handles edge cases in the protocol handshake.
This is where most scanners fall short. Traditional tools like nmap excel at service detection but weren’t architected for Internet-wide surveys that might target millions of hosts. They focus on identifying what’s running rather than capturing detailed protocol exchanges. Packet capture tools like Wireshark provide the transcript depth but require manual operation and don’t scale. ZGrab2 emerged from the ZMap Project to bridge this gap: a scanner designed from the ground up to perform deep application-layer handshakes at scale, capturing complete protocol transcripts as structured JSON for offline analysis. It’s the natural complement to ZMap’s Layer 4 reconnaissance, answering the question ‘Now that we know the host is listening, what exactly is it saying?‘
Technical Insight
ZGrab2’s architecture revolves around a modular scanner framework where each protocol is implemented as an independent module sharing a common interface. Every module must implement three core interfaces: Scanner (the actual scanning logic), ScanModule (module registration and initialization), and ScanFlags (command-line option definition). This design ensures consistency while allowing protocol-specific customization.
The framework reads targets from stdin in CSV format, supporting flexible input specifications. You can provide bare IP addresses, domains (triggering automatic DNS resolution), CIDR blocks (automatically expanded to individual targets), or combinations with optional tags and per-target port overrides. Here’s how input flows through a typical scan:
# Simple domain scan with NTP module
echo "pool.ntp.org" | zgrab2 ntp
# Output shows the complete handshake transcript
{
"ip":"23.143.196.199",
"domain":"pool.ntp.org",
"data":{
"ntp":{
"status":"success",
"protocol":"ntp",
"port":123,
"result":{
"version":3,
"time":"2025-11-07T00:58:45.13740072Z"
},
"timestamp":"2025-11-06T16:58:45-08:00"
}
}
}
The structured JSON output is ZGrab2’s killer feature. Unlike traditional scanners that summarize results, ZGrab2 captures the entire protocol exchange—every message, every header, every certificate in the chain. For TLS scans, you don’t just get “TLS 1.3 supported”; you get detailed handshake information including certificate chain data, supported cipher suites, and extension details. This transcript approach enables researchers to perform deep offline analysis, correlating protocol behaviors across millions of hosts without rescanning.
ZGrab2 supports 31 protocols spanning web services (HTTP, HTTPS/TLS), email (SMTP, IMAP, POP3), databases (MySQL, PostgreSQL, MongoDB, MSSQL, Oracle, Redis), industrial control systems (Modbus, BACnet, DNP3, Siemens, Fox), and specialized protocols (MQTT, Memcached, SMB, SSH, AMQP, JARM, ManageSieve, IPP, NTP, PPTP, SOCKS5, Telnet, FTP). The banner module provides a fallback for unknown protocols, capturing raw responses to custom payloads.
For complex scanning workflows, ZGrab2’s multiple module configuration system uses INI files to coordinate multi-protocol scans. You can trigger different protocol checks based on input tags, enabling sophisticated campaigns like “scan all hosts with the ‘scada’ tag using Modbus, and all hosts with ‘database’ tag using MySQL and PostgreSQL modules.” This conditional triggering optimizes resource usage in large-scale surveys where not every target needs every protocol check.
# Run multiple modules with a configuration file
docker run --rm -i -v /path/to/config.ini:/config.ini \
ghcr.io/zmap/zgrab2 multiple -c /config.ini
The framework explicitly prioritizes ethical scanning. Modules abort handshakes before authentication attempts, never brute-force credentials, and only collect publicly available protocol metadata. This design philosophy is baked into the module interface—there’s no mechanism for authentication, ensuring research remains non-invasive by default. It’s reconnaissance, not penetration testing.
Built in Go, ZGrab2 appears to leverage Go’s concurrency features for parallel scanning while maintaining reasonable resource usage. The module interface design makes extension straightforward for developers familiar with the codebase, though documentation for writing new modules remains incomplete (the README literally cuts off mid-sentence in the integration tests section). Each module handles its own protocol handshake logic, managing connection setup, data exchange, error recovery, and result serialization independently.
Gotcha
ZGrab2’s power comes with significant responsibility. The tool itself doesn’t enforce rate limiting or provide safeguards against overwhelming target infrastructure—that’s entirely up to the user. Internet-wide scans require careful planning around bandwidth, source IP reputation, and ethical considerations. You need to set up proper scanning infrastructure with abuse contact information, respect blocklists, and understand the legal implications of automated scanning in different jurisdictions. ZGrab2 is explicitly a research tool, not a production security scanner.
Module quality may vary. Core modules like HTTP, TLS, and SSH appear well-tested, but lesser-used modules may have varying levels of protocol coverage and testing. If you’re scanning industrial control protocols like BACnet or Siemens S7, expect to read the module source code to understand exactly what’s being tested. The documentation for individual modules is sparse—most detail lives in the command-line help output (zgrab2 [module] -h) rather than comprehensive guides.
The framework’s documentation also has rough edges. The README’s section on integration tests ends abruptly mid-sentence, and guidance for writing new modules is minimal. You’ll need Go proficiency to extend ZGrab2, and debugging failed scans often means diving into protocol-specific module code. The structured JSON output, while powerful, can become unwieldy when processing results from millions of targets—you’ll need to build your own analysis pipeline using tools like jq, database imports, or custom parsers. ZGrab2 captures the data brilliantly but provides no built-in analysis or reporting beyond raw JSON streams.
Verdict
Use ZGrab2 if you’re conducting Internet measurement research, security surveys requiring protocol-level detail, or asset discovery where you need complete handshake transcripts rather than simple reachability checks. It’s the right tool when scanning thousands to millions of hosts across diverse protocols and you plan to analyze behavioral patterns offline. The modular architecture and structured output make it ideal for academic research, infrastructure mapping, and security posture analysis at scale. Skip it for routine penetration testing (use specialized tools designed for authenticated exploitation), simple port scanning (nmap or masscan are faster and simpler), or when you need interactive protocol analysis (Wireshark provides better real-time inspection). Also avoid ZGrab2 if you lack the infrastructure and expertise to conduct ethical large-scale scanning—it’s a power tool that demands responsible use and proper operational setup.