IEC 62443 defines four Security Levels for industrial control systems. At the highest level — SL-4, protection against state-sponsored attacks with extensive resources — the standard calls for unidirectional data flow enforcement. Not a firewall rule. Not a software policy. Hardware-enforced, physically one-way communication.
That’s where data diodes come in. And that’s where things get interesting, because the two most common OT protocols — OPC UA and MQTT — were both designed for bidirectional communication.
I used to install unidirectional gateways at Waterfall Security Solutions. I’ve deployed them at facilities with over 10 OT zones, pushing OPC UA and MQTT through one-way hardware in production.
In a previous post, I set up OPC UA and MQTT on a Raspberry Pi as an edge gateway. Here’s what happens when you need to secure that data path with hardware-enforced one-way communication.
IEC 62443: When Do You Need a Data Diode? #
IEC 62443 (ISA/IEC 62443) is the international standard for industrial cybersecurity. It defines Security Levels that describe the capability of an attacker you’re defending against:
| Security Level | Threat | What It Means | Typical Measure |
|---|---|---|---|
| SL-1 | Casual / unintentional | Accidental misuse, human error | Passwords, basic access control |
| SL-2 | Intentional, simple means | Disgruntled employee, script kiddie | Firewalls, network segmentation, role-based access |
| SL-3 | Sophisticated, moderate resources | Organised crime, hacktivists | Defence in depth, IDS/IPS, encrypted protocols |
| SL-4 | State-sponsored, extensive resources | Nation-state actors | Unidirectional gateways, air gaps, physical isolation |
Most OT networks operate at SL-2 or SL-3. A firewall between IT and OT, network segmentation, and monitoring gets you there. But at SL-4, a firewall isn’t enough — firewalls are software, and software has vulnerabilities. A misconfigured rule, an unpatched CVE, or a zero-day exploit can turn a firewall into a door.
A data diode eliminates this class of risk entirely. There is no software to exploit, no rule to misconfigure, no vulnerability to patch. Data flows one way because the hardware physically cannot transmit in the other direction.
In the Purdue model, data diodes typically sit between Level 3 (site operations) and Level 4 (enterprise) — or at the boundary of the ICS DMZ — allowing monitoring data to flow up to the corporate network while physically blocking any path back down to the OT environment. If the diode hardware fails, data simply stops flowing. The OT network continues operating unaffected — it’s fail-safe by design.
Data Diode vs Unidirectional Gateway #
These terms are often used interchangeably, but they’re different:
A data diode is hardware. It consists of a TX hardware module and an RX hardware module connected by a one-way fibre optic link — a TX laser on one end, an RX photodiode on the other, and no return fibre. Data can physically only travel in one direction. On its own, it doesn’t understand protocols.
A unidirectional gateway is the complete solution. It combines the data diode hardware with software agents (TX and RX) that handle protocol translation. The TX software agent connects to OT systems using native protocols, collects data, and sends it through the data diode. The RX software agent receives the one-way stream and reconstructs mirror servers on the IT network. The one-way enforcement happens in the fibre link between the hardware modules — the only path between the OT and IT networks.
flowchart TB
OT_SYS[OT Systems
PLCs, SCADA, BMS]
TX[TX Software Agent]
DIODE[Data Diode
One-way optical link]
RX[RX Software Agent]
IT_SYS[IT Systems
SIEM, Dashboards, Cloud]
OT_SYS --> TX
TX --> DIODE
DIODE --> RX
RX --> IT_SYS
style OT_SYS fill:#2d9c8f,color:#fff
style TX fill:#2d9c8f,color:#fff
style DIODE fill:#c0392b,color:#fff
style RX fill:#2980b9,color:#fff
style IT_SYS fill:#2980b9,color:#fff
Without the software agents, the data diode is useless — you can’t push a TCP handshake through a one-way link. The gateway makes the diode protocol-aware.
A single unidirectional gateway can handle multiple protocols simultaneously. In production, I’ve had gateways running OPC UA, MQTT, and Syslog through the same data diode at the same time.
The Core Problem: Bidirectional Protocols, One-Way Hardware #
Both OPC UA and MQTT are built on TCP, which requires a three-way handshake (SYN → SYN-ACK → ACK) before any data flows. That handshake is bidirectional. A data diode blocks it immediately.
Beyond TCP, each protocol has its own bidirectional requirements at the application layer. This is where protocol break and reconstruct comes in — the technique that makes a data diode useful for real-world protocols.
The TX agent on the OT side connects to the real system using the native protocol, completes all bidirectional handshakes locally, collects data, serialises it, and pushes it through the diode as a proprietary unidirectional stream. The RX agent on the IT side takes that stream and reconstructs what appears to be a real server — an OPC UA server with a browsable address space, or an MQTT broker with active topics. IT-side clients connect to these reconstructed mirrors and interact with them normally.
The result: IT-side clients see what appears to be a normal OPC UA server or MQTT broker. They can connect, browse, subscribe, and read. But they cannot write, send commands, or push any data back to the OT network.
Monitoring is preserved. Control is physically impossible.
OPC UA Through a Data Diode #
OPC UA has the most complex session lifecycle of any common OT protocol. Before a single data point arrives, the client and server must complete a multi-step handshake:
sequenceDiagram
participant C as OPC UA Client
participant S as OPC UA Server
C->>S: OpenSecureChannel
S-->>C: Response + Server Certificate
C->>S: CreateSession
S-->>C: Session ID
C->>S: ActivateSession (credentials)
S-->>C: Confirmation
C->>S: Browse Address Space
S-->>C: Available Nodes
C->>S: CreateSubscription
C->>S: CreateMonitoredItems
loop Ongoing
S->>C: Publish (changed values)
C->>S: PublishRequest (keep-alive)
end
Note over C,S: Every step is bidirectional
Every one of these steps requires a response. The diode blocks them all.
How the Gateway Solves It #
The TX agent acts as an OPC UA client on the OT side. It connects to the real OPC UA server on the OT network, browses the address space, subscribes to all relevant nodes, and receives value updates. It then serialises these updates and pushes them through the data diode.
The RX agent reconstructs a mirror OPC UA server on the IT side. This mirror has an identical address space — same node structure, same data types, same values. IT-side clients connect to the mirror server using standard OPC UA clients (UaExpert, WinCC, custom applications) and interact with it normally.
flowchart TB
KEPWARE[OPC UA Server]
TX_C[TX Agent — OPC UA Client]
DIODE[Data Diode]
RX_S[RX Agent — Mirror OPC UA Server]
CLIENT[IT Clients]
KEPWARE <--> TX_C
TX_C --> DIODE
DIODE --> RX_S
RX_S <--> CLIENT
style KEPWARE fill:#2d9c8f,color:#fff
style TX_C fill:#2d9c8f,color:#fff
style DIODE fill:#c0392b,color:#fff
style RX_S fill:#2980b9,color:#fff
style CLIENT fill:#2980b9,color:#fff
What Worked #
- Address space reconstruction was faithful. The mirror server on the IT side had the same node hierarchy, data types, and values as the real OPC UA server. Clients couldn’t tell the difference.
- Subscriptions worked as expected. The TX agent subscribed to all nodes and pushed value changes through the diode. IT-side clients received updates at their configured publishing intervals.
What Was Hard #
Certificate management. OPC UA enforces certificate-based authentication — every client needs a trusted X.509 certificate to connect to a server. With the OPC UA server on the OT side, the TX agent’s certificate had to be added to the server’s trusted client store. On the IT side, destination clients needed to trust the mirror server’s certificate. Getting the certificate chain right on both sides of a diode — where the two networks are physically isolated by design — required careful planning during installation.
Initial address space sync. With tens of thousands of tags, the TX agent had to browse the entire OPC UA address space and subscribe to every node. This took time on first startup. Subsequent startups could use a cached address space, but if the source server’s configuration changed (new tags added), the TX agent needed to detect and sync the changes — either through periodic re-browsing or manual trigger.
Writes are blocked. This is by design, but it means any OPC UA client workflow that involves writing setpoints or calling methods simply doesn’t work through the diode. The IT-side mirror server is read-only. This must be clearly communicated to every team that consumes data from the mirror.
MQTT Through a Data Diode #
MQTT is significantly simpler to handle through a data diode. The protocol has fewer bidirectional dependencies, and the payload is opaque bytes — there’s no complex server state to reconstruct.
But it’s still not trivial. MQTT runs on TCP (bidirectional handshake), and the application layer has its own two-way exchanges:
sequenceDiagram
participant C as MQTT Client
participant B as MQTT Broker
C->>B: CONNECT
B-->>C: CONNACK
C->>B: SUBSCRIBE (topics)
B-->>C: SUBACK
loop Data Flow
B->>C: PUBLISH (message)
C-->>B: PUBACK (QoS 1)
end
loop Keep-Alive
C->>B: PINGREQ
B-->>C: PINGRESP
end
Note over C,B: Connection maintenance is bidirectional
How the Gateway Solves It #
The TX agent acts as an MQTT subscriber on the OT network. It connects to the OT-side broker, subscribes to the relevant topics, and receives all published messages. It then pushes these messages through the data diode.
The RX agent acts as an MQTT publisher on the IT network. It takes the messages received from the diode and republishes them to an IT-side broker. Subscribers on the corporate network connect to the IT broker and receive data as if it came from the original source.
flowchart TB
PUB[OT Publishers]
BROKER_OT[OT MQTT Broker]
TX_S[TX Agent — Subscriber]
DIODE[Data Diode]
RX_P[RX Agent — Publisher]
BROKER_IT[IT MQTT Broker]
SUB[IT Subscribers]
PUB --> BROKER_OT
BROKER_OT --> TX_S
TX_S --> DIODE
DIODE --> RX_P
RX_P --> BROKER_IT
BROKER_IT --> SUB
style PUB fill:#2d9c8f,color:#fff
style BROKER_OT fill:#2d9c8f,color:#fff
style TX_S fill:#2d9c8f,color:#fff
style DIODE fill:#c0392b,color:#fff
style RX_P fill:#2980b9,color:#fff
style BROKER_IT fill:#2980b9,color:#fff
style SUB fill:#2980b9,color:#fff
What Worked #
- Simple and reliable. MQTT’s pub/sub model maps naturally to the unidirectional pattern — publishers on one side, subscribers on the other, diode in between.
- Topic structure preserved. Messages arrived on the IT side with the same topics, payloads, and retained flags as the originals.
What Was Hard #
QoS doesn’t survive the diode. QoS 1 requires a PUBACK from the receiver. QoS 2 requires a four-packet handshake (PUBLISH → PUBREC → PUBREL → PUBCOMP). None of these acknowledgments can traverse the one-way link. In practice, this meant best-effort delivery — the most recent value was always accurate, but intermediate updates could be lost if the link was saturated.
MQTT version mismatch. The Waterfall gateway used MQTT 5.0 by default. When integrating with older brokers running MQTT 3.1.1, the connection would silently fail. The protocol version had to be manually downgraded in the TX agent’s configuration file. This was a small detail, but it caused hours of debugging the first time I encountered it — the TX agent reported no errors, it simply didn’t connect.
One channel per gateway (early versions). In earlier software versions, only one MQTT channel was supported per gateway. If you needed to bridge multiple MQTT brokers, you needed multiple gateways. Later versions resolved this.
OPC UA vs MQTT — Which Is Harder Through a Diode? #
| OPC UA | MQTT | |
|---|---|---|
| Session complexity | High — 6+ step handshake before first data | Low — CONNECT/CONNACK |
| State to reconstruct | Full address space (nodes, types, structure) | Nothing — payload is opaque bytes |
| Certificate management | Required — X.509 on both sides | Optional — username/password or none |
| Data model preserved? | Yes — mirror server is browsable | Yes — topics and payloads pass through |
| What breaks | Writes, methods, certificate trust | QoS guarantees, version mismatches |
| Initial sync time | Minutes (tens of thousands of tags) | Seconds |
| Overall difficulty | Hard | Simple |
Key Takeaways #
-
IEC 62443 SL-4 requires more than firewalls. At the highest security level — protection against state-sponsored threats — the standard calls for hardware-enforced unidirectional data flow. A data diode has no software to exploit.
-
A data diode is hardware. A unidirectional gateway is the complete solution. The diode provides the one-way link. The TX/RX software agents handle the protocol break and reconstruct that makes it useful.
-
OPC UA is the harder protocol to push through a diode. The multi-step session handshake, certificate management, and full address space reconstruction make it significantly more complex than MQTT. But the result — a browsable mirror server that IT clients can’t distinguish from the real one — is worth the engineering.
-
MQTT is the simpler case, but not trivial. QoS guarantees don’t survive the crossing, and version mismatches between MQTT 5.0 and 3.1.1 can cause silent failures.
-
The gap between lab and production is real. Protocols that work perfectly with simulators behave differently with real-world equipment. Vendor-specific implementations, certificate chains, and edge cases only surface in production.
-
Monitoring is preserved. Control is physically impossible. That’s not a limitation — it’s the entire point.