$ show FoxIO-LLC/ja4
JA4+ is a multi-protocol passive network fingerprinting suite that generates deterministic fingerprints for TLS, HTTP, SSH, TCP, DHCP, X.509, and latency characteristics. The repository provides four independent implementations: a Python reference library, a Rust CLI tool and library, a Wireshark post-dissector plugin, and a Zeek plugin (C++ BiF + Zeek scripts). All implementations share the same fingerprinting algorithm, test pcap files, and expected output snapshots, enabling cross-validation. The system processes raw packet captures (PCAP/PCAPNG) via tshark or direct packet parsing, extracts protocol handshake parameters (cipher suites, extensions, HTTP headers, SSH key exchange algorithms, TCP flags, DHCP options), normalizes them (GREASE removal, sorting, hashing), and outputs structured JA4+ fingerprints. External dependencies include tshark (for PCAP parsing in Python and Rust), Wireshark/Zeek APIs for plugins, and the ja4db.com database for fingerprint-to-software mapping. The architecture is a collection of standalone tools rather than a unified service, with each implementation optimized for its target environment (CLI, packet analyzer, network monitor). While primarily an application toolkit, the repository also includes research-oriented assets such as a fingerprint-to-software mapping CSV, technical documentation with diagrams, and a large corpus of real-world test traffic, making it a hybrid of production tooling and security research.
The LLM identified 4 files worth highlighting for reuse:
Core Rust library that implements JA4, JA4S, JA4H, JA4T, JA4L, JA4SSH, and JA4X fingerprint generation. It provides a clean public API (e.g., `ja4()`, `ja4s()`, `ja4h()`) that accepts parsed protocol data and returns fingerprint strings. The library is self-contained, with internal modules for TLS, HTTP, SSH, TCP, and latency handling. It demonstrates strong Rust practices: error handling with custom error types, configuration via config.toml, and snapshot-based testing with insta. This crate can be extracted and reused in any Rust project needing network fingerprinting, with minimal adaptation.
A Wireshark post-dissector plugin that registers a 'JA4' protocol and adds JA4+ fingerprint fields to packet details and columns. It implements tap listeners to collect fingerprints across packets and provides a display function for aggregated results. The code is well-structured with clear separation of registration, dissection, and tap logic. It demonstrates advanced Wireshark plugin development patterns (field registration, tap integration, conditional compilation for different Wireshark versions). This file can serve as a reference for building custom Wireshark dissectors and is reusable as a template for other protocol fingerprinting plugins.
A Zeek script module providing reusable utility functions for fingerprint generation: vector sorting, SHA-256 truncation, GREASE filtering, and string formatting. It is imported by all JA4+ fingerprint modules (ja4, ja4s, ja4h, ja4ssh, ja4t, ja4l, ja4d) to ensure consistent algorithm implementation. The functions are parameterized and avoid global state, making them suitable for extraction into other Zeek packages. This demonstrates clean modular design in Zeek's event-driven scripting language.
Python module containing shared helper functions for TLS fingerprinting: GREASE detection and removal, cipher suite and extension normalization, SHA-256 hashing, and a caching mechanism for parsed TLS data. It is used by ja4.py, ja4h.py, ja4ssh.py, and ja4x.py. The functions are pure and stateless, with clear docstrings and type hints. This module can be extracted and reused in any Python project requiring TLS handshake analysis, demonstrating good Python engineering practices.