Skip to main content

Passive discovery

Passive mode is the default and safest way to run cyprobe. It listens on a network interface (typically a SPAN / mirror port) and fingerprints OT protocols from observed traffic. Zero packets are injected into the network.

Basic usage

sudo cyprobe passive --interface eth0 --duration 300

This captures traffic on eth0 for 300 seconds (5 minutes), then writes results to stdout.

Key flags

FlagDefaultDescription
--interface(required)Network interface to capture on
--duration60Capture duration in seconds. 0 = run until Ctrl-C
--formattextOutput format: text, json, sarif
--output-Output file. - = stdout
--bpfnoneBPF filter to narrow capture (e.g. port 502)
--promisctrueEnable promiscuous mode on the interface

What it detects

For each supported protocol, the passive engine extracts:

ProtocolExtracted fields
Modbus TCPUnit ID, function codes observed, register ranges accessed
DNP3Source/destination addresses, object types
S7commRack/slot, PDU type, function codes
OPC UAEndpoint URL, security mode, policy URI
BACnetDevice ID, object name, vendor ID
EtherNet/IPVendor ID, device type, product name, serial
IEC 104ASDU type IDs, IOA ranges, cause of transmission
MQTTClient ID, topic names, QoS levels, TLS in use

Protocol fingerprinting

Cyprobe identifies protocols through a combination of:

  1. Port heuristics -- well-known OT ports (502, 102, 4840, etc.) as a first pass.
  2. Deep packet inspection -- protocol magic bytes and header structure validation. This catches OT traffic running on non-standard ports.
  3. Behavioral patterns -- request/response cadence and payload structure for protocols that lack unique magic bytes (e.g. Modbus).

Fingerprinting runs entirely in userspace with zero kernel modules.

Output formats

Text (default)

Human-readable table, one row per discovered asset:

ASSET INVENTORY (passive, 300s on eth0)
IP MAC PROTOCOL IDENTITY FIRST SEEN
192.168.1.10 00:1c:06:aa:bb:cc Modbus TCP Unit 1, FC 3/16 00:00:02
192.168.1.20 00:80:f4:11:22:33 S7comm Rack 0 Slot 2 00:00:05
192.168.1.30 00:0c:29:44:55:66 OPC UA opc.tcp://plc3:4840 00:00:08

JSON

Machine-readable array of asset objects:

sudo cyprobe passive --interface eth0 --duration 300 --format json > assets.json

Each object includes ip, mac, protocol, identity, first_seen, last_seen, packet_count, and protocol-specific metadata under details.

SARIF

SARIF 2.1.0 output for direct ingestion into the Cybrium platform or any SARIF-compatible tool:

sudo cyprobe passive --interface eth0 --duration 300 --format sarif > scan.sarif

Findings are emitted for each asset, with the rule ID indicating the protocol and the physicalLocation encoding the network address.

Continuous monitoring

For long-running passive capture, use --duration 0 and pipe output to a file with periodic rotation:

sudo cyprobe passive --interface eth0 --duration 0 --format json \
--output /var/log/cyprobe/assets.json

Cyprobe writes incremental updates to the output file as new assets are discovered. Use SIGHUP to force a flush and rotate.

Next step

  • Active mode -- send safe protocol queries for deeper enumeration
  • Rules -- evaluate discovered assets against posture checks