目标

本文档用于指导在 Linux 环境下完成以下工作:

  • 使用 tcpdump 抓取 Modbus TCP 通信报文
  • 使用 Wireshark 对抓到的 .pcap.pcapng 文件进行分析
  • 通过一个完整的 Modbus 读寄存器示例,掌握请求与响应的拆解方法
  • 快速定位通信失败、超时、异常码、地址错误、寄存器数量错误等问题

本文重点面向 Modbus TCP 场景,即通过 TCP 端口 502 进行通信的情况。


适用场景

以下情况都适合使用本文档的方法:

  • EMS 与 PLC、PCS、BMS、电表、保护装置之间的 Modbus TCP 联调
  • 现场设备“能连通但读不到数据”的问题排查
  • 核对主站下发的寄存器地址、功能码、寄存器数量是否正确
  • 分析从站返回异常码的具体原因
  • 复盘偶发超时、重传、断链、错误响应等网络问题

环境准备

建议准备以下工具:

  • Linux 主机一台
  • tcpdump
  • Wireshark
  • 被抓包的 Modbus TCP 通信链路
  • 具备 sudo 权限的账号

Ubuntu / Debian 可参考:

sudo apt-get update
sudo apt-get install -y tcpdump wireshark

安装完成后可确认版本:

tcpdump --version
wireshark --version

如果当前用户无权限直接打开抓包文件或使用抓包能力,可临时通过 sudo 执行抓包命令。


整体流程

整个操作流程建议按下面顺序执行:

  1. 确认通信网卡、对端 IP、TCP 端口
  2. 使用 tcpdump 抓取 Modbus TCP 报文到文件
  3. 用 Wireshark 打开抓包文件
  4. 使用显示过滤器筛选目标流量
  5. 对照 Modbus 报文字段逐项分析
  6. 根据现象判断是网络问题、协议问题还是业务配置问题

步骤一:确认抓包对象

抓包前,先确认以下信息:

  • 本机使用的是哪块网卡
  • Modbus 对端 IP 是多少
  • 是否确实走 TCP 端口 502
  • 抓包点位于主站侧、从站侧,还是中间交换网络

1. 查看本机网卡

ip -br addr

在这里插入图片描述

如果机器有多张网卡,务必确认哪块网卡承载了现场业务流量。

2. 查看抓包接口列表

sudo tcpdump -D

在这里插入图片描述

输出中通常会列出类似 eth0ens33enp3s0bond0any 等接口名称。

3. 确认 Modbus 连接是否存在

ss -ant | grep ':502'

如果已经建立连接,通常能看到:

  • 客户端临时端口 -> 服务端 502
  • ESTAB 状态表示 TCP 已建立

在这里插入图片描述


步骤二:使用 tcpdump 抓取 Modbus TCP 报文

1. 最常用抓包命令

sudo tcpdump -i eth0 -nn -s 0 -w modbus_tcp.pcap 'tcp port 502'

参数说明:

  • -i eth0:指定抓包网卡,请替换为现场实际网卡
  • -nn:不做主机名和端口名解析,避免输出被解析结果干扰
  • -s 0:抓取完整报文,不截断
  • -w modbus_tcp.pcap:将数据写入文件,供 Wireshark 打开
  • 'tcp port 502':只抓取 Modbus TCP 常用端口数据

2. 抓指定主机与端口

如果只想抓某个设备与本机之间的 Modbus 报文:

sudo tcpdump -i eth0 -nn -s 0 -w modbus_192.168.1.10.pcap 'host 192.168.1.10 and tcp port 502'

3. 抓双向通信并保留完整上下文

若现场可能存在建链失败、重传、RST、异常关闭等情况,建议抓整个会话,而不是只抓应用层片段:

sudo tcpdump -i eth0 -nn -s 0 -w modbus_full_session.pcap 'host 192.168.1.10'

这样在 Wireshark 中可以同时看到:

  • TCP 三次握手
  • Modbus 请求与响应
  • 重传、乱序、RST、FIN

4. 长时间抓包建议

如果现场问题偶发,建议使用轮转文件,避免单文件过大:

sudo tcpdump -i eth0 -nn -s 0 -C 100 -W 10 -w modbus_ring.pcap 'tcp port 502'

参数说明:

  • -C 100:单个文件达到 100 MB 后切换
  • -W 10:最多保留 10 个文件,循环覆盖

5. 抓包结束

抓包过程中按 Ctrl + C 停止。结束时 tcpdump 会输出抓到的数据包统计信息。

在这里插入图片描述

步骤三:使用 Wireshark 打开抓包文件

抓包完成后,启动 Wireshark 并打开文件:

wireshark modbus_tcp.pcap

在这里插入图片描述

也可以直接启动 Wireshark 后,通过图形界面打开抓包文件。

打开后,界面通常分为三部分:

  • 数据包列表区:展示时间、源地址、目的地址、协议、长度、摘要信息
  • 协议树详情区:逐层展开 Frame、Ethernet、IP、TCP、Modbus 等字段
  • 字节区:展示原始十六进制内容,并高亮当前选中字段

