OPC UA (Unified Architecture) is the leading platform-independent protocol for industrial data exchange. It connects SCADA systems, MES platforms, HMI panels, historians, and cloud gateways to PLCs, DCS controllers, and edge devices.
OPC UA uses the OPC Binary protocol over TCP on port 4840 (IANA registered as “opc.tcp”). Wireshark decodes every OPC UA service — OpenSecureChannel, CreateSession, Browse, Read, Write, Publish, and more — down to individual node IDs, attribute values, and status codes.
But there are two common problems. First, many OPC UA servers use non-standard ports — Wireshark will not decode them automatically. Second, if the connection is encrypted (which it should be in production), Wireshark shows “UA Secure Conversation Message (encrypted)” and you cannot see the service content without a key log file.
This guide covers capture setup, verified display filters, how to decode both encrypted and unencrypted OPC UA traffic, and how to troubleshoot the most common OPC UA communication problems.
In This Guide
1. How OPC UA Appears in Wireshark
Wireshark decodes OPC UA Binary as a single protocol layer:
| Layer | What It Shows |
|---|---|
| TCP | Port 4840 (default), TCP handshake |
| OpcUa | Message type, service request/response, node IDs, values, status codes |
The Info column shows the OPC UA service name:
HEL - Hello Message
ACK - Acknowledge Message
OPN - OpenSecureChannelRequest
OPN - OpenSecureChannelResponse
MSG - CreateSessionRequest
MSG - CreateSessionResponse
MSG - BrowseRequest
MSG - ReadRequest
MSG - ReadResponse
MSG - CreateSubscriptionRequest
MSG - PublishResponse
CLO - CloseSecureChannelRequest
2. How to Capture OPC UA Traffic
Capture Filter
tcp port 4840
If your server uses a different port:
tcp port 49380
Where to Capture
| Location | When to Use |
|---|---|
| On the OPC UA client machine | See what the client sends and receives |
| On the OPC UA server | See all client connections |
| On a network switch (port mirroring) | Non-intrusive capture between client and server |
3. Decoding OPC UA on Non-Standard Ports
Wireshark decodes OPC UA automatically only on port 4840. Many OPC UA servers use custom ports (e.g., 49380, 48010, 4841, 62541). If your traffic shows as raw TCP:
Fix: Change Preferences
- Go to Edit → Preferences → Protocols → OpcUa
- In the TCP port(s) field, add your port (comma-separated for multiple ports)
- Click OK
Fix: Use “Decode As”
- Right-click a packet on the non-standard port
- Select Decode As…
- Set: Field = TCP port, Value = your port, Current = OpcUa
- Click OK
⚠️ Important: The OPC UA port is found in the server’s endpoint URL. For example,
opc.tcp://192.168.1.50:49380uses port 49380. Always check the endpoint URL first.
4. Display Filters for OPC UA
All filter field names verified against the official Wireshark OpcUa Binary Protocol Display Filter Reference.
Basic Filters
| Filter | What It Shows |
|---|---|
opcua | All OPC UA traffic |
tcp.port == 4840 | All traffic on OPC UA default port |
Message Type Filters
OPC UA uses message types identified by a 3-letter code in the first bytes:
| Filter | What It Shows |
|---|---|
opcua.transport.type == "HEL" | Hello message (connection init) |
opcua.transport.type == "ACK" | Acknowledge message |
opcua.transport.type == "OPN" | OpenSecureChannel request/response |
opcua.transport.type == "MSG" | Service message (Browse, Read, Write, etc.) |
opcua.transport.type == "CLO" | CloseSecureChannel request |
opcua.transport.type == "ERR" | Error message |
Service Filters
Each OPC UA service has a unique ServiceId (numeric NodeId). You can filter by the service name using the Wireshark Info column search, or by ServiceId:
| Service | ServiceId | Common Use |
|---|---|---|
| GetEndpointsRequest | 428 | Discovery — list available endpoints |
| GetEndpointsResponse | 431 | Discovery response |
| OpenSecureChannelRequest | 446 | Establish secure channel |
| OpenSecureChannelResponse | 449 | Secure channel confirmation |
| CreateSessionRequest | 461 | Create a session |
| CreateSessionResponse | 464 | Session confirmation |
| ActivateSessionRequest | 467 | Activate session with credentials |
| ActivateSessionResponse | 470 | Activation confirmation |
| BrowseRequest | 527 | Browse the address space |
| BrowseResponse | 530 | Browse results |
| ReadRequest | 631 | Read node values |
| ReadResponse | 634 | Read results |
| WriteRequest | 673 | Write node values |
| WriteResponse | 676 | Write results |
| CreateSubscriptionRequest | 787 | Create a subscription |
| PublishRequest | 826 | Client requests notifications |
| PublishResponse | 829 | Server sends data changes |
| CloseSessionRequest | 473 | Close the session |
Filter example for WriteRequest:
opcua.ServiceId == 673
Data Filters
| Filter | What It Shows |
|---|---|
opcua.StatusCode | Status code in responses |
opcua.nodeid.string | String NodeId (e.g., tag name) |
opcua.nodeid.numeric | Numeric NodeId |
opcua.AttributeId | Which attribute is being read/written (13 = Value) |
opcua.SecurityPolicyUri | Security policy used |
opcua.EndpointUrl | Endpoint URL in Hello or GetEndpoints |
opcua.ApplicationUri | Application URI of client or server |
opcua.ChannelId | Secure Channel ID |
opcua.TokenId | Security Token ID |
Combination Examples
All Read requests to a specific server:
opcua.ServiceId == 631 && ip.dst == 192.168.1.50
All error messages:
opcua.transport.type == "ERR"
All encrypted messages (cannot see service content):
opcua && !opcua.ServiceId
Failed operations (non-zero status code):
opcua.StatusCode != 0
5. How to Read a Decoded OPC UA Packet
Hello Message
OpcUa Binary Protocol
Message Type: HEL
Chunk Type: F (Final)
Message Size: 61
ProtocolVersion: 0
ReceiveBufferSize: 65535
SendBufferSize: 65535
MaxMessageSize: 16777216
MaxChunkCount: 5000
EndpointUrl: opc.tcp://192.168.1.50:4840
ReadRequest
OpcUa Binary Protocol
Message Type: MSG
ServiceId: ReadRequest (631)
NodesToRead:
NodeId: ns=2; s="Channel1.Device1.Temperature"
AttributeId: Value (13)
ReadResponse
OpcUa Binary Protocol
Message Type: MSG
ServiceId: ReadResponse (634)
Results:
Value: 23.5 (Double)
StatusCode: Good (0x00000000)
SourceTimestamp: 2026-04-10 14:30:15.123
6. What a Healthy OPC UA Session Looks Like
| # | Direction | Info |
|---|---|---|
| 1 | Client → Server | TCP SYN |
| 2 | Server → Client | TCP SYN-ACK |
| 3 | Client → Server | TCP ACK |
| 4 | Client → Server | HEL — Hello (endpoint URL, buffer sizes) |
| 5 | Server → Client | ACK — Acknowledge (negotiated buffer sizes) |
| 6 | Client → Server | OPN — OpenSecureChannelRequest |
| 7 | Server → Client | OPN — OpenSecureChannelResponse |
| 8 | Client → Server | MSG — GetEndpointsRequest |
| 9 | Server → Client | MSG — GetEndpointsResponse |
| 10 | Client → Server | MSG — CreateSessionRequest |
| 11 | Server → Client | MSG — CreateSessionResponse |
| 12 | Client → Server | MSG — ActivateSessionRequest |
| 13 | Server → Client | MSG — ActivateSessionResponse |
| 14 | Client → Server | MSG — BrowseRequest / ReadRequest / CreateSubscriptionRequest |
| … | … | Service calls continue |
| N | Client → Server | MSG — CloseSessionRequest |
| N+1 | Client → Server | CLO — CloseSecureChannelRequest |
The sequence is always: HEL → ACK → OPN → CreateSession → ActivateSession → Services → CloseSession → CLO
7. Decoding Encrypted OPC UA Traffic
OPC UA supports three security modes:
| Security Mode | What Wireshark Shows |
|---|---|
| None | Full decoded service content — all fields visible |
| Sign | Service content visible, but a signature is appended |
| SignAndEncrypt | “UA Secure Conversation Message (encrypted)” — content hidden |
How to Decrypt in Wireshark
OPC UA encryption uses ephemeral symmetric keys derived during the OpenSecureChannel handshake. To decrypt:
Step 1. Set the environment variable OPCUAKEYLOGFILE on the OPC UA client or server machine:
# Linux
export OPCUAKEYLOGFILE=/tmp/opcua_keys.log
# Windows
set OPCUAKEYLOGFILE=C:\temp\opcua_keys.log
The OPC UA stack (if it supports key logging) writes session keys to this file.
Step 2. In Wireshark: Edit → Preferences → Protocols → OpcUa → OPCUA debug file → point to the key log file.
Step 3. Stop capture, save as .pcapng, reopen. Wireshark decrypts the traffic on reload.
⚠️ Note: Not all OPC UA stacks support key logging. Unified Automation SDK and UaExpert support it. Open62541 has partial support. Check your stack documentation. If key logging is not available, temporarily switch to SecurityPolicy None for debugging (do not leave this in production).
UaExpert Built-in Support
UaExpert (free OPC UA client from Unified Automation) has built-in key logging and can inject keys into .pcapng files directly using Wireshark’s editcap tool.
8. Diagnosing Connection and Session Failures
No Connection at All
Filter: tcp.port == 4840
| What You See | Cause | Fix |
|---|---|---|
| TCP SYN, no SYN-ACK | Server offline or port blocked | Check server status. Check firewall for port 4840. |
| HEL sent, ERR received | Server rejected the Hello | Check endpoint URL. Server may not accept the client’s buffer sizes. |
| OPN sent, ERR received | Security policy mismatch | Client and server must agree on SecurityPolicy and MessageSecurityMode. |
Session Creation Fails
Filter: opcua.ServiceId == 461 || opcua.ServiceId == 464
| What You See | Cause | Fix |
|---|---|---|
| CreateSessionResponse with bad StatusCode | Server rejected the session | Check StatusCode for the reason (e.g., BadTooManySessions, BadCertificateInvalid). |
| ActivateSessionResponse with BadUserAccessDenied | Wrong credentials | Check username/password or certificate. |
| ActivateSessionResponse with BadIdentityTokenRejected | Unsupported authentication type | Server may not support anonymous or username/password. Check server security config. |
9. Diagnosing Read and Write Problems
Read Failures
Filter: opcua.ServiceId == 634 (ReadResponse)
Click the ReadResponse and check each result’s StatusCode:
| StatusCode | Meaning | Common Cause |
|---|---|---|
| Good (0x00000000) | Value read successfully | OK |
| BadNodeIdUnknown | Node does not exist | Wrong NodeId string or namespace index |
| BadAttributeIdInvalid | Attribute not supported | Trying to read an attribute the node does not have |
| BadNotReadable | Node is not readable | Access level does not allow reading |
| BadUserAccessDenied | User not authorized | Current session does not have read permission |
Write Failures
Filter: opcua.ServiceId == 676 (WriteResponse)
| StatusCode | Meaning | Common Cause |
|---|---|---|
| BadNotWritable | Node is not writable | Access level is read-only |
| BadTypeMismatch | Wrong data type | Writing a string to a numeric node |
| BadOutOfRange | Value out of allowed range | Value exceeds the configured limits |
10. Diagnosing Subscription and Publish Problems
OPC UA subscriptions let the server push data changes to the client without polling.
No Data Updates
Filter: opcua.ServiceId == 829 (PublishResponse)
| What You See | Cause | Fix |
|---|---|---|
| PublishResponse with no data changes | No values changed since last publish | Normal if nothing changed. Check MonitoredItem sampling interval. |
| No PublishResponse at all | Subscription not created or client not sending PublishRequest | Check CreateSubscriptionResponse for success. Verify client sends PublishRequest. |
| PublishResponse with StatusCode != Good | Subscription error | Check specific error code. May be BadSubscriptionIdInvalid or BadTooManyPublishRequests. |
Publish Timing
OPC UA clients must continuously send PublishRequests to the server. If the client stops sending them, the server stops pushing data. Count the PublishRequests — there should be a steady stream.
Filter: opcua.ServiceId == 826 (PublishRequest)
11. Diagnosing Certificate and Security Issues
Filter: opcua.transport.type == "ERR" or opcua.StatusCode != 0
| Error | Meaning | Fix |
|---|---|---|
| BadCertificateInvalid | Server does not trust the client certificate | Import the client certificate into the server’s trusted store |
| BadCertificateUntrusted | Certificate not in the trust list | Add the certificate to the server’s trust list or PKI store |
| BadCertificateTimeInvalid | Certificate has expired | Renew the certificate |
| BadCertificateHostNameInvalid | Certificate hostname does not match the endpoint | Regenerate the certificate with the correct hostname/IP |
| BadSecurityPolicyRejected | Client’s security policy not supported by server | Check which SecurityPolicies the server supports (GetEndpoints response) |
12. Useful Wireshark Columns for OPC UA Analysis
| Column Title | Type | Field Name |
|---|---|---|
| Service ID | Custom | opcua.ServiceId |
| Status Code | Custom | opcua.StatusCode |
| Channel ID | Custom | opcua.ChannelId |
| Endpoint URL | Custom | opcua.EndpointUrl |
| Delta Time | Custom | frame.time_delta_displayed |
13. Common OPC UA Problems and What They Look Like in Wireshark
| Problem | Wireshark Symptom | Filter |
|---|---|---|
| Server offline | TCP SYN with no SYN-ACK | tcp.flags.syn == 1 && tcp.port == 4840 |
| Wrong port configured | No OPC UA decoding (raw TCP) | Set port in Preferences → Protocols → OpcUa |
| Hello rejected | ERR message after HEL | opcua.transport.type == "ERR" |
| Security policy mismatch | ERR after OPN, or bad StatusCode | opcua.SecurityPolicyUri — compare client vs server |
| Certificate rejected | StatusCode BadCertificateInvalid | opcua.StatusCode != 0 |
| Bad credentials | ActivateSession fails | opcua.ServiceId == 470 — check StatusCode |
| Node not found | ReadResponse with BadNodeIdUnknown | opcua.ServiceId == 634 — check per-result StatusCode |
| Encrypted traffic | “UA Secure Conversation Message (encrypted)” | Load OPCUAKEYLOGFILE in Preferences → Protocols → OpcUa |
| No subscription data | No PublishResponse packets | opcua.ServiceId == 829 |
| Slow response | Large time delta | opcua && frame.time_delta > 2 |
Summary
Wireshark decodes the full OPC UA binary protocol — from Hello/Acknowledge through every service call to CloseSecureChannel.
The key things to remember:
- OPC UA runs on TCP port 4840 by default. Many servers use custom ports — configure them in Preferences → Protocols → OpcUa.
- Use
opcuaas the main display filter - Use
opcua.transport.typeto filter by message type (HEL, ACK, OPN, MSG, CLO, ERR) - Use
opcua.ServiceIdto filter by specific services (631=Read, 673=Write, 829=PublishResponse) - Use
opcua.StatusCode != 0to find all failed operations - Encrypted traffic requires the OPCUAKEYLOGFILE environment variable and key log loading in Wireshark
- The session sequence is always: HEL → ACK → OPN → CreateSession → ActivateSession → Services → Close
- If OPC UA shows as raw TCP, the port is not configured in Wireshark preferences
