1. 工业网络审计产品到底在审什么
去年我接手了一套工业网络审计产品的测试工作,第一反应是这东西跟传统防火墙、IDS应该差不多,后来真正把环境搭起来才发现,完全不是一回事。所谓工业网络审计产品,简单说就是部署在工业控制网络里的“监控+记录”设备,它不阻断流量,但是会把网络里跑的每一个报文解析出来,还原出谁在什么时候对哪台PLC执行了什么操作、读写的是哪个寄存器、数值是多少。一旦出现异常操作或者疑似攻击行为,它能立刻告警并留下完整证据链。
这跟传统IT审计最大的区别在于,工业现场跑的不是HTTP、MySQL,而是Modbus TCP、S7comm、DNP3、IEC 61850这类工控协议。这些协议的特点是结构固定、字段紧凑、很多厂家还在标准之上做了私有扩展,用传统IT安全产品的规则引擎去解析,大概率会把正常流量识别成异常。所以测试这类产品,核心考验的是它对工控协议的解析能力和对工业场景的理解深度。
我梳理了一下,这类产品的功能可以拆成四块:
- 协议识别与深度解析:能认出网络里跑的是哪些工控协议,并把协议头、功能码、数据区拆开,还原成可读的操作记录。
- 资产与通信基线学习:自动发现网络里的PLC、HMI、工程师站,学习它们之间的通信关系,形成白名单基线。
- 异常行为与攻击检测:在基线之上识别异常,比如非授权访问、功能码滥用、寄存器读写越界、频繁重连等。
- 全流量记录与回溯:把原始报文完整留存,支持事后从海量数据里检索某一次操作。
测试工作的难点也恰好在这四块上。协议解析需要对着协议规范逐字节核对,资产识别要在不同厂家的设备混杂环境下验证准确率,异常检测要同时兼顾“漏报”和“误报”,而全流量记录则考验存储和检索性能。任何一个环节出问题,产品拿到现场就是灾难。
所以我的建议是:拿到测试任务后,不要急着打开工具乱发报文,先花一天时间把被测产品的功能边界搞清楚,再对着功能点设计测试用例。后面所有看起来复杂的测试动作,其实都是在回答这四个问题:它认得出协议吗?它能还原操作吗?它能发现异常吗?它存得下查得快吗?
2. 搭建一套可复现的工控协议测试环境
2.1 为什么不能拿生产环境来试
做工业安全产品测试,第一条铁律就是绝对不能用真实的生产线去验证。工业现场对可用性要求极高,一套停机损失就是几十万上百万,而测试工具发出去的畸形报文、风暴流量、异常重连完全不可控,万一触发了PLC的故障保护,后果没人担得起。所以一切测试都必须在实验室环境里模拟。
工业网络审计产品是旁路部署的,它通过交换机镜像口或者TAP分光器获取网络流量,不参与通信链路。这个特性给了测试很大的便利:被测设备的稳定性不影响工业通信本身,反过来工业通信的异常报文也只会被审计设备看到,不会直接打给真实的PLC。但正因为是旁路,测试时就必须额外确认一件事——设备拿到镜像流量后,能否在不影响现有通信的前提下完成解析和记录。我在测试中发现过不止一次,审计设备在高流量下CPU打满,管理口响应迟缓,虽然不影响业务转发,但告警和日志全卡住了,这在现场同样不可接受。
搭建环境的总体思路是:用软件仿真实现场,把PLC、HMI、上位机全部虚拟化或仿真化,让仿真节点之间跑真实协议,然后把审计设备串进镜像链路。
2.2 硬件拓扑与网卡配置
硬件部分我用了三台机器加一台交换机:
- 一台高配工控机装被测审计产品,三张网卡分别接管理口、镜像口、数据口。
- 一台普通PC做攻击与异常流量发生源,系统装了Kali和Windows双系统。
- 一台PC做正常的工控业务仿真机,跑Modbus Slave和KEPServerEX模拟多个PLC点位。
- 一台千兆交换机,配置端口镜像,把业务仿真机的流量镜像给审计设备。
这里最容易踩的坑是网卡混杂模式和Offload卸载。审计产品的镜像口必须开启混杂模式才能收到所有报文,但很多网卡默认开启了TCP校验和卸载、GRO/LRO,会造成抓到的报文被硬件重组,某些畸形报文在应用层根本看不到。测试前先确认被测产品的网卡驱动和抓包配置,如果支持,直接把Offload关掉,否则后续所有畸形报文测试都会得到假阴性结果。
2.3 软件仿真层:协议仿真组合
软件侧我准备了这样一套组合,覆盖了绝大多数工控协议测试需求:
- Modbus Poll / Modbus Slave:Modbus TCP最常用的主站/从站模拟工具,操作简单,点位和寄存器模型配置灵活。
- KEPServerEX:商业级OPC UA/Modbus网关模拟软件,可以同时模拟几十种协议的设备,特别适合做资产发现测试。
- S7comm模拟插件 + 真实S7-1200仿真器:西门子S7协议在工控网络里非常常见,但解析难度也最大,需要专用的仿真环境配合测试。
- DNP3 / IEC 61850模拟器:电力行业协议,做电力场景的审计测试时是刚需。
- Scapy + 自研脚本:构造畸形报文、异常标志位、模糊测试时的主力工具。
环境搭好之后,我先做了一轮“正常通信跑通”的验证:上位机通过Modbus TCP周期性读写PLC寄存器,审计设备能正确识别出协议类型并记录操作日志。这一步如果都不通过,后面的测试全部失去意义。
3. 测试工具链:从抓到构造、从解析到模糊
3.1 Wireshark:不只用来抓包
工控协议测试里Wireshark是绝对的主力。它的价值不只是看报文内容,更重要的是它内置了完整的协议解析器。测试工业审计产品时,我习惯把Wireshark和审计设备接到同一个镜像口,两边同时抓包,这样做有两层意义:
第一,用Wireshark的解析结果作为“标准答案”。审计设备对某条Modbus TCP报文的解析是否准确,直接和Wireshark的解析树逐字段对比,功能码、事务标识符、单元标识符、寄存器地址、值域,一个字段一个字段核对,偏差立现。
第二,用Wireshark的专家信息(Expert Info)功能辅助判断异常。Wireshark会对报文中的异常标志、错误的校验和、重传行为打上标记,这些标记可以直接作为测试预期,帮助验证审计产品的告警规则是否合理。
比如一个经典场景——Modbus TCP的功能码0x2F(读多寄存器)与私有功能码复用时,很多审计产品会误判成未知协议。用Wireshark先确认标准解析结果,再对比审计产品的识别结果,就能快速定位是解析器的问题还是规则的问题。
3.2 Modbus主从站模拟工具的两面性
Modbus Poll和Modbus Slave这对组合非常有意思,它们模拟的是“正常业务”,但在审计产品测试里,它们又天然是制造“合理异常”的工具:人为停掉从站、修改从站地址、切换功能码、突然把所有寄存器数值写成0,都是几秒钟就能完成的操作,测试效率非常高。
我的经验是,主站模拟器除了配置功能码和地址外,要把轮询周期这个参数利用起来。工业现场的正常Modbus通信是有固定节拍的,比如HMI每200毫秒读一次保持寄存器、每500毫秒写一次线圈。审计产品学习到的通信基线就是基于这些节拍。测试时把轮询周期从200毫秒突然改成20秒,或者从20秒突然改成100毫秒,产品的基线学习和异常判定就会受到考验。我在测试中实际验证过,多数产品的基线学习窗口设定为24小时,节拍突变在窗口内会被当作“新基线”接受,不会告警,这在需求层面其实是合理的,但如果产品支持基线对比告警,那么节拍突变就应该是可疑事件。
3.3 Scapy:工控协议的“积木盒”
Scapy是构造任意报文的神器。它虽然不自带完整的Modbus TCP解析器,但可以手工构造数据包的各层头部,灵活度极高。我常用它做三类工作:
畸形字段构造:把Modbus TCP头里的协议标识符改成0xFFFF、把长度字段改成与实际负载不符、把功能码改成0x80(异常响应码)、构造超长数据区,这些都能验证审计产品的容错能力。
重放与篡改:先抓一段正常的Modbus通信,用Scapy把它保存为pcap并重放,或者修改其中某个寄存器的写入值再重放。这能测试审计产品能否识别出重放攻击和伪造指令。
连接信号伪造:构造大量SYN包扫描PLC端口,或者构造恶意TCP连接,验证审计产品能不能从流量里识别出扫描、暴力破解等攻击前兆。
用Scapy测试时有一个特别容易踩的坑:工控协议里很多字段是大小端混合编码的,比如Modbus的数据区是大端(Big-Endian)存放,而一些私有厂家的扩展字段是小端(Little-Endian)。构造报文前一定要先用Wireshark抓一个真实设备的报文,对照字节顺序,否则构造出来的畸形报文可能根本不会触发被测产品的解析逻辑,后续测试也就白做了。
3.4 通用模糊测试工具的借用思路
工控协议模糊测试在专业领域里有很多商业化工具,比如Achilles、ThreatGen,但这类工具价格不菲,而且上手门槛高。在实际测试里,我更推荐用通用模糊测试思路加脚本实现,成本低且可控。
核心思路是:把一份正常报文模板中的某个字段设为变量,按一定策略变化取值,比如一整段寄存器地址从0x0000递增到0xFFFF,功能码遍历0x00到0x7F与0x80到0xFF,数据区随机填充长度递增的字节串。执行过程中观察两件事:一是审计产品有没有崩溃、断流或者CPU异常升高,二是它有没有把畸形报文正确地识别为异常事件。
实测下来,这种轻量模糊测试的发现效率非常高。在一次测试里,我用脚本连续发送了500条长度不一的异常功能码报文,其中大约30条被审计产品标成“未知协议”,20条被标成“协议异常”,剩下几乎全部被直接忽略。产品对异常报文的覆盖率和归类合理性,在这种压力测试下暴露得淋漓尽致。
3.5 工具选型的核心逻辑
工具从来不是越贵越好,关键看你测什么。我的工具选型逻辑按测试目标来分:
| 测试目标 | 首选工具 | 备选方案 |
|---|---|---|
| 协议解析基准 | Wireshark | 协议规范文档 |
| 正常通信模拟 | Modbus Poll / Slave | KEPServerEX, S7仿真器 |
| 异常报构造 | Scapy | Python套接字脚本 |
| 模糊测试 | Scapy + 自研脚本 | 商业模糊测试工具 |
| 攻击场景模拟 | Kali + Nmap | Metasploit |
| 性能压测 | hping3 + Scapy | 商业流量发生器 |
这个表是经过多次测试迭代定下来的。用工具之前先明确测试目标,才不会出现用Modbus Poll去测畸形报文、用Scapy去模拟正常业务这种吃力不讨好的操作。
4. 测试执行的节奏:先正常后异常、先单点后风暴
4.1 正常流量基线先行
任何一轮测试都从“持续正常运行”开始。我先用Modbus Poll作为主站,按照现场常见的轮询周期持续读写从站,同时让审计产品学习基线,这个阶段至少持续两到三个小时。期间我会定期查看审计产品生成的资产列表和通信关系图,确认它能正确识别出主站的IP、从站的IP、使用的协议以及读写方向。
这一步看着简单,却决定了后续异常检测测试的可靠度。如果基线学习阶段产品就连资产都认不全,后面所有“偏离基线”的告警基本没有参考价值。我在一次测试中遇到过产品把同一个PLC的3个IP段误识别成3台独立设备的情况,原因是对VLAN标签的处理有问题,这种问题不先通过基线测试根本发现不了。
正常流量基线测试之后,还要验证产品的存储与检索性能。我连续灌了48小时的模拟业务流量,然后在审计平台上做时间范围查询、IP过滤检索、寄存器操作回溯,记录查询响应时间。这个指标直接影响现场取证体验,很多产品在测试阶段就暴露了大流量下查询超时的问题。
4.2 从单条异常到链路级异常
基线建立后,开始异常检测测试。我习惯从最简单的单条异常报文开始,逐步升级到复杂场景,避免一开始就跑复杂攻击脚本导致结果难以归因。
单条异常:比如向PLC的寄存器写入一个超出工艺范围的超大值,或者向一个不存在的单元标识符发起读请求,验证产品能否精确捕获单条异常并标记风险等级。这个阶段最重要,因为它检验的是产品对“异常”的定义是否清晰。
通信关系异常:模拟一台从未出现过的新设备接入网络,试图访问PLC。验证产品能否根据已学习的通信白名单,识别出非授权访问并告警。
链路层异常:模拟ARP欺骗、MAC地址漂移、VLAN跳跃等二层攻击。工业网络大多是二层扁平结构,这类攻击的实际危害远大于IT网络,因为资产之间基本没有隔离措施。
会话级异常:模拟TCP连接重放、异常断连、频繁重连等行为,验证产品对会话层异常的感知能力。
实际操作中,单条异常测试需要准备详细的异常报文清单,我一般把每个清单项写成表格,包含报文描述、构造工具、发送目标、预期告警、实际结果、结论。表格化能极大提升测试效率,也方便最后写成报告时追溯。
4.3 风暴场景下的性能与告警洪峰
前面都是单点验证,真正贴近现场的是风暴场景。工控网络中带宽虽小但通信密集,一旦出现广播风暴或某个PLC频繁重启,审计设备将面对大量并发的连接建立与断开,同时还要保持告警输出不中断。
我在性能测试里用Scapy同时开了100个线程,每个线程循环发送随机目标地址的Modbus TCP连接请求,给审计产品制造了一个接近真实的连接风暴。同时用iperf3打满镜像口的带宽。结果发现被测产品的告警队列出现了明显的延迟,前端页面刷新要等5秒以上,但后台日志和数据库写入没有丢失。这个结果说明了产品的性能瓶颈在哪里——不是捕获层,而是实时分析加工层。
还有一类风暴是广播风暴。工业网络里STP(生成树协议)、ARP、EtherNet/IP的CIP广播都可能大量存在,我构造了一个持续发送CIP广播报文的场景,验证审计产品能否从海量广播中准确识别出“关键资产通信”的异常。这个测试直接暴露了产品对广播报文的丢弃策略是否合理。
5. 踩坑记录:一次“误报PLC停机”的完整排查链路
5.1 现象描述
有一次测试跑到通信关系异常场景时,审计平台突然弹出一条高优先级告警:1号车间的PLC发生了疑似停机事件,告警来源是检测到该PLC的Modbus TCP长连接被中断且超过30秒没有重新建立。我当时第一反应是模拟器的S7服务可能崩了,检查了Modbus Slave进程,发现运行正常,通信也没有中断。重新查看审计平台,告警确实存在,但时间上对不上——它告警的是1号车间的旧PLC,而我当时操作的设备是2号车间的模拟PLC。
5.2 排查过程
我先把Wireshark的抓包和审计平台的事件记录拉到一起对齐。Wireshark里能看到,1号车间PLC的Modbus TCP连接在告警时间点确实断开了,但断开原因是正常的——模拟器在第5分钟主动执行了一次重启逻辑,10秒后重连成功,而审计平台的告警等了50分钟才弹出来。
这就奇怪了,如果是因为连接断开告警,为什么延迟这么久?如果是因为停机告警,为什么一个10秒的重启会被判定成停机?
我顺着审计平台的事件队列往回查,发现它在告警时间点前后30秒内收到了大量来自我模糊测试脚本的畸形报文。这些报文的目的端口都指向1号车间的PLC,虽然它们的协议解析失败了,但连接跟踪模块还是把每一条畸形TCP连接都记录为“新连接”。由于畸形报文里的瞬时序列号和窗口大小都不正常,连接跟踪模块误判为原有连接被强制重置,从而触发了“连接中断”的判定逻辑。
5.3 根因定位
问题出在产品的连接跟踪机制上。正常Modbus TCP长连接有固定的四元组和连接序号,但我的模糊测试脚本发送的是大量随机源端口、随机序列号的畸形TCP报文,其中一部分恰好与原有连接的源端口相同,连接跟踪模块就认为这是原连接的“重置包”。它在状态表里把原连接标记为CLOSED,但由于我后续不断发送的新报文让状态机产生抖动,最终它等了近50分钟才确认连接已不可恢复,输出停机告警。
这个根因说明被测产品的TCP状态机实现过于激进,把“连接异常”与“设备停机”两个概念混为一谈。一个正常的PLC重启会导致连接中断,但也会在几秒内重新建立连接;而真正的停机是连接完全不恢复。审计产品正确的做法应该是同时关联“连接状态”和“协议心跳”两个维度来做联合判定,而不是只看TCP连接表。
5.4 修复与验证
我把问题反馈给研发后,他们在告警判定逻辑上增加了两个条件:一是保留协议层心跳检测(比如周期性收到Modbus请求即认为设备在线),二是对TCP连接断开事件增加一个二次确认窗口,在窗口内如果检测到同一设备的任何协议报文到达,就不触发停机告警。
修复后我用同样的模糊测试脚本重新跑了一遍,又增加了一个新的验证场景:断开PLC的Modbus TCP服务但保留ICMP ping可达,验证产品不会把“通信服务中断”误报成“设备停机”;再断开整个模拟器的网络,验证真正的设备离线能否被准确识别。两个场景都通过后,这个误报问题才算闭环。
这个坑给我的教训很直接:测试工控审计产品时,不能只关注“能不能告警”,更要关注“告警判定的依据是否合理”。不少产品在规则里写了大量“连接中断即异常”之类的简单逻辑,这类逻辑在IT网络里问题不大,但放到PLC频繁重启、设备偶发断网的工业现场,就是误报制造机。
6. 测试工具的进阶用法与测试铁律
6.1 Wireshark自定义协议解析在测试中的妙用
工控协议测试中遇到的协议经常是厂家私有扩展,Wireshark默认解析器无法识别。这时可以用Wireshark的插件机制,写一个简单的Lua解析器,把报文的二进制结构按厂家协议规范拆开。我实际用过这个方法来验证一款私有协议产品对特定字典字段的解析是否与规范一致。
写Lua解析器的好处是能自动化地逐字段高亮、计算偏移量,测试脚本构造出的报文可以快速用同一套解析器做校验。很多测试人员不知道这个方法,遇到私有协议只能干瞪眼,要么拿十六进制数组硬看,效率极低。学会写Lua解析器,工控协议测试的深度能提升一大截。
6.2 自研报文的“三查三测”
构造畸形报文时,我总结了一套“三查三测”流程,每次都照这个来,几乎没有漏测过。
三查指发送前自查:查IP地址和端口是否按规划填写,查功能码及子功能码是否符合被测产品的支持范围,查长度字段是否与构造的数据一致,这三个字段在工控协议里最容易因机械填充而出错。
三测指发送后的三个必测项:被测产品能否在协议层正确识别报文类型;能否在内容层还原出具体的操作对象和值域;能否在策略层给出合理的风险评级。有些产品协议识别和内容解析都能做,但最终的风险评级全是“未知风险”,这本质上等于没有识别能力,测试时要单独关注。
6.3 测试工控审计产品的四条铁律
最后分享几条我真正在项目里总结出的测试铁律,每一条都对应着真实的血泪教训:
铁律一:不要脱离业务流来测安全。工控审计产品做的是在业务运行中识别异常,测试时必须先建立稳定、持续的正常业务流,再叠加异常流量,否则产品无法区分“新学习的基线”和“真正的异常”。
铁律二:不要只测标准协议不测私有扩展。现场设备厂商多、协议实现杂,私有功能码复用、变长结构、厂商自定义对象非常常见。测试用例里至少要覆盖50%以上的私有扩展场景。
铁律三:不要只看告警数量,要看误报率与漏报率的平衡。我在一项测试中对比过,某产品把告警阈值调低后,确实把所有异常都无遗漏地报了,但误报也从每天4条飙升到每天300多条。工业用户无法承受这种告警噪音,现场值班人员很快会变得对告警麻木。测试时要结合真实的运营场景判断产品的默认策略是否可用。
铁律四:所有告警都要能回溯到原始报文。审计产品最核心的价值是事后取证,如果一条告警无法关联到对应的pcap报文和协议解析详情,那它在工业现场几乎没有意义。这一条在功能测试里一定要专项验证,不能只看告警界面的展示效果。
把工具用好是基础,把测试逻辑想通才是关键。做工业网络审计产品的测试,很多时候拼的不是工具多强大,而是你对工业现场的理解有多深——你越懂PLC的工作方式、越懂现场运维人员的痛点,你设计的用例就越能命中产品的软肋,你的测试报告对研发和客户也越有价值。