Open-source project
cisco/mercury avatar
cisco/mercury

Mercury fingerprints TLS, SSH and HTTP traffic from packet metadata

Mercury: network metadata capture and analysis

521 stars87 forksC++NOASSERTION

At a glance

What is it?
Mercury is a Cisco C++ tool that reads network packets, extracts protocol metadata, writes it as JSON and optionally emits fingerprint strings for TLS, DTLS, SSH, HTTP and TCP, with optional process identification. The standalone binary captures via AF_PACKET TPACKETv3 on Linux and libpcap on macOS, and the README asks you to treat it as beta software.
Who is it for?
Adopt Mercury if you need passive protocol identification from packet metadata rather than payload inspection, and if you have the Linux kernel and hardware to run it at line rate. Skip it if you need deep payload analysis or application-layer logging, since Mercury deliberately works from metadata.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 14 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two programs: the C++ binary and the Python port

The package contains two programs for fingerprinting network traffic and capturing and analyzing packet metadata. The first is mercury, a standalone application for Linux and macOS, and the second is pmercury, a portable Python application documented separately. The split is about capture, not about analysis. On Linux the standalone binary uses the kernel's AF_PACKET TPACKETv3 capture path, and on macOS it uses libpcap for interface capture. The Python version exists for portability, and the README notes that pmercury and its associated tools need Python 3.9 or later along with several pip packages. There is also a batch_gcd tool that needs the GNU Multiple Precision Arithmetic Library. The runtime dependency list for the standalone binary is short: zlib and OpenSSL, and a Dockerfile is provided that gives a working example on Debian. The primary language is C++, and the repository is not archived with the last push on 2026-10-09.

What it produces: metadata, fingerprints and optional process identification

Mercury reads network packets, identifies metadata of interest and writes it out in JSON format, and alternatively it can write out the packets that contain the metadata in the PCAP file format. The fingerprint strings are the part that matters for most users. Mercury produces fingerprints for TLS, DTLS, SSH, HTTP, TCP and other protocols, and these are formed by carefully selecting and normalizing metadata extracted from packets, with the selection documented in the repository under doc/npf.md. The fingerprint strings are reported in the fingerprint object of the JSON output. On top of that, mercury can optionally perform process identification based on those fingerprints and the destination context, and those results are reported in the analysis object. The distinction between the two output objects is useful: one is a description of what the traffic looks like, the other is a guess about what the traffic is.

Performance model: zero-copy ring buffers and worker threads

The README states that mercury can scale up to high data rates, with 40Gbps on server-class hardware, and that it uses zero-copy ring buffers to acquire packets while packets are processed by independent worker threads. Both of the two knobs that matter operationally are configurable: the amount of memory consumed by the ring buffers, and the number of worker threads. That configurability is what makes it easy to scale up, and the README adds the obvious caution, be wary of using too much memory. The TPACKETv3 path requires Linux kernels newer than 3.2, which sets a floor on the deployment target that matters for anyone considering containerised or older hosts. The design is a straightforward producer and consumer split, and the two numbers you tune are exactly the two that determine whether you drop packets.

Building on Linux

The build itself has minimal dependencies beyond a g++ or llvm environment, but the automated tests and ancillary programs need more, and the README gives a Debian and Ubuntu example.

bash
sudo apt install g++ jq git zlib1g-dev tcpreplay valgrind python3-pip libssl-dev clang
sudo apt install libxsimd-dev   # optional: enables SIMD-accelerated classification

The build is a configure step followed by make.

bash
./configure
make

The xsimd package is optional and enables SIMD-accelerated classification, which is the package to reach for if the classification stage is your bottleneck. The Python build of the Cython modules needs its own set of packages, installed with pip after an upgrade of pip itself. The top-level make is also the target that builds the programs and python modules needed to test the package. The Makefile itself is non-recursive, with an include-per-module layout under mk/ covering the Cython modules, the documentation, libmerc, mercury itself, the signature tables, the tests and the tools, and the install rules come last because they depend on the certificate tools.

Installing, and what the install actually creates

After building you review mercury.cfg in the root directory, then install.

bash
./configure
make

sudo make install MERCURY_CFG=mercury.cfg

