En la practica de hoy vamos a configurar un maestro y esclavo Modbus TCP que se comunican, para después pasar a “espiar” estas comunicaciones mediante Wireshark.

Si queréis un ejemplo donde se usen las comunicaciones serie, aquí Jose Manuel lo hizo hace años.

Espiar comunicaciones Modbus con Wireshark, puede ser de utilidad en entornos donde tenemos que conectarnos a equipos que utilizan este protocolo y que pueden estar conectados a redes con más elementos. Así aseguramos que estamos leyendo y escribiendo del dispositivo que toca.

Esto pone en evidencia la vulnerabilidad de este protocolo, que debido al diseño que tiene desde su origen no se planteó con medidas de cifrado de las comunicaciones ni autenticación. En el siguiente artículo se habla de un Modbus TCP/Seguro, que mejora e implementa cifrado y autenticación mediante TLS.


Indice:


Paso 1: Descargar un Maestro y Esclavo de Modbus

Existen multitud de software proveedores de este servicio, la mayoría de ellos de pago. En nuestro caso vamos a usar la versión de prueba de https://modbustools.com/ que para este ejemplo sencillo nos sirve.

Paso 2: Iniciar las comunicaciones

  • Modbus Slave: Es el esclavo porque será al que le demos órdenes de lectura o escritura. Para ello tenemos que configurar el protocolo a utilizar, en este caso Modbus TCP/IP y el Puerto y dirección del servidor donde queremos que corra.

Aceptamos y ya tiene que estar corriendo, si no había nada sirviendo en dicho puerto.

  • Modbus Poll: será el encargado de hacer las solicitudes de escritura y lectura del esclavo previamente configurado. Simplemente abriéndolo, como ya tiene por defecto el puerto 502 y la misma IP del PC “127.0.0.1” ya se conectará y quedará establecida la conexión.

En la imagen se observa que estamos comunicando bien los valores de los registros configurados. Todos estos registros se pueden ampliar y configurar, pero para el ejemplo nos basta con estos 10.


Paso 3: Analizar las comunicaciones con Wireshark

Es el momento de ponernos a escuchar el canal de comunicaciones y pinchar el tráfico, en este caso con Wireshark.

  • Seleccionamos la tarjeta de red por la cual queremos escuchar. En nuestro caso como estamos comunicando por el propio PC con el que trabajamos, seleccionamos
    Adapter for loopback traffic capture“.
  • Hacemos doble click y nos aparece la siguiente ventana con los paquetes que esta escuchando, filtramos por “Modbus” para ver los paquetes relacionados con este concepto e ir al grano:
  • Vemos que efectivamente hay paquetes intercambiados. Para ver los valores hacemos doble click sobre cualquiera de los paquetes y aparece la siguiente ventana:
  • Hacemos click sobre el desplegable “Modbus” y vemos los mismos valores que tenemos en nuestra comunicación.

Gracias a la herramienta Wireshark que ya viene preparada para interpretar las tramas de Modbus, es muy fácil decodificarlas y poder ver que registros son los que hay.


BONUS TRACK

Una vez tenemos sirviendo los datos Modbus, es muy sencillo generar un maestro Modbus TCP con Python por ejemplo, para leer estos datos. Por supuesto, ahorremos tiempo con la IA.

A continuación un ejemplo realizado con ChatGPT.

import tkinter as tk
from tkinter import ttk
from pymodbus.client import ModbusTcpClient
from pymodbus.payload import BinaryPayloadDecoder

def read_modbus_registers(host, port, unit_id, start_address, count):
    # Crear un cliente Modbus TCP
    client = ModbusTcpClient(host, port=port)

    # Verificar la conexión al servidor Modbus
    if not client.connect():
        print(f"No se pudo conectar al servidor Modbus en {host}:{port}")
        return

    print(f"Conectado al servidor Modbus en {host}:{port}")

    try:
        # Leer los registros de retención
        result = client.read_holding_registers(start_address, count, unit=unit_id)

        # Comprobar si la lectura fue exitosa
        if result.isError():
            print("Error al leer los registros:", result)
        else:
            # Procesar y mostrar los valores leídos en la interfaz gráfica
            for i, reg in enumerate(result.registers):
                reg_label = tk.Label(root, text=f"Registro {start_address + i}: {reg}")
                reg_label.grid(row=i + 1, column=0, padx=10, pady=5)
    except Exception as e:
        print("Ocurrió un error durante la lectura de registros:", str(e))
    finally:
        # Cerrar la conexión
        client.close()
        print("Conexión cerrada")

# Configuración del cliente
modbus_host = '127.0.0.1'  # Dirección IP del servidor Modbus (localhost para pruebas locales)
modbus_port = 502          # Puerto del servidor Modbus
slave_id = 1               # Dirección del dispositivo esclavo Modbus
start_address = 0          # Dirección inicial de los registros
count = 10                 # Número de registros a leer

# Crear la ventana principal de la aplicación
root = tk.Tk()
root.title("Cliente Modbus")

# Etiqueta de encabezado
header_label = tk.Label(root, text="Lectura de Registros Modbus", font=("Arial", 16))
header_label.grid(row=0, column=0, padx=10, pady=10)

# Botón para iniciar la lectura
read_button = tk.Button(root, text="Leer Registros", command=lambda: read_modbus_registers(modbus_host, modbus_port, slave_id, start_address, count))
read_button.grid(row=11, column=0, padx=10, pady=10)

# Iniciar la aplicación
root.mainloop()

Y aquí el resultado, ya tenemos un maestro Modbus gratis!!