Zend certified PHP/Magento developer

modbus traffic on wire shark

I am tinkering with some modbus python scripts to try and learn it but I cant seem to capture traffic on wireshark. Can a Modbus client and server both run localhost on the same computer listening on the same TCP port 502? Or would they have to be on separate machines?

All running local host a client and server scripts based on pyModbusTCP which is surprisingly easy getting this up and working on Python 3.9 Windows 10.

These two scripts are from the examples of the pyModbusTCP repo I am just running them locally on my Windows 10 machine to see if I can view the traffic on wireshark. Pip install the package and this code will work:

client.py

from pyModbusTCP.client import ModbusClient
import time

c = ModbusClient(host="localhost",
                 port=502,auto_open=True,
                 auto_close=False)


# main read loop
while True:
    # read 10 bits (= coils) at address 0, store result in coils list
    coils_l = c.read_coils(0, 10)

    # if success display registers
    if coils_l:
        print('coil ad #0 to 9: %s' % coils_l)
    else:
        print('unable to read coils')

    # sleep 2s before next polling
    time.sleep(2)

server.py

import argparse
from pyModbusTCP.server import ModbusServer, DataHandler
from pyModbusTCP.constants import EXP_ILLEGAL_FUNCTION


# some const
ALLOW_R_L = ['127.0.0.1', '192.168.0.10']
ALLOW_W_L = ['127.0.0.1']


# a custom data handler with IPs filter
class MyDataHandler(DataHandler):
    def read_coils(self, address, count, srv_info):
        if srv_info.client.address in ALLOW_R_L:
            return super().read_coils(address, count, srv_info)
        else:
            return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)

    def read_d_inputs(self, address, count, srv_info):
        if srv_info.client.address in ALLOW_R_L:
            return super().read_d_inputs(address, count, srv_info)
        else:
            return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)

    def read_h_regs(self, address, count, srv_info):
        if srv_info.client.address in ALLOW_R_L:
            return super().read_h_regs(address, count, srv_info)
        else:
            return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)

    def read_i_regs(self, address, count, srv_info):
        if srv_info.client.address in ALLOW_R_L:
            return super().read_i_regs(address, count, srv_info)
        else:
            return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)

    def write_coils(self, address, bits_l, srv_info):
        if srv_info.client.address in ALLOW_W_L:
            return super().write_coils(address, bits_l, srv_info)
        else:
            return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)

    def write_h_regs(self, address, words_l, srv_info):
        if srv_info.client.address in ALLOW_W_L:
            return super().write_h_regs(address, words_l, srv_info)
        else:
            return DataHandler.Return(exp_code=EXP_ILLEGAL_FUNCTION)


if __name__ == '__main__':
    # parse args
    parser = argparse.ArgumentParser()
    parser.add_argument('-H', '--host', type=str, default='localhost', help='Host (default: localhost)')
    parser.add_argument('-p', '--port', type=int, default=502, help='TCP port (default: 502)')
    args = parser.parse_args()
    # init modbus server and start it
    server = ModbusServer(host=args.host, port=args.port, data_hdl=MyDataHandler())
    server.start()

On Wireshark am definitely a newbie here but selecting my ethernet adapter there is definitely traffic:
enter image description here

Then attempting to filter for modbus tcp.port 502 nothing comes up…any ideas to try?
enter image description here

The scripts appear to be working as client script console prints:

coil ad #0 to 9: [False, False, False, False, False, False, False, False, False, False]
coil ad #0 to 9: [False, False, False, False, False, False, False, False, False, False]
coil ad #0 to 9: [False, False, False, False, False, False, False, False, False, False]