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