在这里插入图片描述


步骤四:在 Wireshark 中过滤 Modbus 报文

Wireshark 分为两类过滤:

  • 抓包过滤器tcpdump 执行时使用,决定“抓什么”
  • 显示过滤器:Wireshark 中使用,决定“看什么”

本文主要关注 Wireshark 的显示过滤器。

1. 显示所有 Modbus 报文

modbus

如果 Wireshark 已正确识别协议,这个过滤器最直接。
在这里插入图片描述

2. 按 TCP 端口过滤

tcp.port == 502

在这里插入图片描述

3. 按 IP 地址过滤

ip.addr == 192.168.3.23

在这里插入图片描述

4. 只看某个方向

ip.src == 192.168.1.100 && ip.dst == 192.168.1.10 && tcp.port == 502

在这里插入图片描述

这个过滤器适合只看主站请求,或只看从站响应。

5. 只看异常与网络问题

tcp.analysis.retransmission
tcp.flags.reset == 1
modbus || tcp.analysis.retransmission || tcp.flags.reset == 1

6. 端口不是 502 时的处理方法

有些测试环境不会使用标准端口 502。如果 Wireshark 没有自动识别成 Modbus,可手动指定:

  1. 选中对应 TCP 报文
  2. 菜单进入 Analyze -> Decode As...
  3. 在对应 TCP 端口上选择 Modbus/TCP
  4. 应用后再使用 modbus 过滤

步骤五:结合示例分析 Modbus 报文

下面用一个典型的 读取保持寄存器 示例说明如何分析。

示例场景

  • 主站 IP:192.168.1.100
  • 从站 IP:192.168.1.10
  • TCP 端口:502
  • 单元标识符(Unit ID):1
  • 功能码:0x03,读取保持寄存器
  • 起始地址:0x0000
  • 读取数量:1

1. 请求报文示例

十六进制内容如下:

00 21 00 00 00 06 01 03 00 00 00 01

拆解如下:

字节位置字段含义
0-1Transaction Identifier0x0021事务标识,用于请求响应匹配
2-3Protocol Identifier0x0000Modbus TCP 固定为 0
4-5Length0x0006后续字节长度
6Unit Identifier0x01设备地址 / 单元标识
7Function Code0x03读取保持寄存器
8-9Starting Address0x0000起始地址
10-11Quantity0x0001读取 1 个寄存器

分析结论:

  • 这是一个标准的 Modbus TCP 读保持寄存器请求
  • 主站要求从地址 0 开始读取连续 1 个寄存器
  • Transaction Identifier1,后续响应通常会保持一致

在这里插入图片描述


2. 响应报文示例

十六进制内容如下:

00 21 00 00 00 05 01 03 02 70 f8

拆解如下:

字节位置字段含义
0-1Transaction Identifier0x0021与请求匹配
2-3Protocol Identifier0x0000固定为 0
4-5Length0x0005后续字节长度
6Unit Identifier0x01单元标识
7Function Code0x03响应功能码,与请求一致
8Byte Count0x02返回 4 个字节数据
9-10Register 00x0070十进制 112
11-12Register 10x00f8十进制 248

分析结论:

  • 响应与请求事务号一致,说明配对正确
  • 返回了 2 个寄存器,共 4 字节,和请求数量一致
  • 两个寄存器的值分别为 100200

在这里插入图片描述


3. 如何在 Wireshark 中看懂这类报文

分析时建议按下面顺序看:

  1. 先看 TCP 层
    • 是否成功三次握手
    • 是否有重传、RST、乱序、零窗口
  2. 再看 MBAP 头
    • Transaction Identifier 是否能和响应匹配
    • Protocol Identifier 是否为 0
    • Length 是否合理
    • Unit Identifier 是否符合设备配置
  3. 最后看 Modbus PDU
    • 功能码是否正确
    • 起始地址是否正确
    • 寄存器数量是否超限
    • 返回字节数是否与寄存器数量一致

如果 Wireshark 协议树能正确展开,一般说明 TCP 层和 Modbus 报文结构至少基本可解析。


4. 异常响应示例

若从站不支持请求的功能、地址错误或数量越界,常见会返回异常响应。例如:

00 03 00 00 00 03 01 83 02

拆解如下:

字段含义
Transaction Identifier0x0003与请求配对
Unit Identifier0x01单元标识
Function Code0x83异常响应,0x80 + 0x03
Exception Code0x02非法数据地址

说明:

  • 正常功能码是 0x03
  • 异常响应时功能码最高位置位,因此变成 0x83
  • 0x02 常表示寄存器地址不存在、越界,或设备不支持该地址范围

常见异常码

异常码名称常见原因
0x01Illegal Function功能码不支持
0x02Illegal Data Address地址错误、寄存器不存在、地址越界
0x03Illegal Data Value数量、值或参数非法
0x04Slave Device Failure从站内部处理失败

