Skip to content

14.2 Network Segmentation and DMZ

The previous chapter covered the threats OT networks face. The most effective defense against those threats is network segmentation: dividing the network into isolated zones so that a compromise in 1 zone does not spread to others.

Industrial protocols have no authentication. A device with network access reads and writes PLC registers. Segmentation limits which devices have network access to which zones. An attacker who compromises an engineering workstation in 1 cell does not reach PLCs in another cell when the cells are in separate VLANs with firewall rules between them.

The DMZ (Demilitarized Zone) sits between OT and IT. The DMZ contains systems that communicate with both sides.

ComponentPurpose in DMZ
Historian mirrorReceives replicated data from the OT historian. IT users query the mirror, not the OT historian directly.
Jump serverServes as a single, audited entry point for remote access to OT. Remote sessions terminate here.
Patch server (WSUS/SCCM)Downloads patches from the internet and stages the patches for OT deployment. OT devices pull patches from the DMZ, never from the internet.
Data aggregatorCollects, filters, and normalizes OT data before sending the data to IT or cloud. The aggregator reduces the attack surface by limiting what data leaves OT.
Antivirus update serverDownloads signature updates and distributes the updates to OT endpoints. OT devices never connect to the internet for updates.
Syslog collectorReceives logs from OT devices. The IT SIEM pulls logs from this collector, not directly from OT switches.

Each component exists in the DMZ because the component communicates with both IT and OT. Placing the component in the DMZ means neither IT nor OT has direct access to the other.

SourceDestinationAllowedDenied
ITDMZHistorian queries, jump server RDPDirect access to OT
DMZOTHistorian replication (pull), patch distributionArbitrary connections
OTDMZSyslog, SNMP traps, historian data pushInternet access
ITOTNeverEverything
OTInternetNeverEverything

A data diode enforces one-way data flow at the physical layer. The diode uses a fiber-optic transmitter on the source side and a receiver on the destination side, with no return fiber. Data flows in 1 direction only. No software vulnerability, misconfiguration, or exploit creates a return path because the physical medium does not exist.

The transmitter converts data to light pulses. The receiver converts light pulses back to data. No return fiber exists, so no data flows from IT to OT. The diode software handles protocol conversion: the software receives TCP data on the OT side, strips the protocol headers, sends the raw data over the one-way link, and reconstructs the TCP session on the IT side.

  • Sending historian data from OT to IT for analytics
  • Exporting syslog from OT to the IT SIEM
  • Replicating OPC UA data to a cloud gateway
  • Sending safety system status to the corporate dashboard
ProductVendorKey Feature
Waterfall Unidirectional GatewayWaterfall SecuritySupports OPC, Modbus, historian replication
Owl Cyber DefenseOwlCross-domain transfer, government certified
Hirschmann Eagle OneBeldenIntegrated with the Hirschmann ecosystem
Fox DataDiodeFox-ITHigh-throughput (up to 1 Gbps)

Data diodes are appropriate for the highest-security zones (safety systems, infrastructure) where the consequence of inbound compromise outweighs the inconvenience of one-way communication.

OT firewall rules differ from IT rules. OT rules are protocol-specific, direction-specific, and source/destination-specific.

Example Rule Set: Production Cell Firewall

Section titled “Example Rule Set: Production Cell Firewall”
RuleSourceDestinationProtocolPortActionRationale
1192.168.10.50 (SCADA)192.168.20.0/24 (PLCs)TCP502PermitSCADA reads Modbus registers
2192.168.10.51 (Eng WS)192.168.20.0/24 (PLCs)TCP102PermitEngineering access (S7comm)
3192.168.20.0/24 (PLCs)192.168.10.60 (Historian)TCP4840PermitPLCs push OPC UA data
4192.168.50.0/24 (Mgmt)192.168.20.0/24 (Switches)TCP22PermitSSH management
5192.168.50.0/24 (Mgmt)192.168.20.0/24 (Switches)UDP161PermitSNMPv3 polling
6Any192.168.20.0/24UDP67-68DenyNo DHCP in production
7AnyAnyAnyAnyDenyImplicit deny-all

