A single Docker image bundling packet capture, packet crafting/manipulation, MITM proxying, and general network diagnostics — for network engineers, software engineers, and security engineers/testers troubleshooting or exercising network behavior.
Base: Chainguard Wolfi — minimal, glibc-based, packages built/signed/rebuilt by Chainguard with SBOMs and near-zero known CVEs at any point in time.
docker pull ownjooorg/packet-benchPublished automatically by .github/workflows/docker-publish.yml
on every push to main (tag latest) and on v* tags (semver tags). Requires the
DOCKERHUB_USERNAME/DOCKERHUB_TOKEN repo secrets to be configured before the workflow can push.
Images are cosign-signed and ship an attached SBOM, matching the smb-mock publishing pattern.
docker build -t packet-bench .Tool versions for the from-source builds are pinned build args (see "Supply chain" below):
docker build -t packet-bench \
--build-arg NMAP_VERSION=7.99 \
--build-arg MASSCAN_VERSION=1.3.2 \
--build-arg BETTERCAP_VERSION=v2.41.7 \
.# General use — most tools (tcpdump, mitmproxy, dig, iperf3, curl, etc.) work as-is
docker run --rm -it packet-bench
# Packet capture / crafting that needs raw sockets (scapy, impacket, arbitrary
# nmap scan types, bettercap) — grant the capabilities at run time:
docker run --rm -it --cap-add=NET_RAW --cap-add=NET_ADMIN packet-bench
# L2 work (ARP, bridging, bettercap's wifi/ble modules) generally wants the host's
# network namespace too:
docker run --rm -it --cap-add=NET_RAW --cap-add=NET_ADMIN --network host packet-bench| Category | Tools |
|---|---|
| Capture/analysis | tcpdump, tshark (+ editcap/capinfos/mergecap), ngrep |
| MITM/proxy | mitmproxy / mitmdump |
| DNS | dig/nslookup/host (bind-tools), drill |
| TLS | openssl |
| Diagnostics | ip/ss (iproute2), mtr, ping/tracepath/arping (iputils), nc (netcat-openbsd), socat, curl, httpie, iperf3, ethtool, nftables |
| SMB/Kerberos/AD | kinit/klist/kdestroy (krb5), smbclient/net (samba-client, samba-common-tools), mount.cifs (cifs-utils) |
| SSH | ssh, scp, sftp, ssh-keygen (openssh-client, openssh-keygen) |
| SNMP | snmpget/snmpwalk/snmpbulkwalk/snmptrap/snmptranslate (net-snmp-tools) |
| SMTP | swaks |
| LDAP | ldapsearch/ldapmodify/ldapwhoami (openldap-2.6-clients) |
| Databases (CLI) | psql (postgresql-18-client), valkey-cli (Redis-protocol compatible), tsql (freetds) |
| Misc | whois, rsync |
| Console browsers | lynx, w3m |
| Category | Packages |
|---|---|
| Packet crafting/protocol | scapy, impacket |
| TLS auditing | sslyze |
| SMB/Kerberos/NTLM/AD | smbprotocol (import as smbclient), pyspnego (import as spnego), gssapi, ldap3, requests-ntlm, requests-kerberos, pywinrm (import as winrm), msldap, minikerberos |
| HTTP/API clients | httpx[http2], requests, websocket-client, PyJWT[crypto] (import as jwt), zeep (SOAP) |
| AWS | boto3 |
| SSH scripting | paramiko |
| Config/data | pyyaml, python-dotenv, dnspython, pydantic |
| RPC/messaging | grpcio, redis, pika (AMQP), paho-mqtt |
| Databases | sqlalchemy, psycopg[binary] (Postgres), pymysql (MySQL/MariaDB), pymssql (SQL Server, via FreeTDS), oracledb (Oracle, thin mode — no Instant Client needed), pymongo, tinydb |
| Interactive/dev quality-of-life | ipython, rich |
testssl.sh
nmap (+ ncat, nping), masscan, bettercap
- FTP client — not packaged in Wolfi;
curlcoversftp://get/put for common cases. - Telnet client — not packaged;
ncat host portis a strict superset for troubleshooting use. - NTP query — only
chronyexists (a full clock-steering daemon, not a one-shot query tool like the oldntpdate); not included. - MySQL/MariaDB CLI — only the connector library is packaged, no standalone
mysqlclient binary;pymysqlcovers scriptable access.
The whole point of Wolfi here is Chainguard's build/signing/SBOM pipeline. Everything in the
"native apk" table above gets that for free. nmap, masscan, and bettercap aren't packaged
in Wolfi, so they're compiled from source in a builder stage and copied into the final image —
for those three specifically, we are the build pipeline, not Chainguard. That's a real
downgrade in provenance for just those binaries, accepted here because nmap in particular isn't
optional for this toolbox.
Mitigations in place:
- All three are pinned to a specific release tag/version (
NMAP_VERSION,MASSCAN_VERSION,BETTERCAP_VERSIONbuild args) — neverlatest/main— so builds are reproducible and upgrades are a deliberate, reviewable version bump. - The builder stage itself is still Wolfi, so the compiler toolchain has the same provenance guarantees; only the final compiled artifact loses it.
- Consider running
trivy image packet-benchperiodically to catch CVEs in these three that Chainguard's auto-rebuild would otherwise have caught for you.
Deliberately left out: hping3, dsniff, netdiscover, tcpreplay, bittwist, arp-scan —
all old C codebases that are painful/fragile to build on a modern glibc toolchain, and whose use
cases are mostly covered already: scapy can construct anything hping3 can, and bettercap
covers ARP-spoofing/MITM recon that arp-scan/dsniff/netdiscover would otherwise provide.
Ping if you actually need one of these and we'll add it.
Non-root by default (netutils user). Rather than requiring --privileged, the single-purpose
compiled binaries (nmap, nping, masscan, bettercap, tcpdump) have cap_net_raw/
cap_net_admin set as file capabilities at build time. That still requires the container
itself to be granted those capabilities at docker run time — Docker's default capability
bounding set excludes NET_ADMIN entirely, so you need --cap-add=NET_RAW --cap-add=NET_ADMIN
regardless (see "Run" above). What the file-capability setup buys you is that the non-root
netutils user can actually use those capabilities once granted — without it, only root could
pick them up, and this image deliberately doesn't run as root. tshark uses Wolfi's own
tshark-4.4-privileged variant, which handles its own dumpcap capability grant.
python3.14 itself is deliberately not given those capabilities — that would hand raw-socket
power to any script run in the interpreter, not just scapy/impacket. For those, pass
--cap-add=NET_RAW --cap-add=NET_ADMIN at docker run time (see above).
setuid/setgid bits are stripped from the entire final image as defense-in-depth (same pattern
used in the smb-mock project).