Our FortiGate IPS was blocking Modbus TCP polling from SCADA to PLCs — production operators were getting alerts every 30 minutes.
When Normal OT Traffic Looked Hostile
We first saw the issue on a Tuesday morning shift change, which is about the worst time to discover that our perimeter-style IPS logic had wandered into the control network. The SCADA server kept polling a bank of PLCs over Modbus TCP, the FortiGate running FortiOS 7.4.3 kept classifying part of that traffic as scanning behavior, and our line operators were stuck watching nuisance alerts while trying to keep production moving.
My first assumption was wrong. I thought we had a misconfigured PLC or a failing switch generating malformed packets. We pulled SPAN captures from the OT core, checked the SCADA polling cycle, and compared the traffic against the previous week. The packets were boring. They were repetitive, clean, and expected. That was the point.
The default IPS profile had signatures that flagged legitimate high-frequency Modbus read requests as scanning activity. In a normal IT subnet, repeated requests across device registers can look suspicious because users and laptops do not usually behave that way. In our manufacturing environment, that behavior was exactly how the SCADA system maintained state, alarms, trends, and historian feeds.
Noise breaks trust.
I do not like running IPS blindly in OT, and I like disabling it even less. The right answer was not to turn inspection off. The right answer was to tune the inspection layer so it understood the difference between our process traffic and a real attacker probing the cell network.
Why Enterprise IPS Logic Trips Over Modbus
Enterprise IPS profiles are built around patterns that make sense for workstations, servers, browsers, remote access tools, and user-driven application flows. OT protocols are different. Modbus TCP, EtherNet/IP, PROFINET, and vendor-specific engineering traffic can be steady, repetitive, unauthenticated, and extremely predictable, which makes them easy to mistake for reconnaissance when the IPS has no plant context.
Our SCADA server used a fixed polling pattern against PLC registers every few seconds. During high-load periods, the historian and alarm subsystem increased read volume, and the FortiGate saw repeated function code activity from one source to many industrial endpoints. From an enterprise security lens, that resembled scanning. From our control room lens, it was normal production telemetry.
What I didn’t expect was how cleanly the false positives lined up with shift reporting windows. We had alerts every 30 minutes because our reporting process briefly increased read density at predictable intervals. That timing helped us prove the traffic was legitimate, but it also showed how badly a generic profile can misunderstand manufacturing behavior.
Context beats defaults.
We kept reminding ourselves that IPS signatures designed for enterprise IT traffic will classify legitimate OT protocol behavior as attacks. Tuning is not optional in manufacturing networks. I would rather spend a careful afternoon building exceptions than spend months teaching operators to ignore security alerts.
Trace the Signatures Before Touching Policy
We started with evidence, not guesses. I exported IPS logs from FortiAnalyzer, filtered on the SCADA source IP, grouped by destination PLC, and reviewed the signature IDs that repeated during production windows. I also ran a small Python 3.11 parser on Ubuntu 22.04 to correlate log timestamps with historian polling intervals, because manually reading thousands of IPS events is where mistakes hide.
- Confirmed the source was our primary SCADA polling server, not an engineering workstation.
- Matched destination addresses to known PLCs in our asset inventory.
- Compared alert timestamps against historian and reporting schedules.
- Reviewed packet captures for malformed Modbus function codes.
- Checked whether any destination showed failed sessions or unusual port changes.
- Validated that the same signatures did not appear on unrelated IT VLANs.
The repeated offenders were a small group of signatures tied to scan-like Modbus behavior and abnormal industrial protocol access patterns. The signatures were not bad. They were just too broad for our cell zone, where one SCADA host was supposed to query many PLCs all day long.
Small lists win.
I refused to create a broad bypass for port 502 because that would have hidden real problems. We needed exceptions tied to specific signatures, specific source and destination groups, and the one traffic path that represented known-good polling. Anything outside that path still deserved inspection.
Build an OT-Specific IPS Profile
We created a dedicated IPS sensor for the OT firewall policy instead of editing the enterprise default profile. That mattered because our office networks, DMZ services, and remote access segments still needed the stricter baseline. Manufacturing traffic needed its own policy object, its own comments, and its own change-control record.
config ips sensor
edit "IPS_OT_SCADA_MODBUS_TUNED"
set comment "OT profile for SCADA to PLC Modbus TCP polling on FortiOS 7.4.3"
config entries
edit 1
set rule 12345
set status disable
set log enable
next
edit 2
set rule 23456
set status disable
set log enable
next
edit 3
set rule 34567
set status disable
set log enable
next
end
next
end
config firewall policy
edit 42
set name "SCADA_to_PLC_Modbus"
set srcintf "OT_SCADA"
set dstintf "OT_CELL"
set srcaddr "SCADA_Primary"
set dstaddr "PLC_Modbus_Group"
set service "TCP_502"
set ips-sensor "IPS_OT_SCADA_MODBUS_TUNED"
set logtraffic all
next
end
The production profile eventually included 12 signature exceptions. Each exception had a reason, a packet capture reference, an affected asset group, and a review date. I wanted the next engineer to understand why the exception existed without having to reverse-engineer my thinking during an outage.
After creating an OT-specific IPS profile with 12 signature exceptions, false positive rate dropped from 34/day to 0. That number mattered because it changed behavior in the control room. Operators stopped dismissing every security pop-up as background noise, and our team could focus on alerts that deserved investigation.
Precision is cheaper than panic.
My opinion is that every OT IPS profile should be treated like process safety logic: narrow scope, documented intent, controlled changes, and no casual wildcard exceptions. A default profile is a starting point, not a design.
Watch for Real Threats After Removing Noise
Once the false positives disappeared, we did not declare victory and move on. We added monitoring around the exceptions so the same traffic path stayed visible. The FortiGate still logged allowed sessions, FortiAnalyzer still tracked volume changes, and we built alerts for new Modbus talkers, unexpected destinations, and polling spikes outside the normal reporting cycle.
We also kept IPS active for other industrial signatures that made sense in our environment. Write function abuse, suspicious engineering workstation access, protocol fuzzing, and traffic from non-SCADA sources stayed in scope. The custom profile removed noise from legitimate reads; it did not create a quiet tunnel through the firewall.
The best control was boring documentation. We mapped the SCADA server, PLC address groups, approved service objects, expected polling intervals, and known maintenance windows. When we upgraded lab firewalls from FortiOS 7.4.2 to FortiOS 7.4.3 before production rollout, we replayed captured traffic and confirmed the same exceptions still behaved correctly.
Trust needs maintenance.
I do not believe OT security works when we copy enterprise controls into the plant and hope they fit. The plant has patterns, timing, and consequences that standard IT profiles do not understand. We still need inspection, but we need inspection that respects the process.
Keep Tuning Close to Production Reality
Our final operating model is simple: any IPS change touching PLC or SCADA traffic gets reviewed with network security, controls engineering, and operations. We test in the lab, validate on a limited production window, watch logs during a full shift cycle, and keep rollback ready. That sounds slow until a bad security change stops a line.
I learned that the hard part was not finding the 12 noisy signatures. The hard part was resisting the easy fix. Disabling IPS for the OT zone would have made the alerts disappear, but it also would have removed one of the few inspection points we had between SCADA and the cell networks.
In my environment, FortiGate IPS belongs in OT, but only when we tune it like we understand the machines behind the IP addresses. Defaults protect averages. Manufacturing networks punish averages.

