Modbus TCP, Python, and Security: My Hands-On Experiment
Building a Modbus TCP Client with Python: A Fun and Practical Learning Experience


Introduction
In my journey to expand my Python skills, I recently built a Modbus TCP client from scratch. This project was both a practical learning exercise and an eye-opener to industrial automation protocols and network security concerns. In this blog post, I’ll walk you through how I created a simple Modbus TCP client, used ModbusPal to simulate a server, and even analyzed Modbus TCP traffic using Wireshark.
Additionally, I’ll touch on the security risks associated with Modbus TCP communication and how attackers could potentially manipulate industrial controllers. If you're interested in Python, networking, or industrial cybersecurity, this post is for you!
Getting Started: What is Modbus TCP?
Modbus TCP is a communication protocol commonly used in industrial control systems (ICS) and SCADA environments. It allows a client (master) to read from or write to registers and coils on a Modbus-compatible device (slave) over a TCP/IP network.
Since Modbus TCP does not use encryption or authentication, anyone who can intercept the network traffic can read and manipulate register values, which can pose serious security risks in industrial environments if you happen to have an attacker in the ICS/OT network.
Step 1: Setting Up the Environment
To build my Modbus TCP client and to analyze the traffic, I used:
Python 3
pymodbus – A Python library for Modbus communication
ModbusPal – A Java-based Modbus TCP server simulator
Wireshark – A network traffic analysis tool
Installing pymodbus
Before diving into the code, I set up my Python environment and installed the necessary dependencies. See code snippet below under the pymodbus tab.
If you’re using a virtual environment (which I highly recommend), create and activate one before installing pymodbus. To make this process easier I used pycharm, by using pycharm you can simply open terminal within pycharm and run pip3 install pymodbus within this terminal and it is automatically installed in your virtual environment.
Step 2: Running a Modbus TCP Server (ModbusPal)
Since I didn’t have access to a real Modbus device (and I didn't want to use the PLC/PFC I use to develop for my company - for obvious reasons !), I used ModbusPal to simulate a Modbus TCP server (slave). Here’s how:
Download ModbusPal from ModbusPal Official Repository.
Run it using Java:
Step 3: Building a Basic Modbus TCP Client
I started by creating a simple Python script to read and write Modbus registers. Here’s the basic structure:
Step 4: Expanding Functionality
I later expanded the script to handle multiple Modbus function codes, including:
Reading Data
01 - Read Coils
03 - Read Holding Registers
Writing Data
05 - Write Single Coil
06 - Write Single Holding Register
0F - Write Multiple Coils
10 - Write Multiple Holding Registers
Example of writing a single register:
Step 5: Making It Interactive
To improve the usability of the script, I implemented an interactive mode, allowing users to dynamically enter commands to read and write values in a loop:
This made it possible to change values on the fly, making the script more user-friendly.
Step 6: Analyzing Modbus TCP Traffic with Wireshark
One of the most interesting parts of this project was using Wireshark to analyze Modbus TCP traffic.
I ran Wireshark in the background while executing my script.
I filtered packets using: [modbus] as the search filter.
I observed that all data was sent in clear text—no encryption or security mechanisms!
Security Concerns
Since Modbus TCP lacks security features, a malicious actor could:
Eavesdrop on Modbus traffic, revealing register values.
Send unauthorized commands to manipulate industrial equipment (e.g., setting registers to zero, causing system shutdowns).
Exploit default TCP ports (502) if they are publicly accessible.
To mitigate risks:
Use a firewall rules to restrict Modbus TCP access.
Implement network segmentation to isolate control systems. IT network should never be allowed to talk to ICS/OT network.
Consider migrating to secure alternatives, like Modbus Secure (which supports TLS encryption), in cases where this is absolutely needed. In most cases it is not used or not desirable to encrypt ICS/OT communication traffic.
Conclusion
Building a Modbus TCP client in Python was a rewarding experience. Not only did I strengthen my Python skills, but I also gained valuable insights into industrial protocols and network security risks.
If you’re interested in learning more about Python, Modbus, and Cybersecurity, continue to follow my journey here. I next want to expand my current python code to possibly add a user interface. Then I am planning on creating a simulated client/server environment, using a virtual pfSense router in-between and simulating a possible intruder (attacker) in a ICS/OT plant trying to sniff for Modbus TCP traffic.
Oh, and before you go—if you're looking for a cool Python-themed mouse pad, check out my Amazon affiliate link here. Your support helps me keep learning and sharing!