That target installs mercury, creates and starts a systemd service, and it must be run as root because it creates the output user named mercury, which owns the output file directory. If you do not want the systemd service installed, there is an install-nosystemd target instead. The default file and directory locations are /usr/local/bin/mercury for the executable, /usr/local/share/mercury for the resource files, /usr/local/var/mercury for the output files, /etc/mercury/mercury.cfg for the configuration file, and /etc/systemd/system/mercury.service for the unit file. The deb and rpm packages install the unit into the library directories instead, and a unit in /etc/systemd/system overrides both, so systemctl cat mercury shows which one is in effect. If you want everything under your home directory, configure with --prefix, and if you do not want the mercury user created at all, the install-nonroot target installs nothing into /etc and creates no systemd unit.

Running as a service and reading its logs

The easiest way to run mercury in capture mode is through systemd, since the operating system starts the unit after each boot and halts it on shutdown.

bash
systemctl status mercury

The output should contain active (running). The log output, mostly on stderr, is read with the journal.

bash
sudo journalctl -u mercury

On systems where journald entries are forwarded or imported by syslog or rsyslog, which the README notes is the default on RHEL and Alma, those messages also appear in /var/log/messages. To bypass the journal entirely and write the streams straight to a file, you edit the unit and set the output options.

bash
[Service]
StandardOutput=append:/var/log/mercury.log
StandardError=inherit

Then you restart the service. The README is careful to point out that Mercury's JSON output files are written under the working directory, /usr/local/var/mercury by default, and are not affected by those settings, so a log redirect does not change where your analysis output lands. Uninstalling is a make uninstall run as root.

Capture mode, configuration and the ethics of the output

The default mercury.cfg enables capture mode with capture=auto and auto-detects a network interface on Linux at runtime, and setting capture to a specific interface forces it instead. The README's table of contents includes an Ethics section, and that is not a formality for a tool that reads every packet on a segment. The output records which hosts are talking to which destinations, and the fingerprint strings identify the software behind those flows, which makes the JSON output a record of your network's behaviour at a level that most organisations treat as sensitive. The macOS path deserves a separate note: building on Apple Silicon is currently experimental, standalone mercury can read pcap files and capture from an interface using libpcap, and the current macOS live-capture backend supports a single capture thread, which rules out the multi-worker throughput that the Linux path is designed around. The README also asks you to consider the software as a beta while noting it is used in some production applications.

Editorial conclusion

Adopt Mercury if you need passive protocol identification from packet metadata rather than payload inspection, and if you have the Linux kernel and hardware to run it at line rate. Skip it if you need deep payload analysis or application-layer logging, since Mercury deliberately works from metadata. Before you deploy it, read the ethics section of the README and decide how long you will keep the JSON output, because the output records what every host on the segment is talking to.

Frequently asked questions

What is Mercury and what does it output?

Mercury is a network metadata capture and analysis tool. It reads packets, identifies metadata of interest and writes it as JSON, and it can alternatively write out the packets containing that metadata in PCAP format. It produces fingerprint strings for TLS, DTLS, SSH, HTTP, TCP and other protocols, reported in the fingerprint object, with optional process identification in the analysis object.

How does Mercury capture packets?

On Linux the standalone binary uses the kernel's AF_PACKET TPACKETv3 capture path, which needs a kernel newer than 3.2, and on macOS it uses libpcap, where the live-capture backend supports a single capture thread. Packets are acquired through zero-copy ring buffers and processed by independent worker threads, both configurable.

What does installing Mercury create on the system?

The binary at /usr/local/bin/mercury, resource files in /usr/local/share/mercury, output files in /usr/local/var/mercury, the configuration at /etc/mercury/mercury.cfg and a systemd unit at /etc/systemd/system/mercury.service, plus a system user named mercury that owns the output directory. Use make install-nonroot to skip the user, the /etc files and the unit.

What are the runtime dependencies of the Mercury binary?

Only zlib and OpenSSL. The ancillary tools need more: pmercury and its tools require Python 3.9 or later plus several pip packages, and batch_gcd requires the GNU Multiple Precision Arithmetic Library. A Dockerfile on Debian is included as a working example.

Official sources

  1. cisco/mercury on GitHub
  2. Issues
  3. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cisco-mercury.svg)](https://hysenlabs.com/projects/cisco-mercury)

Was this useful?