步骤六:定位常见问题

下面给出现场最常见的几类现象以及对应排查思路。

1. 看不到任何 Modbus 报文

排查方向:

  • 抓错网卡
  • 流量不经过当前主机
  • 端口不是 502
  • 防火墙或交换机策略限制
  • 通信根本没有发起

建议操作:

sudo tcpdump -i any -nn -s 0 -w test_any.pcap host 192.168.1.10

先放宽过滤条件确认有没有相关主机流量,再逐步收窄。

2. 能看到 TCP 建链,但没有 Modbus 数据

排查方向:

  • 应用程序连接成功但未发请求
  • 上层程序卡住或等待条件未满足
  • 使用了非 Modbus 协议
  • 端口被复用,但协议不是 Modbus

建议在 Wireshark 中观察:

  • TCP 三次握手之后是否出现 PSH, ACK
  • 载荷是否能被 Decode As Modbus/TCP

3. 有请求,无响应

排查方向:

  • 从站未收到请求
  • 从站收到但未处理
  • 网络单向不通
  • 中间设备丢包
  • 从站处理超时

重点看:

  • 请求发出后是否有 TCP 重传
  • 是否有 ICMP 不可达
  • 是否最终收到 RST

4. 响应是异常码

排查方向:

  • 功能码不支持
  • 寄存器地址写错
  • 地址基准错位
  • 读取数量超限
  • 单元标识符配置错误

工业现场很常见的问题是:

  • 文档地址从 40001 开始描述,但程序里直接用了协议地址 0
  • 或者相反,设备要求协议地址,主站却把文档地址直接发下去了

因此要特别确认:

  • 设备手册中的地址是 协议地址
  • 还是 人类可读的数据模型地址

5. Wireshark 能解包,但数值不对

排查方向:

  • 寄存器高低位组合方式不对
  • 多寄存器拼接时字序不同
  • 设备手册定义的是有符号数,程序按无符号解释
  • 缩放比例未处理,例如真实值为“寄存器值 / 10”

这类问题通常不是网络故障,而是 协议解释或点表配置问题

6. 报文正常,但业务仍报超时

排查方向:

  • 应用层超时时间设置过短
  • 程序在等待错误的事务号
  • 多线程并发访问同一连接导致响应配对错乱
  • 上层日志记录时间与抓包时间不一致

建议同时核对:

  • 程序日志时间
  • 抓包时间戳
  • Transaction Identifier
  • 同一 TCP 流中的请求响应顺序

推荐抓包命令模板

模板 1:标准 Modbus TCP 抓包

sudo tcpdump -i eth0 -nn -s 0 -w modbus_tcp.pcap 'tcp port 502'

模板 2:抓指定设备

sudo tcpdump -i eth0 -nn -s 0 -w modbus_device.pcap 'host 192.168.1.10 and tcp port 502'

模板 3:抓完整会话

sudo tcpdump -i eth0 -nn -s 0 -w modbus_full.pcap 'host 192.168.1.10'

模板 4:长时间轮转抓包

sudo tcpdump -i eth0 -nn -s 0 -C 100 -W 10 -w modbus_ring.pcap 'tcp port 502'

模板 5:先粗抓、后精看

sudo tcpdump -i any -nn -s 0 -w all_traffic.pcap host 192.168.1.10

适合一开始不确定端口、协议、网卡或方向时使用。


最佳实践

  • 抓包时优先使用 -s 0,避免报文被截断
  • 尽量抓到完整会话,包括 TCP 握手和断开过程
  • 抓包文件命名建议包含设备 IP、时间、问题现象
  • 问题偶发时优先使用轮转抓包
  • 分析时先看网络层是否通,再看 Modbus 协议字段是否正确
  • 不要只看“有没有响应”,还要核对响应是不是匹配的事务号
  • 如果端口不是 502,记得在 Wireshark 中使用 Decode As
  • 对照设备手册时,务必确认地址基准和数据类型定义

推荐命名格式:

modbus_192.168.1.10_2026-04-17_读寄存器超时.pcap

附录:常见 Modbus 功能码

功能码名称说明
0x01Read Coils读线圈
0x02Read Discrete Inputs读离散输入
0x03Read Holding Registers读保持寄存器
0x04Read Input Registers读输入寄存器
0x05Write Single Coil写单个线圈
0x06Write Single Register写单个寄存器
0x0FWrite Multiple Coils写多个线圈
0x10Write Multiple Registers写多个寄存器

总结

使用 tcpdump + Wireshark 分析 Modbus TCP 的核心思路可以概括为三句话:

  1. 先确认流量到底有没有到达
  2. 再确认 Modbus 报文字段到底是不是按协议发送
  3. 最后确认业务点位解释是否和设备手册一致

只要把 网卡、IP、端口、事务号、功能码、地址、数量、异常码 这几个关键点按顺序核对,绝大多数 Modbus TCP 问题都可以较快定位。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