ZEEK FOR ICS

Zeek for ICS: Logging Industrial Protocols With ICSNPP

How Zeek and CISA's ICSNPP parsers turn industrial traffic into searchable logs: the packages and logs per protocol, a lab install, three worked questions answered from the logs, Zeek next to Suricata, and ATT&CK for ICS detections.

By EDWartens engineering team 11 October 2026 9 min
Zeek for ICS: Logging Industrial Protocols With ICSNPP

Zeek for ICS means running the open source Zeek network security monitor on a passive copy of industrial control traffic, with CISA's ICSNPP parsers added, so that every Modbus read and write, every S7comm program download, every EtherNet/IP and CIP command and every BACnet property write becomes a searchable log line you can keep for months. Zeek understands Modbus and DNP3 on its own; ICSNPP adds full parsers for S7comm, EtherNet/IP and CIP, BACnet, OPC UA Binary, Profinet IO CM and more, and extends the Modbus and DNP3 logs. It never sends a packet to the plant, which is why it is one of the safest first security controls in operational technology (OT).

Versions and parser lists were checked on zeek.org and CISA's GitHub repository in October 2026. Zeek, ICSNPP, Suricata and Malcolm belong to their projects; this guide is defensive and lab-based throughout.

What Zeek does, and what it does not

Zeek is not mainly a signature engine. It watches traffic, hands each connection to a protocol analyser chosen by content rather than port, and writes one log per kind of activity: conn.log for every connection, protocol logs such as modbus.log or dnp3.log for each request and reply, weird.log for protocol oddities, notice.log for things a script flagged and capture_loss.log to tell you whether the sensor is missing packets. Every line about one connection shares a connection uid, so you can follow one conversation across all the logs.

That design suits plants well. Control networks are predictable: the same HMI polls the same PLCs for the same registers on the same cycle, day after day. When everything normal is written down, anything abnormal stands out, and you can ask a question about last month that nobody thought of at the time. Zeek's get Zeek page listed Zeek 9.0 as the current long-term support release when we checked, with the 8.0 line as the previous LTS.

What Zeek cannot see is just as important. Serial links such as Modbus RTU on RS-485 never reach Ethernet. Traffic between two devices on the same switch never reaches a sensor unless that switch mirrors it. Encrypted sessions show who talked to whom and when, but not what was said. And a change made at the controller's own panel leaves no network trace at all.

The ICSNPP parsers and the logs they add

CISA's ICSNPP repository (Industrial Control Systems Network Protocol Parsers, released under the 3-clause BSD licence) lists the packages. Each protocol writes several logs that share the connection uid.

PackageProtocolLogs it adds (examples)Question it answers
icsnpp-modbusModbus/TCP, TCP 502modbus_detailed.log, modbus_read_device_identification.logWhich registers did each client write, with what values?
icsnpp-s7commS7comm, S7comm-plus, COTP, TCP 102s7comm.log, s7comm_read_szl.log, s7comm_upload_download.logWho downloaded program blocks to which PLC?
icsnpp-enipEtherNet/IP and CIP, TCP 44818, UDP 2222enip.log, cip.log, cip_identity.log, cip_io.logWhich host sent CIP resets or List Identity sweeps?
icsnpp-dnp3DNP3, TCP 20000dnp3_control.log, dnp3_objects.logWho issued select and operate commands?
icsnpp-bacnetBACnet/IP, UDP 47808bacnet.log, bacnet_discovery.log, bacnet_property.logWho wrote a setpoint at a high priority?

The repository also lists full parsers for BSAP, ANSI C12.22, EtherCAT, GE-SRTP, Genisys, HART-IP, Omron FINS, OPC UA Binary, ROC Plus, Synchrophasor (C37.118) and Profinet IO CM, so it covers protocols from power, water, oil and gas and building automation.

ICSNPP packages and the logs they add
ICSNPP packages and the logs they add

Installing ICSNPP in a lab

Run everything on a Linux virtual machine of your own, against public ICS capture files. The workflow is short:

  1. Install Zeek from a binary package, as the Zeek manual recommends, and add its bin directory to your path.
  2. Install the packages with Zeek's package manager, for example zkg install icsnpp-modbus, then icsnpp-s7comm, icsnpp-enip, icsnpp-dnp3 and icsnpp-bacnet.
  3. Confirm the analysers loaded: zeek -NN lists every analyser, and you should see S7comm, ENIP and BACnet among them.
  4. Run Zeek on a capture with installed packages enabled: zeek -C -r capture.pcap local. The -C flag ignores checksum errors, which are common in captures.
  5. List the logs, then read them with zeek-cut, which prints just the columns you name.

Test new packages on the same Zeek version in the lab before you put them on a production sensor. A parser that crashes takes your visibility with it.

“ZeekWeek 2022 - Two Years of Developing Parsers for Industrial Control System Protocol - Seth Grover” by Zeek, 32 min. Played from the creator's own YouTube channel; the video belongs to them.

Worked example: turning logs into answers

Question 1: is the HMI polling at its configured rate? Five consecutive Modbus read requests from the HMI to PLC-1 in modbus_detailed.log carry the Unix timestamps 1728640800.000, 1728640800.500, 1728640801.001, 1728640801.500 and 1728640802.002. The intervals are 0.500, 0.501, 0.499 and 0.502 s, so the mean is (0.500 + 0.501 + 0.499 + 0.502) / 4 = 0.5005 s. An hour should therefore hold about 3,600 / 0.5 = 7,200 polls. If tomorrow's count is 14,400, something is polling twice as fast; if it is zero, the HMI has lost its link and the operators will notice before you do.

