Skip to main content

Active probing

Active mode sends protocol-native read-only queries to OT devices to enumerate identity, firmware, and configuration details that passive observation alone cannot reveal. Every active probe is designed to be non-destructive, but OT devices are notoriously fragile -- so active mode is gated behind an explicit confirmation flag.

Basic usage​

sudo cyprobe active --targets 192.168.1.0/24 --active-confirm

Without --active-confirm, the command prints what it would do and exits. This is intentional -- you should review the probe plan before sending packets to production OT infrastructure.

Dry run (default)​

sudo cyprobe active --targets 192.168.1.0/24

Output:

PROBE PLAN (dry run — pass --active-confirm to execute)
TARGET PROTOCOL PROBE RISK
192.168.1.10 Modbus TCP FC 0x2B Device ID low
192.168.1.20 S7comm SZL 0x0011 low
192.168.1.30 OPC UA GetEndpoints low
192.168.1.40 BACnet Who-Is low

4 probes planned. 0 targets on safelist. Pass --active-confirm to execute.

What each probe does​

ProtocolProbeWhat it returnsRisk
Modbus TCPFC 0x2B (Device ID)Vendor name, product code, firmware versionLow
DNP3Data Link StatusOutstation address, link-layer configLow
S7commSZL request (0x0011)Module identification, firmware version, serialLow
OPC UAGetEndpointsEndpoint URLs, security modes, certificate infoLow
BACnetWho-Is + Read-PropertyDevice ID, object name, firmware, vendorLow
EtherNet/IPList IdentityVendor ID, device type, product name, serialLow
IEC 104STARTDTControl direction confirmation, link statusLow
MQTTCONNECT (no auth)Broker version, auth requirement, TLS supportLow

All probes are read-only. No writes, no configuration changes, no firmware uploads, no coil/register modifications.

Safety gates​

--active-confirm​

Required to actually send probes. Without it, cyprobe only prints the plan.

Rate limiting​

sudo cyprobe active --targets 192.168.1.0/24 --active-confirm \
--rate-limit 10 \
--probe-timeout 5000
FlagDefaultDescription
--rate-limit10Maximum probes per second across all targets
--probe-timeout3000Per-probe timeout in milliseconds
--retries1Number of retries on timeout (0 = no retry)

The default rate of 10 probes/second is conservative. Most OT networks can handle more, but start low and increase only after validation.

Fragile device safelist​

Some devices are known to misbehave when probed -- older PLCs that restart on unexpected packets, safety controllers that should never receive unsolicited traffic, etc.

Create a safelist file to exclude them:

# safelist.yml
- ip: 192.168.1.100
reason: "Safety PLC — do not probe"
- ip: 192.168.1.101
reason: "Legacy Modicon — crashes on Device ID request"
- cidr: 10.0.50.0/24
reason: "SIS network — no active probing allowed"
sudo cyprobe active --targets 192.168.1.0/24 --active-confirm \
--safelist safelist.yml

Safelisted targets are skipped entirely and noted in the output. The dry-run plan also flags them so you can verify coverage before executing.

Combining passive and active​

A common workflow is to run passive discovery first, then target active probes only at the assets that were found:

# Step 1: passive discovery
sudo cyprobe passive --interface eth0 --duration 300 --format json > passive.json

# Step 2: active probes against discovered assets only
sudo cyprobe active --from-passive passive.json --active-confirm

The --from-passive flag reads the passive output and builds a target list from discovered IPs, automatically selecting the right protocol probes for each.

Output​

Active mode produces the same output formats as passive mode (text, json, sarif) with additional fields for probe responses:

sudo cyprobe active --targets 192.168.1.0/24 --active-confirm \
--format json > active.json

Each asset object gains a probe_response field containing the raw structured data returned by the device.

Next step​