PROFINET RT uses EtherType 0x8892 at Layer 2. PROFINET RT traffic does not route and does not respond to IP-based firewall rules. PROFINET traffic stays within its VLAN. The firewall helps protect the PROFINET VLAN by blocking IP traffic into the VLAN except management access (SSH, SNMP) from the management VLAN.

VLANZoneDevicesRouting
10ProductionPLCs, drives, I/O modulesRouted to SCADA, historian only
20SCADAHMIs, SCADA serversRouted to production, historian
30SafetySIS controllers, safety PLCsNo routing to any other VLAN
40EngineeringEngineering workstationsRouted to production (controlled)
50ManagementSwitch management, SNMPRouted to all (SSH, SNMP only)
4094Black holeUnused portsNo routing, no traffic

Safety systems (VLAN 30) have no routing to any other VLAN. Safety systems communicate only with their dedicated safety controllers on the same VLAN.

Remote access is a major attack vector. Apply defense in depth:

  1. Terminate remote sessions on a jump server in the DMZ
  2. Require MFA (Multi-Factor Authentication) for every session
  3. Use time-limited access that expires automatically after the maintenance window
  4. Record remote sessions (screen recording and keystroke logging)
  5. Disable vendor remote access connections when not in active use
  6. Use separate credentials for remote access (not the same as local admin accounts)

The following script reads a firewall rule list (CSV format) and checks for overly permissive rules: rules that allow “any” source, “any” destination, or broad port ranges to OT subnets.

import csv
from dataclasses import dataclass
OT_SUBNETS = ["192.168.10.0/24", "192.168.20.0/24", "192.168.30.0/24"]
@dataclass
class Finding:
rule_num: int
severity: str
message: str
def validate_rules(rules_csv: str) -> list[Finding]:
findings = []
with open(rules_csv) as f:
for row in csv.DictReader(f):
num = int(row["rule"])
src, dst = row["source"], row["destination"]
port, action = row["port"], row["action"].lower()
if action != "permit":
continue
# Check for "any" source to OT subnets
if src.lower() == "any" and dst in OT_SUBNETS:
findings.append(Finding(num, "CRITICAL",
f"Rule {num}: 'any' source permitted to OT subnet {dst}"))
# Check for broad port ranges
if "-" in port:
low, high = map(int, port.split("-"))
if high - low > 100:
findings.append(Finding(num, "WARNING",
f"Rule {num}: broad port range {port} to {dst}"))
# Check for any/any
if src.lower() == "any" and dst.lower() == "any":
findings.append(Finding(num, "CRITICAL",
f"Rule {num}: permit any-to-any detected"))
return findings
for f in validate_rules("firewall_rules.csv"):
print(f"[{f.severity}] {f.message}")

Run this script after every firewall change to catch overly permissive rules before the rules reach production. The CSV format (rule,source,destination,protocol,port,action) matches the export format of most firewall management tools.

DMZ contains shared services

Historian mirrors, jump servers, and patch servers live in the DMZ. Neither IT nor OT connects directly to the other.

Data diodes enforce physics

No software exploit creates a return path through a data diode. Use data diodes for the highest-security zones.

Validate rules automatically

Script-based rule validation catches overly permissive rules before the rules reach production. Run validation after every change.

Segmentation defines the network architecture. IEC 62443 provides the framework for determining the security level each zone requires and the controls to implement. The next chapter covers the practical application of IEC 62443 security levels to OT network design.

  • IEC 62443-3-3:2013 — System security requirements and security levels
  • NIST SP 800-82 Rev. 3 — Guide to Operational Technology (OT) Security (2023)
  • Knapp, E. D., & Langill, J. T. (2014). Industrial Network Security (2nd ed.). Syngress.
  • Waterfall Security Solutions. (2023). Unidirectional Security Gateways. Waterfall.