ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Wireshark抓包分析ModbusTCP:从报文到故障排查实战

2026/9/19 0:46:20 拓冰建站 浏览量
Wireshark抓包分析ModbusTCP:从报文到故障排查实战 1. 工控现场为什么要盯着ModbusTCP的报文看干工控这行的多少都遇到过这种场景PLC和上位机之间数据对不上触摸屏显示的值跟实际传感器差了一大截或者某个写线圈的指令发下去设备纹丝不动。这时候你翻代码、查配置、重启设备折腾半天可能一点头绪都没有。问题往往就藏在网络报文里——指令到底发出去没有发出去的字节序对不对从站有没有正常回应这些光看应用层日志根本看不出来。ModbusTCP这个协议在工业现场太常见了走的是标准以太网默认端口502。它的报文结构本身不复杂但正因为简单很多细节容易被忽略。比如功能码和寄存器地址的对应关系、事务标识符的匹配、异常码的含义这些东西在调试的时候如果手里没有一份完整的报文记录基本就是盲人摸象。Wireshark作为一款通用的网络协议分析工具恰好能把ModbusTCP的每一帧报文拆解得清清楚楚从TCP握手到Modbus PDU每一层都能看到原始字节和解析结果。这篇文章面向的是需要在现场排查ModbusTCP通信问题的工程师、做设备联调的技术人员以及刚接触工控协议分析的新手。我会从抓包环境的搭建讲起把Wireshark针对ModbusTCP的过滤、解析、统计功能逐一拆开再结合几个典型的故障场景把报文级别的排查思路讲透。中间会穿插一些我实际踩过的坑比如抓不到包、解析乱码、时间戳对不上这些问题怎么处理。看完之后你应该能独立完成一次完整的ModbusTCP通信抓包分析并且能从报文里读出设备到底在干什么。2. 抓包前的环境准备与工具选型2.1 Wireshark版本选择与安装要点Wireshark的版本迭代挺快的但工控现场用的电脑往往系统比较老不一定能跑最新版。我的建议是如果是在Windows 7或者Windows Server 2008这类老系统上抓包选Wireshark 3.6.x这个长期支持版本比较稳妥它对老系统的兼容性经过大量验证。如果是Windows 10/11或者主流Linux发行版直接上最新的稳定版就行新版本对Modbus协议的解析字段更全比如对Modbus over TCP的单元标识符处理更准确。安装的时候有一个关键点Npcap驱动。Wireshark在Windows上抓包依赖这个驱动安装向导里会默认勾选。但要注意如果你机器上已经装过WinPcap得先卸掉两者会冲突。另外Npcap安装时有个选项叫Restrict Npcap drivers access to Administrators only如果勾上了普通用户权限启动Wireshark会看不到网卡列表。现场调试经常是用普通账号登录的所以这个选项建议不要勾或者直接用管理员身份运行Wireshark。Linux环境下就简单多了apt install wireshark或者yum install wireshark安装过程中会提示是否允许非root用户抓包选是就行。如果选否后面每次抓包都得sudo比较麻烦。2.2 抓包位置的选择逻辑抓包位置决定了你能看到什么。ModbusTCP的通信路径通常是上位机/SCADA → 交换机 → PLC/从站设备。如果你在上位机本机抓包看到的是本机网卡进出的流量适合排查上位机发出的指令是否正确。如果在交换机上做端口镜像能看到多个设备之间的完整对话适合分析主从站交互过程。如果是在PLC侧抓包那看到的是从站视角的报文适合确认从站是否收到了请求。现场最常用的方式是在上位机或者工程师笔记本上直接抓。把笔记本接到交换机的空闲口配置一个同网段的IP然后抓包。这时候有个坑交换机的端口镜像没配好的话你只能看到广播包和自己网卡的流量。ModbusTCP是单播通信如果镜像没做你根本看不到上位机和PLC之间的报文。所以抓包之前一定要确认镜像配置正确或者干脆把笔记本串在通信链路中间做透明桥接。还有一种情况是抓本机回环流量。比如上位机和Modbus模拟器跑在同一台机器上通信走的是127.0.0.1。Wireshark在Windows上默认抓不到回环包需要装Npcap的时候勾选Support loopback traffic选项或者用\Device\NPF_Loopback这个接口。Linux下直接抓lo接口就行。2.3 网卡与抓包选项配置选好网卡之后Wireshark的抓包选项里有几个参数值得注意。混杂模式默认是开的这个模式会让网卡接收所有经过它的帧即使目标MAC不是自己。在端口镜像场景下混杂模式必须开否则只能收到发给本机的单播。抓包缓冲区默认2MB长时间抓包的话建议调到64MB甚至更大避免缓冲区满了丢包。实时更新选项在抓包时能看到报文滚动但会消耗一些性能如果抓包速率很高可以关掉。还有一个容易被忽略的抓包过滤器。这是BPF语法的过滤器在抓包之前就生效只抓符合条件的包。比如tcp port 502就只抓ModbusTCP的流量。这个过滤器能大幅减少抓到的数据量尤其是在网络里还有其他协议在跑的时候。但要注意BPF过滤器写错了会导致一个包都抓不到而且Wireshark不会报错只是静默地什么都不显示。所以写完过滤器之后先确认一下有没有报文进来。3. ModbusTCP协议在Wireshark里的解析机制3.1 ModbusTCP报文结构回顾ModbusTCP的报文是在TCP payload里承载的结构分两部分MBAP头和PDU。MBAP头固定7个字节包含事务标识符2字节、协议标识符2字节、长度2字节、单元标识符1字节。PDU就是功能码加数据比如读保持寄存器是功能码0x03后面跟起始地址和寄存器数量。Wireshark内置了Modbus/TCP的解析器默认情况下只要TCP端口是502它就会自动按Modbus协议解析。解析结果会显示在报文详情面板里展开Modbus/TCP这一层就能看到各个字段的值。但这里有个细节如果ModbusTCP跑在非标准端口上比如有些设备用5020或者1502Wireshark不会自动识别需要手动配置。方法是右键报文 → Decode As → 选择Modbus/TCP或者直接在首选项里添加端口映射。3.2 关键字段的解读方法事务标识符是排查请求响应匹配问题的关键。主站每发一个请求事务标识符会递增或者随机生成从站的响应必须带回相同的事务标识符。如果抓包看到请求和响应的事务标识符对不上说明有报文错位或者设备实现有问题。协议标识符在ModbusTCP里固定是0如果不是0说明这个报文可能不是标准的ModbusTCP或者是被其他协议封装了。单元标识符在串口时代用来区分从站地址在TCP里通常用于区分网关后面的多个从站。如果现场用了Modbus网关一个IP对应多个串口从站那单元标识符就很重要了。Wireshark会把单元标识符显示出来分析的时候要结合网关的配置来看。功能码和异常码是判断操作结果的核心。正常响应里功能码和请求一致异常响应里功能码的最高位会置1比如0x03变成0x83后面跟一个异常码字节。常见的异常码有01非法功能、02非法数据地址、03非法数据值、04从站设备故障。Wireshark会直接显示异常码的文字描述不用去翻协议文档。3.3 解析器配置与自定义Wireshark的Modbus解析器有一些可配置项在首选项 → Protocols → Modbus/TCP里。比如可以设置是否解析Modbus RTU over TCP是否显示原始字节是否把寄存器值按有符号/无符号/浮点数解析。这些选项在分析特定设备的时候很有用。比如有些设备把两个寄存器拼成一个32位浮点数Wireshark默认按16位整数显示看起来就是两个莫名其妙的数字。这时候可以在解析器里配置浮点解析或者用自定义的Lua插件来处理。如果Wireshark自带的解析器不够用还可以写Lua脚本扩展。比如某些设备在标准ModbusTCP基础上加了自定义的功能码Wireshark会显示成Unknown function code这时候写个简单的Lua dissector就能把自定义字段解析出来。这个后面在实操部分会详细讲。4. 实操从抓包到分析的完整流程4.1 抓包过滤器的编写与验证打开Wireshark选好网卡在抓包过滤器栏里输入tcp port 502然后点开始。这时候如果网络里有ModbusTCP流量应该能看到报文在滚动。如果什么都没看到先检查几个点网卡选对没有镜像配置对不对BPF过滤器有没有写错。可以先把过滤器清空看看有没有任何流量确认网卡是通的。抓包过滤器除了按端口过滤还可以按IP过滤。比如host 192.168.1.100 and tcp port 502只抓跟这个IP相关的ModbusTCP流量。如果现场有多个主站可以用ip src 192.168.1.100来区分方向。BPF语法支持逻辑运算符and、or、not可以组合使用写复杂过滤器的时候注意优先级必要时加括号。提示抓包过滤器在抓包过程中不能修改要改的话得停止抓包重新开始。所以开始抓包之前最好把过滤条件想清楚避免抓了一堆无关数据。4.2 显示过滤器的灵活运用抓完包之后面对成千上万条报文得用显示过滤器来筛选。Wireshark的显示过滤器语法比BPF更丰富支持协议字段级别的过滤。针对ModbusTCP常用的显示过滤器有modbus所有ModbusTCP报文modbus.func_code 3只显示功能码为3的报文modbus.func_code 0x83只显示功能码3的异常响应modbus.reference_num 100只显示起始地址为100的报文tcp.flags.reset 1只显示TCP复位报文这些过滤器可以组合比如modbus.func_code 3 modbus.reference_num 100精确找到对地址100的读保持寄存器操作。显示过滤器支持自动补全输入modbus.之后会弹出所有可用字段不用死记硬背。还有一个很实用的技巧右键报文 → Apply as Filter → Selected可以直接把选中的字段值作为过滤条件。比如选中一个事务标识符右键应用为过滤器就能看到这个事务的所有相关报文。4.3 报文追踪与对话分析Wireshark的Follow TCP Stream功能可以把一个TCP连接的所有报文按顺序拼起来显示原始的应用层数据。对于ModbusTCP来说这个功能能看到完整的请求响应序列但因为是原始字节可读性不如协议解析视图。更推荐的是用Conversations视图在Statistics → Conversations → TCP标签页里能看到所有TCP连接的统计信息包括每个连接的报文数、字节数、持续时间。找到端口502的连接右键 → Follow Stream就能看到这个连接的完整对话。对于ModbusTCP还有一个更专业的分析方式用tshark命令行工具做批量分析。tshark是Wireshark的命令行版本可以在没有图形界面的服务器上跑也适合做自动化分析。比如要统计所有功能码3的请求数量可以用tshark -r capture.pcap -Y modbus.func_code 3 -T fields -e modbus.reference_num -e modbus.word_cnt | sort | uniq -c这条命令会读出pcap文件过滤出功能码3的报文提取起始地址和寄存器数量然后统计每个组合出现的次数。对于分析设备的轮询模式特别有用。4.4 时间戳与响应时间分析ModbusTCP的性能问题往往体现在响应时间上。Wireshark默认显示的是相对时间可以在View → Time Display Format里改成Seconds Since Beginning of Capture或者Time of Day。要分析请求到响应的延迟可以手动计算两个报文的时间差也可以用Wireshark的Time Shift功能。更高效的方式是用tshark提取时间戳然后做统计分析。比如要找出响应时间超过100ms的请求tshark -r capture.pcap -Y modbus -T fields -e frame.time_relative -e ip.src -e modbus.func_code -e modbus.transaction_id把输出导入到Excel或者用Python脚本处理就能算出每个请求的响应延迟分布。我实际用这个方法发现过好几次PLC响应慢的问题最后定位到是某个寄存器的读取触发了从站内部的慢速操作。5. 典型故障场景的报文级排查5.1 请求发出但无响应的排查思路这是现场最常见的问题上位机日志显示指令已发送但设备没反应。抓包一看请求报文确实发出去了但没有任何响应报文回来。这时候要分几步排查先确认请求报文本身有没有问题。检查MBAP头的长度字段是否和实际PDU长度匹配如果长度字段写错了从站可能会直接丢弃报文。检查功能码和寄存器地址是否在从站支持的范围内如果地址越界从站应该返回异常码02但如果从站实现不规范可能直接不响应。再确认网络层是否可达。看TCP握手有没有完成如果TCP连接都没建立那Modbus请求根本发不出去。如果TCP连接建立了但请求发出去没响应可能是从站的TCP缓冲区满了或者从站处理不过来。这时候可以看TCP的窗口大小和重传情况。还有一种情况是请求发到了错误的单元标识符。如果现场用了Modbus网关单元标识符决定了请求转发到哪个串口从站。如果单元标识符配错了网关可能直接丢弃报文不会有任何响应。5.2 异常码的解读与处理当从站返回异常响应时Wireshark会显示异常码。常见的几个异常码含义可能原因01非法功能从站不支持该功能码或功能码被禁用02非法数据地址寄存器地址超出从站支持范围03非法数据值写入的值超出允许范围04从站设备故障从站内部错误需要检查设备状态05确认从站已接受请求正在处理中06从站设备忙从站正在处理长任务暂时无法响应异常码02和03在调试阶段最常见通常是上位机的寄存器映射表跟实际设备对不上。异常码04一般是设备本身的问题比如传感器故障或者内部逻辑错误。异常码06在设备执行耗时操作时会出现比如某些PLC在做批量写入的时候会返回忙。5.3 数据错位的字节序问题Modbus协议规定寄存器是16位大端序但有些设备实现的时候用了小端序或者把32位浮点数拆成两个寄存器的时候顺序搞反了。抓包的时候看到原始字节Wireshark默认按大端序解析如果设备实际是小端序显示的值就是错的。比如一个32位浮点数1.0大端序字节是3F 80 00 00小端序是00 00 80 3F。如果Wireshark按大端序解析成两个16位整数会显示16384和0看起来完全不对。这时候需要手动计算或者用Wireshark的解析器配置把字节序改过来。排查字节序问题的时候可以先用一个已知的值做测试。比如写入一个特定的整数然后抓包看原始字节对比设备的实际响应就能确定设备的字节序。5.4 网络层问题的识别有时候ModbusTCP的问题不在应用层而在网络层。比如TCP重传、乱序、重复ACK这些都会影响Modbus通信的稳定性。Wireshark的专家信息Expert Information功能会自动标记出这些异常在Analyze → Expert Information里可以看到。如果看到大量的TCP Retransmission说明网络有丢包或者拥塞。ModbusTCP对延迟比较敏感重传会导致响应时间大幅增加。如果看到TCP Zero Window说明接收方缓冲区满了发送方需要暂停发送。这种情况在从站处理能力不足的时候会出现。还有一种情况是TCP连接被意外复位。如果看到RST报文说明有一方主动断开了连接。可能是上位机的连接池管理逻辑有问题也可能是从站的TCP栈有bug。这时候要结合应用层的日志一起分析。6. 进阶技巧与效率提升6.1 用tshark做批量自动化分析tshark的强大之处在于可以脚本化。比如要每天定时抓包并生成报告可以写一个shell脚本#!/bin/bash tshark -i eth0 -f tcp port 502 -a duration:3600 -w /tmp/modbus_$(date %Y%m%d_%H%M).pcap tshark -r /tmp/modbus_$(date %Y%m%d_%H%M).pcap -Y modbus.func_code 0x83 -T fields -e ip.src -e modbus.exception_code | sort | uniq -c这个脚本抓一个小时的包然后统计异常响应的来源和类型。对于长期监控Modbus通信质量的场景很实用。tshark还支持自定义输出格式-T fields -e可以指定要提取的字段-E separator,可以指定分隔符方便导入到数据库或者Excel。如果要提取Modbus的寄存器值可以用modbus.regval_uint16字段。6.2 自定义Lua解析器处理私有协议有些设备在标准ModbusTCP基础上做了扩展比如自定义功能码或者私有数据格式。Wireshark默认解析不了这些会显示成未知功能码。这时候可以写一个Lua dissector来解析。一个简单的Lua dissector示例local modbus_custom Proto(modbus_custom, Modbus Custom Protocol) local f_func ProtoField.uint8(modbus_custom.func, Function Code, base.HEX) local f_data ProtoField.bytes(modbus_custom.data, Data) modbus_custom.fields { f_func, f_data } function modbus_custom.dissector(buffer, pinfo, tree) local subtree tree:add(modbus_custom, buffer()) subtree:add(f_func, buffer(0,1)) subtree:add(f_data, buffer(1)) end local tcp_port DissectorTable.get(tcp.port) tcp_port:add(502, modbus_custom)这个脚本把端口502的流量用自定义解析器处理。实际使用的时候要根据设备的协议文档来调整字段定义。Lua脚本放在Wireshark的插件目录下重启Wireshark就能生效。6.3 长时间抓包的策略现场排查偶发问题的时候可能需要抓几个小时甚至几天的包。长时间抓包有几个注意点文件大小限制Wireshark可以配置自动分割文件比如每100MB换一个文件避免单个文件过大打不开。环形缓冲区配置多个文件循环覆盖只保留最近的抓包数据。抓包过滤器尽量缩小抓包范围只抓必要的流量减少磁盘占用。在Linux下还可以用tcpdump做长时间抓包它对系统资源的占用比Wireshark小。命令示例tcpdump -i eth0 -w /tmp/modbus.pcap -C 100 -W 10 tcp port 502这个命令每100MB换一个文件最多保留10个文件循环覆盖。抓完之后用Wireshark打开分析。6.4 常见问题速查问题现象可能原因排查方法抓不到任何包网卡选错、镜像未配、过滤器错误清空过滤器看是否有流量只能看到广播包交换机镜像未配置检查镜像配置或改用串接方式Modbus解析显示为TCP端口非502手动Decode As Modbus/TCP寄存器值显示异常字节序问题对比原始字节和实际值请求响应事务ID不匹配设备实现问题或报文错位检查事务ID字段大量TCP重传网络丢包或拥塞检查网络质量和设备负载抓包文件打不开文件过大或损坏用editcap分割或修复时间戳不准确系统时间未同步抓包前同步NTP注意抓包分析只是手段最终目的是解决问题。不要陷入为了抓包而抓包的误区明确排查目标之后再动手效率会高很多。7. 几个我实际踩过的坑第一个坑是Npcap和杀毒软件的冲突。有些现场电脑装了某款杀毒软件会把Npcap的驱动当成可疑程序拦截导致Wireshark能启动但看不到网卡。解决办法是把Npcap的安装目录加到杀毒软件的白名单里或者临时关闭杀毒软件再安装。第二个坑是抓包过滤器和显示过滤器搞混。抓包过滤器是BPF语法显示过滤器是Wireshark自己的语法两者不通用。我见过有人把modbus.func_code 3写到抓包过滤器里结果一个包都抓不到。记住抓包过滤器只能用tcp port 502这种BPF语法协议字段级别的过滤要用显示过滤器。第三个坑是时间戳的时区问题。Wireshark默认显示的是本地时间但如果抓包文件和设备日志的时区不一致对时间的时候会很痛苦。建议在抓包之前确认所有设备的时间同步或者统一用UTC时间。第四个坑是大文件分析的内存问题。几个GB的抓包文件直接打开会吃掉大量内存机器配置不高的话会卡死。这时候可以用editcap先分割文件或者用tshark做命令行分析避免打开图形界面。第五个坑是Modbus网关的单元标识符。有一次现场调试上位机发的单元标识符是1但网关配置的是把单元标识符1映射到串口2而实际设备接在串口1上。抓包看到请求发出去了网关也转发了但设备没响应。后来查网关配置才发现映射关系搞错了。这种问题光看Modbus报文看不出来得结合网关的配置一起分析。8. 从报文到结论的思维路径抓包分析的核心不是工具用得多熟练而是能不能从报文里读出设备的行为逻辑。我一般的分析路径是这样的先看TCP层有没有异常握手是否正常有没有重传和复位。然后看Modbus层请求和响应是否配对事务标识符是否一致功能码和地址是否合理。最后看数据层寄存器的值是否符合预期字节序有没有问题。这个过程听起来简单但实际操作的时候需要耐心和细心。有时候一个偶发问题要抓很多次包才能复现有时候报文里的一个字节差异就是问题的根源。工具只是辅助真正值钱的是对协议的理解和排查问题的经验。如果你刚开始接触ModbusTCP抓包建议先在一个简单的环境里练手比如用Modbus模拟器加Wireshark自己发请求看报文。熟悉了标准流程之后再到现场去处理实际问题。现场环境复杂得多但有了扎实的基础排查起来就不会慌。