This tool aims to replay OPCUA packets by simulating the sequence of events from a Wireshark capture
When customers raise issues, it is hard to replay the same process that caused an issue like a PLC crash for example. Therefore, this python script aims to take in a Wireshark capture, along with a PLC that already has the application that caused the issue downloaded, and simulate the whole process through
- Creating an OPCUA client and making a successful connection
- Then, follow the sequence of wireshark capture opcua packets and their request parameters to send to the PLC.
asyncua (for replay_asyncua) (V1.1.0)
opcua (for the deprecated version) (V0.98.13)
pyshark (V0.6)
datetime
time
re
itertools
- In order to make the
asyncua
library work for our use case, please "disable" the watchdog which will keepAlive by sending Read Requests constantly. To "disable", go to the asyncua library source code in your local machine,import math
and initializeasyncua.client.Client
class'sself.watchdog_intervall = math.inf
, this will cause the keepAlive to send read requests every interval of infinite seconds.
A shortcut to this step is to write import asyncua.client.Client
then ctrl + click onto that, then you'll be able to view the source codes.
- Ensure that the application to debug is INSTALLED into the PLC using ESME, in order to simulate the same scenario in the PLC.
I would recommend using this program as it uses asyncua, and has more "functionalities" like different packet cases as compared to deprecated_version.py
I have used the synchronous version of this library as it makes things more straightforward.
- Initialize a ReplayHandler
RH = ReplayHandler("<PATH TO WIRESHARK CAPTURE>", "opc.tcp://<IP address of PLC>", None)
time.sleep(2)
- Start the replay
RH.start() # start the replay from start to finish of the whole wireshark capture
- Loop
RH.loop(looping_time="0W;0D;0H;30M;0S;", snippet_start=31, snippet_end=None)
# looping time must be specified in a specific format, go to the function definition to read on how
# snippet_start is the start of the loop, meaning which packet do you want to start your loop with
# snippet_end None means till the end, otherwise, it specifies the packet that it ends with (inclusive!)
- Disconnect
RH.disconnect() # handles deletion of subscription and disconnection with PLC
There are some packets that cannot be simulated using the deprecated opcua
library, for example:
- ModifySubscriptionRequest
- SetPublishingMode
Publish Responses to Publish Requests from the opcua
library, will cause some sort of BadSequenceNumberUnknown ua error, that's why asyncua
is better, as it fixes this bug
Also, there isn't any community support for this library.
The way to call the functions is similar to the one in replay_asyncua.py
There was prior research and failures before this project. To read more about how it led to the current method of replaying, it's on the confluence blog. :)
- The time release control is yet to be implemented, meaning, each packet, is released at a set timing instead of following the time from the Wireshark capture
- Might be met with BadTooManySubscriptions ua exception, more needs to be researched into to amend this. Maybe add a check to see whether objects have already been subscribed.