Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CLI Tool

The MRPF CLI (mrpf) is a command-line interface to all MRPF scanners. It provides subcommands for each scanner type, a TOML-based configuration system, flexible input/output options, and API integration for notifications.

Architecture

The CLI follows a clean separation between argument parsing, configuration, and scanner execution:

graph TB
    A[main.rs] -->|parse args| B[cli.rs<br>Clap derive structs]
    A -->|load config| C[config.rs<br>TOML + CLI merge]
    A -->|dispatch| D[commands/]

    C -->|build| E[ScannerConfig]

    D --> F[dns.rs]
    D --> G[whois.rs]
    D --> H[tcpsyn.rs]
    D --> I[tls.rs]
    D --> J[http.rs]
    D --> K[generate.rs]
    D --> L[notify.rs]

    F & G & H & I & J -->|use| E
    F & G & H & I & J -->|write| M[output.rs<br>console / JSON file]

    L -->|uses| N[mrpf_api_client]

Subcommands

CommandPurposeRequires root
mrpf dnsDNS resolution (A, AAAA, CNAME, MX, etc.)Yes
mrpf whoisWHOIS domain lookupsYes
mrpf tcpsynTCP SYN port scanningYes
mrpf tlsTLS/SNI certificate discoveryYes
mrpf httpTemplated HTTP/1.1 requestsYes
mrpf generateGenerate sample JSON input files or configNo
mrpf notifySend notification via MRPF APINo

Configuration

The CLI uses a layered configuration model where CLI arguments always take priority:

CLI flags  >  config file  >  auto-detected defaults

Config file location

  • Default: ~/.mrpf/config.toml
  • Override: mrpf --config /path/to/config.toml <command>

Only the [cli] section is read by mrpf_cli.

Config file format

[cli]
interface = "en0"
# src_ip = "192.168.1.100"     # optional — auto-detected from interface
# router_ip = "192.168.1.1"    # optional — auto-detected from interface
rate_limit = 1000               # packets per second

base_url = "https://api.mrpf.example.com"  # used by `mrpf notify`
api_key = "your-api-key-here"              # used by `mrpf notify`

The ScannerConfig is built by resolving the interface, extracting its MAC and IPv4 address, and applying any overrides from the config file or CLI flags. When src_ip or router_ip are not explicitly configured, they default to the interface’s actual IP and the first IP in its subnet respectively.

Input / Output

Targets

All scanner subcommands accept targets in two ways:

  1. CLI positional arguments: mrpf dns example.com google.com
  2. JSON input file: mrpf dns -f dns_input.json

The mrpf generate <type> command creates sample input files pre-filled with sensible defaults for each scanner type.

Output

  • Console (default): Pretty-printed JSON to stdout
  • JSON file: --output json --output-file results.json

API Integration

The notify subcommand uses mrpf_api_client to send notifications to the MRPF API via PUT /notifications. This enables the CLI to report scan results or status updates that trigger push notifications to the Apple app.

The API client uses reqwest with rustls-tls and authenticates via the x-api-key header.

Design Decisions

Why clap derive over builder

Clap’s derive API keeps argument definitions close to their types, making it easy to add new subcommands by creating a new file in commands/ with its Args struct. The Commands enum in cli.rs is the single point where all subcommands are registered.

Why TOML for config

TOML is simple, human-readable, and works well with serde while allowing multiple services to share a single ~/.mrpf/config.toml via separate sections (e.g. [cli], [scanner], [proxy]).

Why one-shot tokio runtime for notify

The scanner subcommands are synchronous (they use the engine’s thread-based architecture). Only the notify command needs async (for reqwest). Rather than making the entire binary async, a one-shot tokio::runtime::Runtime is created only when needed.