Security Probes
Security probes
Axiom Border assesses the network it sits on with four probes. They share one execution model, one audit trail and one accumulated view of results, so the findings of each one reinforce the others instead of living in separate reports.
| Probe | What it answers | Requires |
|---|---|---|
| Network discovery | What is out there, and what is it listening on? | nmap 7.80+ on PATH |
| Vulnerability scanning | Which of those services are vulnerable? | A templates directory (OT/ICS checks are included) |
| SNMP | What does the device say about itself? | Reachable SNMP agent, credentials or a profile |
| Traffic capture | What is actually crossing the wire? | libpcap, a valid capture interface, root |
Each runs two ways: automatically on a configurable interval, and manually on demand from the API or the web UI. Results are kept locally as probe state and written to InfluxDB as metrics, and every execution is audited.
flowchart TB
DISC["Network discovery<br><i>live hosts and ports</i>"]
DISC --> VULN["Vulnerabilities"]
DISC --> SNMP["SNMP identity"]
DISC --> CAP["Traffic capture"]
VULN --> INV
SNMP --> INV
CAP --> INV
DISC --> INV[("Consolidated<br>inventory")]
INV --> ALARM["Alarms and<br>audit trail"]
Network discovery establishes the baseline and the other three enrich it. That ordering matters: a
vulnerability scan with no targets scans every host in the baseline, so a discovery scan must have run
first for it to have anything to do. Newly discovered hosts also trigger a vulnerability scan on their
own, grouped together after a short delay, so new assets get assessed without waiting for the next
interval.
Where you see the results
Network status in the console is the operational view of everything on this page: the discovered hosts with their addresses, when each was first and last seen, and per-host actions for its open ports, its vulnerabilities and its SNMP data. The charts below summarise findings by severity, hosts by status, and how many hosts carry vulnerabilities at all.
The header names the last assessment that ran and how it finished, so you can tell at a glance whether what you are looking at is current.
Each row carries its own actions. Scan opens the Ports panel for that host — what it is listening on, with the service the scan identified and when the port was first and last seen:
Vulnerabilities opens the findings for that host. Each row names the check that fired and explains what it confirmed, which is what makes a finding actionable rather than just a label:
Both panels carry a re-scan button, so you can reassess a single host without launching a sweep of the whole range.
How to read a finding
Name says what was confirmed — Modbus/TCP Diagnostics Function Exposed Without Authentication — and
Description explains how it was confirmed and why it matters. Two more columns sit to the right of the
description: CVE, empty whenever the finding is an exposure rather than a published vulnerability, and
Template ID, which always identifies the check (modbus-diagnostics-exposure and the like). Since not
every finding has a CVE, the template identifier is the stable way to refer to one.
Checks from the write/control layer are marked twice over: the name ends in [INTRUSIVE] and the
description opens with INTRUSIVE / GATED. Those only ever run when a scan explicitly asks for intrusive
mode — see OT/ICS vulnerability scanning.
The shared execution model
Every probe launch is asynchronous: the request is accepted, you get an identifier back immediately, and the work continues in the background.
Open Network status and use Edit to set the scan parameters, then Reload to refresh the view once the run finishes. The header keeps showing the state of the most recent execution while it progresses.
Poll GET /security/executions/{uuid} until the status leaves inprogress, landing on finished or
failed. An execution record carries two payloads that are easy to confuse: currentOutput is the
result of that run alone, while currentStatus is the consolidated view of the affected hosts. To list
completed runs, filter by finished.
Executions also publish over MQTT
If you would rather not poll, the embedded broker publishes started, finishedok and failed events
for every execution. See MQTT and OpenGate operations.
Network discovery and port scanning
The discovery probe. It finds live hosts, enumerates ports, and optionally identifies services and operating systems.
The portFilter above is worth copying if you have industrial equipment: it covers the common IT range
plus the Modbus, IEC-104, DNP3 and BACnet ports, so the OT assets show up in the baseline that the
vulnerability probe will later work from.
Practical notes:
os: trueneeds root, because OS fingerprinting implies a SYN scan over raw sockets. Without it, leave OS detection off.udp: trueis slow. RestrictudpPortsrather than sweeping.- Only one discovery scan runs at a time. A second request returns
409 Conflictunless you pass?force=true, which cancels the running one and marks itfailedwithcancelled due to forced run. - The default
portFilteris the full1-65535range. On a/24at cautious timing that is a long scan — narrow it.
Scheduled behaviour is configured under securityProbes.nmap — from the console’s Configuration
view, or in the file. See Configuration.
Vulnerability scanning
Template-based scanning, in two distinct halves. The web and CVE half uses the standard upstream template tree and needs that tree present on disk. The OT/ICS half uses Axiom Border’s own suite of 57 industrial protocol checks, which are installed with the product and work with no internet access.
Depth is chosen with level, which takes one of four values — ligero, medio, profundo or ot.
Always use one of those four: each selects a different set of checks, and the mapping table in
Configuration is worth reading before you pick one.
Industrial protocol scanning has its own page, because the safety model deserves the space:
→ OT/ICS vulnerability scanning — Modbus/TCP, IEC 60870-5-104, DNP3, BACnet/IP and OPC UA, with the two-lock model that governs write operations.
Check the templates directory before trusting an empty report
A web scan that reports nothing looks exactly like a web scan that had no templates to run. Confirm the directory is populated:
You should see per-protocol directories such as http/, network/ and ssl/. CVE templates live under
http/cves/, not at the root. OT/ICS findings are unaffected, because those checks are installed with
the product.
SNMP — interrogation and profiles
Two operations: a GET of specific OIDs, and a walk from a root OID.
Symbolic names work as well as numeric OIDs — sysDescr is resolved through the bundled
MIB catalogue, which matters on an air-gapped probe where you cannot look an OID up.
Profiles and associations
Rather than passing credentials with every request, store them once as a profile and bind them to hosts with an association:
Resolution order when a scan runs: the request’s profileName wins, then the per-IP association, then
the configured default. A target that resolves to no profile fails with
snmp omitted targets due to missing profile: <ip>.
Supported versions are v1, v2c and v3. For v3, defaults when fields are left empty are authPriv with
SHA and AES.
Prefer profiles over inline credentials
Credentials sent inline as customParams are persisted with the execution record and returned in its
detail. Profiles keep them out of execution history. Use customParams for one-off diagnostics only.
Note
The scheduled SNMP probe runs a discovery pass first, with a fixed budget of 30 seconds. A /24 at
cautious timing will exhaust it, so narrow the range or raise the discovery timing value.
Traffic capture
Two modes, both capturing IPv4 traffic through libpcap:
- Continuous, driven by configuration. When
securityProbes.sniffing.interfacesis non-empty, capture starts automatically and persists flow counters to thenetworktrafficbucket everyflushInterval. - On demand, via the API, for a bounded duration, merged into the latest scan result.
The BPF filter above captures Modbus traffic only, which is a good way to confirm an industrial segment is actually active before scanning it.
Capture contributes bytesIn/bytesOut and packetsIn/packetsOut counters plus samples to each
host in the merged result.
The interface name is the usual culprit
Capture failing silently almost always comes down to the interface. It must be a pcap name: eth0
or enp3s0 on Linux, en0 on macOS, and an Npcap NPF device path such as \\Device\\NPF_{GUID} on
Windows — the friendly name Ethernet does not work there. Confirm with nmap --iflist.
Also confirm the service runs as root, and that there is traffic to see:
sudo tcpdump -i <iface> -c 10.
The merged result view
Individual executions tell you what one probe found. GET /security/results/last tells you what is
known about a host, merged across all four probes:
Each host carries ipAddress, hostname, macAddress, os, manufacturer, status, firstSeen and
updatedAt, then the per-probe contributions: ports from discovery, vulnerabilities from the
vulnerability scan, snmp entries from the SNMP probe, and sniffing counters from traffic capture.
This is the view worth putting on a dashboard.
The firstSeen and updatedAt pair is what turns the baseline into change detection: a host with a
recent firstSeen is new to the network.
Feeding results into rules
Probe results are available to the rules engine, so a scan finding can raise an alarm the same way a metric can — a new host appearing, a critical vulnerability, a port opening that should not be open. See Alarms and rules.
Results also flow to InfluxDB as metrics under the SECSCAN group with a probe tag, and are queryable
through POST /auditlog with agent set to network, vulns, snmp or sniff.