← All posts
Capabilities · · 7 min read

Meet mach, voyage, and pulse: the Rust recon engines

Crossfyre ships three in-house recon engines written in Rust: mach for content discovery, voyage for subdomain enumeration, and pulse for port and host scanning. Here is what each one does, why we built them in Rust, and how they run standalone or orchestrated across a fleet.

Crossfyre is a control plane for distributed recon, but the actual scanning is done by three engines we wrote ourselves: mach, voyage, and pulse. They are open source, each is a single static Rust binary, and each persists its own scan state so a run can be stopped and resumed. You can drive them by hand on one box with no account at all, or let the platform orchestrate them across your fleet.

This post is a tour of all three: what each does, a realistic standalone command for each, and how the orchestration layer fans them out across nodes when you are ready for that.

Why Rust, and why one binary each

Recon is throughput-bound and runs in unfriendly conditions. The engines are async (Tokio) so a single process can hold thousands of in-flight probes without a thread per request, and Rust keeps that concurrency memory-safe instead of a heap of segfaults at 2am. Three properties fall out of the design and matter day to day:

  • Single static binary. No runtime, no interpreter, no dependency tree to reproduce on a disposable VPS. You drop the binary on a host and it runs.
  • Resumable state. Each engine writes progress to a local Postgres (managed by the CLI). Kill the scan, reboot the box, come back tomorrow: it picks up where it stopped rather than re-walking the wordlist from zero.
  • A live TUI. Run interactively and you get a terminal UI streaming results as they land, with the same engine binary that runs headless under the daemon.
Note

Each engine runs in two modes from one binary: a foreground client with the live TUI for hands-on work, and a background daemon (--daemon) that the node talks to over a local socket. The orchestration layer drives the daemon mode.

mach: HTTP content discovery and fuzzing

mach is the content-discovery engine. You give it a URL with a fuzz marker and a wordlist, and it discovers paths, parameters, and virtual hosts by substituting each word into the marker position. It tracks status codes, follows (or pins) redirects, and lets you tune concurrency and per-task interval. Because it is stateful, a half-finished 200k-word run resumes instead of restarting.

bash
# Standalone path discovery against an asset you own. # ::FUZZ:: marks where each wordlist entry is substituted. mach scan \ --url "https://app.example.com/::FUZZ::" \ --wordlist-path ./wordlists/raft-medium-dirs.txt \ --tasks 40 \ --interval 25 \ --success-status-codes 200,204,301,302,401,403

The same marker works for parameter and vhost discovery: put ::FUZZ:: in a query parameter or in a Host: header. Add --fresh-start to ignore saved state and begin a clean run, or leave it off to resume. For more on running these at fleet scale without tripping rate limits, see content discovery at scale.

voyage: subdomain enumeration

voyage maps the subdomain surface of a domain two ways at once. Passive enumeration pulls names from OSINT sources (certificate transparency and similar) without touching the target. Active enumeration brute-forces names from a wordlist against your resolvers and probes the candidates over HTTP/HTTPS. You almost always want both, because each finds names the other misses.

bash
# Passive + active enumeration of a domain in your scope. voyage scan \ --domain example.com \ --wordlist-path ./wordlists/subdomains-top20k.txt \ --tasks 8 \ --http-ports 80,8080 \ --https-ports 443,8443

You can disable either half (--disable-passive-enum or --disable-active-enum) or exclude specific passive sources. The full methodology, including wildcard handling and validation, is in subdomain enumeration that does not miss.

pulse: port and host scanning

pulse is the network engine. It takes hosts or CIDR ranges, scans ports with either a SYN (half-open) or full connect technique, and optionally runs service and version detection on what it finds open. Concurrency, per-probe timeout, and an inter-probe delay are all tunable so you can dial the scan from aggressive to quiet.

bash
# Connect scan of the top 1000 ports across a range you own, # with service detection on open ports. pulse scan \ --target 10.0.0.0/24 \ --ports top-1000 \ --technique connect \ --tasks 200 \ --timeout 1500 \ --service-detection
Heads up

SYN scanning needs raw-socket privileges, so it runs as root. Connect scanning does not require privileges but is louder and slower. Only point pulse at ranges you own or are explicitly authorized to test.

Standalone versus orchestrated

Everything above runs on one machine with no Crossfyre account. That is deliberate: the engines are open source and useful on their own. The platform adds the layer above them.

When you enrol a host as a node and launch a workflow, the control plane decomposes the job into discrete operations and publishes them onto a durable NATS JetStream queue. Each node pulls operations, runs the relevant engine daemon against them, and streams results back. A 200k-word mach run or a /16 pulse sweep becomes hundreds of operations spread across the fleet instead of one long process pinned to one box.

  • Work is split across nodes, so wall-clock time drops with every node you add.
  • Because operations are acknowledged, a node that dies mid-run has its in-flight work redelivered elsewhere. Nothing already finished is rescanned. See how scans survive a crashed node.
  • Results from all three engines land in one Findings explorer, filterable by severity, method, and host, exportable to CSV, JSON, or Markdown.
  • Each node carries its own scoped credentials and can route egress through proxy chains and a VPN-isolated network namespace.

Same engines, same binaries. The difference between a one-box recon session and a coordinated fleet sweep is whether the platform is fanning the operations out for you. Vulnerability scanning and a visual Mission Planner to chain these engines into multi-stage engagements are on the roadmap.

Install the toolchain, run mach, voyage, and pulse standalone, then enrol a node and watch them fan out.

Start free
#engines#mach#voyage#pulse