Question 2: how much does that poll cost? The matching conn.log line shows a duration of 3,600 s and orig_bytes of 1,200,000. That is 1,200,000 / 3,600 = 333 bytes a second, about 2,667 bit/s, or 1,200,000 / 7,200 = 167 bytes of request payload per poll cycle. Small numbers, which is why industrial traffic is cheap to log in full.

Question 3: how complete is the asset inventory? The site register lists 45 networked devices in one area. A week of Zeek logs (conn.log addresses, plus vendor and firmware from cip_identity.log and Modbus device identification replies) finds 37 of them and 3 that are not on the register. Coverage is 37 / 45 = 82.2%. The 8 silent devices need a site check (spares, serial devices behind gateways, equipment that talks only at shift change), and the 3 unknowns need identifying and an owner before anything else.

Zeek next to Suricata

Zeek and Suricata are complementary, which is why CISA's Malcolm and Security Onion run both.

PointZeek with ICSNPPSuricata
Main outputTransaction logs for everythingAlerts when a rule matches, plus EVE metadata
FindsAnything you can describe after the eventPatterns written in advance
Best OT useBaselines, inventory, rare function codesKnown-bad commands, such as a write from the wrong host
Tuning workDeciding what to log and how long to keep itRemoving noise, writing local rules

If you add Suricata, two details matter. In Suricata 8's default configuration the Modbus, DNP3 and EtherNet/IP parsers ship disabled, so OT rules stay silent until you enable them. And the Suricata modbus keyword treats an address range a<>b as greater than a and smaller than b. To cover holding registers 100 to 149 in a PLC manual that counts from zero, convert to 101 to 150 (Suricata counts from 1) and write address 100<>151.

From logs to detections

Map each detection to MITRE ATT&CK for ICS, which had 12 tactics when we checked, including two unique to industrial systems: Inhibit Response Function and Impair Process Control. Typical Zeek-visible techniques are T0843 Program Download (an S7 or CIP program transfer outside a maintenance window), T0836 Modify Parameter (a Modbus write to setpoint registers), T0846 Remote System Discovery (one host sending List Identity or Who-Is to every device) and T0858 Change Operating Mode (an S7 PLC stop). IDs change between versions, so check them on the site when you write a detection note.

Zeek-visible ATT&CK for ICS techniques
Zeek-visible ATT&CK for ICS techniques

When an alert fires, the control room owns the process. Triage in a fixed order: what fired, where it is, who did it, and what it could do to the process. If it could move the plant, call the operators first and let them choose the containment step. Never send commands to a controller as part of a security response.

When to step up to Malcolm

Running Zeek by hand is the best way to learn it. For a team, CISA's Malcolm packages Zeek with ICSNPP, Suricata, Arkime and OpenSearch, with prebuilt ICS dashboards, under the Apache 2.0 licence. Malcolm's system requirements set a minimum of 8 CPU cores and 24 GB of RAM on a dedicated host, with 16 or more cores and 32 GB or more recommended, so plan a lab server rather than a laptop.

For the wider context of OT security, our guide to OT cybersecurity, IEC 62443 and the Purdue model explains where sensors sit in a zoned plant, and our roundup of free IEC 62443 training lists the programme side.

Learn Zeek for ICS free

The free OT Network Monitoring: Zeek, Suricata and Malcolm course teaches all of this in fifteen modules: passive sensor placement, Wireshark on Modbus, S7comm, EtherNet/IP, DNP3 and BACnet, Zeek with ICSNPP, asset inventory from traffic, Suricata rules for OT, Malcolm and Arkime, baselines, ATT&CK for ICS and alert triage with operations. Every lab runs in your own virtual machines with public captures.

It is a free course with a verifiable certificate of completion, and anyone can check a certificate on our verification page. It is not a certification from CISA, MITRE or the Zeek project, and EDWartens is not affiliated with them. Start the Zeek and OT monitoring course in your own lab.

Take the free course

Questions

Can Zeek decode industrial protocols?

Yes. Zeek parses Modbus and DNP3 on its own, and CISA's ICSNPP packages add full parsers for S7comm, EtherNet/IP and CIP, BACnet, OPC UA Binary, Profinet IO CM and others, plus richer Modbus and DNP3 logs. Each protocol writes logs linked by the connection uid.

What is ICSNPP?

ICSNPP (Industrial Control Systems Network Protocol Parsers) is a set of free Zeek plugins published by CISA under the 3-clause BSD licence. They turn industrial protocol traffic into detailed Zeek logs, such as program downloads in s7comm_upload_download.log or device identity in cip_identity.log.

Is Zeek safe to run on a plant network?

Yes, when it runs on a passive copy of the traffic from a SPAN port or a TAP. Zeek only receives packets and never transmits on the control network. Setting up the SPAN port is still a change to a live switch and goes through the plant's change process.

Should I use Zeek or Suricata for OT monitoring?

Use both. Zeek logs every transaction so you can baseline traffic, build an inventory and ask new questions later; Suricata alerts the moment a known-bad pattern appears. Remember that Suricata 8 ships its Modbus, DNP3 and EtherNet/IP parsers disabled.

What hardware do I need to learn Zeek for ICS?

A laptop able to run a Linux virtual machine with about 8 GB of RAM is enough for Zeek, ICSNPP and Suricata on public capture files. CISA's Malcolm, which bundles them with dashboards, needs a dedicated host with at least 8 CPU cores and 24 GB of RAM.

Is there a free Zeek for ICS course with a certificate?

Yes. OT Network Monitoring: Zeek, Suricata and Malcolm on EDWartens is a free course with a verifiable certificate of completion, issued after the modules and a 15-question final passed at 60 percent. It is not a CISA, MITRE or Zeek project certification.

Sources

Written by the EDWartens engineering team for general education. Product names are trademarks of their owners; mentioning them does not imply endorsement. Prices and terms of other providers were checked on the date shown and can change.