
这次我们来看一个 OT/ICS 安全训练数据集项目。它目前开放了 5% 的公开样本并且这些样本带有 provenance也就是可追溯的来源信息。和普通抓包数据集不同这类数据不只是丢给你一堆 pcap 或日志而是会在元数据里说明采集场景、设备类型、攻击注入方式和标签定义。对做工控安全研究的人来说这个特点非常关键因为很多公开数据集无法复现论文结果根源就在于来源信息缺失。如果你正在搭工控网络入侵检测、做异常检测算法评估或者只是想给安全分析课程找一套可用的上课数据这个 5% 公开样本值得先下载下来验证一遍。本文会围绕这套数据做完整梳理先做核心能力评估再讲数据目录结构与溯源字段接着是本地下载校验和 Python 环境准备然后给出数据质量检查、模型基线和批处理自动化脚本最后补充常见问题排查和数据使用合规建议。先给一个总体判断这个公开样本的主要价值不在“量大”而在“可评估、可复现、可接入实验流程”。你不需要一开始就去申请完整数据集先把 5% 样本放进自己的数据处理流程里跑通再决定是否值得投入更多资源。1. 核心能力速览能力项说明数据领域OT/ICS 安全训练数据集公开规模5% 公开样本适合先期评估溯源信息带 provenance 元数据覆盖场景、采集方式、标签来源等数据形态以实际发布说明为准通常包含流量记录、日志或特征表主要用途入侵检测、异常检测、安全研究、教学复现硬件要求基础分析通常无需 GPUCPU 8GB 内存可完成样本处理启动方式不需要常驻服务主要做离线文件读取与脚本分析接口 API不确定需以项目说明为准可通过脚本封装本地分析接口批量能力可批量解析 pcap、批量提取特征、批量评测多个模型适合用户工控安全研究员、算法工程师、蓝队成员、安全课程教师从这张表可以看出这个项目与普通的网络流量数据集有三个明显区别。第一定位明确是面向 OT/ICS 安全训练的不是一堆通用抓包文件。第二带溯源信息样本来源、采集方式、标签归属都有说明。第三公开 5% 样本的目的就是让研究者先评估数据质量再决定是否使用完整数据。这个模式对选型、评测和论文复现都比较友好。需要说明的是表格中有些字段在拿到实际项目发布说明之前是不确定的例如数据形态、是否提供 API、文件体积等。在后续操作中我们必须以实际发布的 README、数据字典和授权声明为准不要假设所有 OT/ICS 数据集都长成同一个样子。2. 适用场景与使用边界2.1 适合谁用如果你属于下面几类人这个 5% 公开样本值得花时间跑一遍。第一类是工控安全研究人员正在找带场景标注的数据集做异常检测算法验证第二类是算法工程师需要评估 OT 流量数据和 IT 流量数据在特征分布上的差异第三类是蓝队或安全运营人员想验证现有 IDS 规则在工业协议场景下的召回情况第四类是高校教师或培训讲师需要一套带说明文档的数据用于实验教学。对这几类人来说公开样本最大的价值是先花少量时间确认数据质量。数据格式是否兼容你的 pipeline、标签是否够细、协议类型是否覆盖目标场景这些都不需要完整数据集就能确认。2.2 不适合什么场景如果只做传统 IT 网络入侵检测这套 OT/ICS 数据未必合适。工业控制系统里的协议结构、流量周期性、设备 IP 固定程度都和企业办公网差异很大模型迁移时通常需要重新微调。如果要做实时在线检测平台数据集本身只提供离线训练和验证不直接提供实时推理框架需要自己搭服务。如果对数据量有硬性指标5% 样本可能不够完成大规模预训练只能作为一轮快速验证。2.3 安全与合规边界OT/ICS 数据往往来自电力、水务、制造等关键工业场景使用时有几个底线必须守住。第一确认数据集授权条款不要超出允许范围使用或二次分发。第二即使是公开样本也只用于防御技术研究、检测模型训练和教学演示不应用于任何攻击真实工控系统的用途。第三如果样本中包含设备 IP、拓扑关系、时间特征等敏感字段实验报告、论文和博客中都要避免直接泄露可识别信息。第四研究过程中遇到疑似真实环境信息不要尝试反向定位或触碰生产系统。3. 数据资产清单与目录结构拿到数据集之后第一步不是急着写模型而是先建立对数据资产的全局认识。从公开数据集的常见组织方式看目录结构通常会按“原始数据、处理后特征、标签文件、元数据、工具脚本”分层。下面是一个通用示例结构实际项目请以发布说明为准。ot_ics_dataset_5pct/ ├── README.md ├── data/ │ ├── raw/ │ │ ├── sample_01.pcap │ │ ├── sample_02.pcap │ │ └── ... │ ├── processed/ │ │ └── features.csv │ └── labels/ │ └── labels.csv ├── meta/ │ ├── provenance.json │ └── data_dictionary.csv └── tools/ ├── parse_pcap.py ├── analysis.ipynb └── requirements.txt其中meta/provenance.json是这个数据集的特色它记录每个样本的来源场景、采集设备和标签规则。拿到这个文件后建议优先读一遍因为它直接决定了数据能不能用于你的实验场景。比如一场水处理仿真平台采集的数据和一套真实变电站旁路镜像的数据两者特征分布会差很多。meta/data_dictionary.csv是字段字典建议同时打开。字段字典通常会说明每一列的含义、类型和取值范围。没有字段字典时标签文件里很容易出现模棱两可的字段名光靠猜会浪费很多时间。4. 下载校验与环境准备4.1 下载前确认下载之前先确认两件事。第一项目发布页是否提供了校验和SHA256 或 MD5。如果提供下载后必须做校验避免拿到损坏文件。第二确认样本包内是否包含 pcap 原始流量。如果包含你的环境里需要安装 tshark 或准备 scapy如果只有处理好的 CSV那环境准备可以更轻量。4.2 完整性校验下载完成后先用校验命令确认文件没有损坏。Linux 或 macOS 下使用 sha256sumWindows 下使用 certutil。# Linux / macOS 校验 SHA256 sha256sum ot_ics_sample_5pct.zip # 与发布页给出的 SHA256 值对比:: Windows 校验 SHA256 certutil -hashfile ot_ics_sample_5pct.zip SHA256如果校验值不一致先不要解压。优先用支持断点续传的工具重新下载下载完成后再次校验。确认一致后再进入解压步骤。4.3 Python 环境准备数据分析和模型训练建议使用 Python 3.8 或更高版本。为了不污染系统环境推荐先创建虚拟环境再安装依赖。基础依赖包括 pandas、numpy、scikit-learn如果涉及 pcap 解析建议安装 scapy 或使用 tshark。# 创建并激活虚拟环境 python -m venv .venv source .venv/bin/activate # Windows 使用 .venv\Scripts\activate # 安装基础依赖 pip install pandas numpy scikit-learn scapy安装完成后把当前环境的依赖版本记录到 requirements.txt。这一步对后续复现实验很关键OT/ICS 数据集本来就是面向可复现研究的如果依赖版本漂移实验结果很难对比。pip freeze requirements.txt4.4 磁盘空间与内存5% 公开样本的体积通常不大但解压后如果包含 pcap 文件磁盘占用可能比压缩包大 3 到 5 倍。处理前先查看解压目录大小。# 查看解压后目录占用空间 du -sh ot_ics_dataset_5pct内存方面如果只是用 pandas 读取标签文件做分布统计2GB 内存就够如果要把 pcap 全部解析成特征并载入 DataFrame建议至少准备 8GB 内存。深度学习和 Transformer 类模型并不在这个样本验证的第一优先级里因为先用浅层模型跑通流程更重要。5. 数据质量检查与样本验证5.1 目录结构确认解压后先跑一遍目录检查确认所有关键文件都存在。如果文件缺失需要回到发布页看清楚是不是分卷下载或需要额外申请。目录检查可以手工完成也可以用脚本自动对比。import os from pathlib import Path required [ README.md, meta/provenance.json, meta/data_dictionary.csv, data/labels/labels.csv, ] for item in required: p Path(item) if p.exists(): print(f[OK] {item}) else: print(f[MISSING] {item})5.2 标签分布统计标签文件是判断数据可用性的第一站。用 pandas 读取后先看前几行再统计标签和攻击类型分布。import pandas as pd # 按实际文件路径调整 labels pd.read_csv(data/labels/labels.csv, encodingutf-8) print(labels.head()) print(labels[label].value_counts()) print(labels[attack_type].value_counts(dropnaFalse))这里需要特别关注两类结果。第一正常流量和攻击流量的比例是否极度不均衡。如果攻击样本占比过低后续训练时要考虑重采样或改用异常检测模型。第二attack_type 字段是否覆盖你关心的攻击类型比如扫描侦察、拒绝服务、命令注入、重放攻击等。覆盖率不足时样本只适合做通用基线不适合做特定场景评测。5.3 流量样本协议分布如果数据集包含 pcap 文件值得用 tshark 看一下协议分布。OT 场景里常见的协议包括 Modbus/TCP、DNP3、OPC UA、S7comm、EtherNet/IP 等混在 TCP/IP 流量中。用 tshark 可以快速统计协议类型。# 查看 pcap 中的协议统计 tshark -r data/raw/sample_01.pcap -q -z io,phs如果要提取具体字段用于特征工程可以用 tshark 将 pcap 转成 CSV。# 将 pcap 转成 csv 特征字段按需要保留 tshark -r data/raw/sample_01.pcap -T fields \ -e frame.time_epoch -e ip.src -e ip.dst \ -e tcp.srcport -e tcp.dstport -e tcp.flags \ -e udp.srcport -e udp.dstport \ -E headery -E separator, data/processed/sample_01_features.csv这个命令是通用模板实际字段名以 tshark 支持范围为准。如果样本里包含非 IP 流量比如某些工业总线上直接是 MAC 层通信需要根据数据字典确认是否要保留链路层信息。5.4 样本可用性判断标准完成前面三个检查后可以按下面四个维度判断样本是否值得继续投入第一字段字典和标签文件能对上列名没有歧义。第二正常与攻击样本的比例在可处理范围内或者不均衡程度可控。第三协议类型覆盖目标场景至少包含你要研究的主要工业协议。第四provenance 元数据足够详细能支撑论文或实验报告中的场景描述。如果四个维度都基本满足就可以放心进入特征工程和模型基线阶段。如果某一项明显缺失建议先调整实验预期或者联系数据集发布方确认完整版是否包含更全的字段。6. 用公开样本搭建检测模型基线6.1 特征思路OT/ICS 流量检测的特征通常围绕流量会话和协议行为构建。常见特征包括包长度统计、到达时间间隔、TCP 标志位分布、源端口/目的端口组合、会话持续时长、双向包数与字节数。如果样本里已经提供处理好的特征表可以直接从特征表开始跳过 pcap 解析这一步。有一点需要特别注意不要直接把时间戳、设备 IP、会话 ID 这类高基数标识列放进模型否则容易出现数据泄漏导致指标虚高。时序类任务中如果按随机方式划分训练集和测试集某些时间特征会让模型记住“某个时间段等于某种攻击”这对真实场景没有任何意义。更稳妥的做法是按时间顺序划分或者至少在做特征选择时排除时间标识字段。6.2 加载数据示例假设你已经把 pcap 转换成了features.csv并且标签文件中包含session_id、label等字段。加载和合并的示例代码如下。import pandas as pd features pd.read_csv(data/processed/features.csv) labels pd.read_csv(data/labels/labels.csv) # 合并确保 id 对齐 df features.merge(labels, onsession_id, howinner) print(df.shape) print(df[label].value_counts())实际操作中字段名不一定叫session_id可能叫flow_id、conversation_id或conn_id需要以数据字典为准。6.3 随机森林基线先用浅层模型跑通流程再考虑深度模型。随机森林对表格型特征比较稳定训练速度快也容易解释。下面是一个通用训练模板。import pandas as pd from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report features pd.read_csv(data/processed/features.csv) labels pd.read_csv(data/labels/labels.csv) df features.merge(labels, onsession_id, howinner) drop_cols [session_id, timestamp_start, timestamp_end] drop_cols [c for c in drop_cols if c in df.columns] X df.drop(columnsdrop_cols [label, attack_type]) y df[label] X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42, stratifyy ) model RandomForestClassifier(n_estimators100, random_state42, n_jobs-1) model.fit(X_train, y_train) print(classification_report(y_test, model.predict(X_test)))如果样本量很大可以先跑n_estimators50验证流程再调大。如果类别不均衡严重可以在RandomForestClassifier中设置class_weightbalanced或者训练后使用 PR 曲线、F1-score 而不是只看准确率。6.4 模型评测注意事项评测时最容易犯的错是只看 accuracy。正常流量在 OT 场景里通常占多数一个把所有样本都判为正常的“模型”也可能有很高的准确率但没有检测能力。建议至少输出混淆矩阵、precision、recall、F1-score 四个指标。如果攻击类别不止一种还要分别查看每个攻击类别的召回率避免某一类攻击被完全忽略。在时间维度上如果原始数据包含连续采集的多个时间片随机划分训练集和测试集会比较乐观。更接近真实部署的评测方式是前 70% 时间片训练后 30% 时间片测试或者按轮次分折。具体怎么切分要根据数据的时间跨度决定不能盲目套模板。7. 批处理、自动化与性能观察7.1 批量解析 pcap公开样本通常包含多个 pcap 文件手工一个个跑 tshark 效率太低。写一个批处理脚本对目录下所有 pcap 文件执行解析、输出 CSV、记录日志并在失败时跳过继续处理。import os import glob import logging import subprocess from pathlib import Path logging.basicConfig( filenamebatch_process.log, levellogging.INFO, format%(asctime)s %(levelname)s %(message)s, ) RAW_DIR Path(data/raw) OUT_DIR Path(data/processed) OUT_DIR.mkdir(parentsTrue, exist_okTrue) pcap_files sorted(glob.glob(str(RAW_DIR / *.pcap))) for pcap in pcap_files: out_csv OUT_DIR / (Path(pcap).stem _features.csv) if out_csv.exists(): logging.info(fskip existing: {out_csv}) continue cmd [ tshark, -r, pcap, -T, fields, -e, frame.time_epoch, -e, ip.src, -e, ip.dst, -e, tcp.srcport, -e, tcp.dstport, -e, udp.srcport, -e, udp.dstport, -E, headery, -E, separator,, ] try: with open(out_csv, w, encodingutf-8) as f: result subprocess.run( cmd, stdoutf, stderrsubprocess.PIPE, textTrue, timeout600 ) if result.returncode ! 0: logging.error(fparse failed: {pcap}, stderr: {result.stderr[:200]}) else: logging.info(fparsed: {pcap} - {out_csv}) except subprocess.TimeoutExpired: logging.error(ftimeout: {pcap}) except Exception as e: logging.error(funexpected error: {pcap}, {e})这个脚本里的字段列表是示例实际需要根据数据字典和 tshark 字段名调整。批量处理时建议开启日志因为 pcap 解析可能遇到编码问题、截断文件、超时等意外情况没有日志很难排查。7.2 本地 API 封装如果之后想把训练好的模型暴露给其他工具可以用 Flask 封装一个本地推理接口。注意这不是数据集自带的 API只是通用实践。import pandas as pd from flask import Flask, request, jsonify import joblib app Flask(__name__) model joblib.load(model/rf_baseline.joblib) app.route(/predict, methods[POST]) def predict(): data request.get_json() features pd.DataFrame([data[features]]) prob model.predict_proba(features)[0].tolist() return jsonify({probabilities: prob}) if __name__ __main__: app.run(host127.0.0.1, port8080)调用时建议只绑定 127.0.0.1不要暴露公网避免未授权访问。如果后续要接入到安全分析平台可以在接口前面加一层鉴权。7.3 性能观察这套样本的基础分析以 CPU 和内存为主。解压阶段看磁盘 IO解析 pcap 阶段看 CPU 和磁盘载入 CSV 和训练模型阶段看内存。用系统自带的性能工具就能观察。# Linux 查看 CPU 和内存占用 top -o %MEM # 实时刷新 htop # Windows 任务管理器可以直接看内存和磁盘使用解析 pcap 时如果 CPU 占用跑满说明可以并行。并行解析最简单的方式是按文件拆成多个进程每个进程处理一个 pcap避免同一文件内过度拆分导致顺序错乱。如果内存不足优先检查是否把不必要的字段都载入了比如原始负载、超大字符串列等。只保留数值型特征和类别型特征可以有效降低内存占用。8. 常见问题与排查方法问题现象可能原因排查方式解决方案下载文件校验和不一致网络传输中断或源文件更新对比发布页 SHA256 或 MD5重新下载优先使用断点续传工具解压报错压缩包损坏或磁盘空间不足检查磁盘剩余空间释放空间后重新解压标签文件读取乱码编码与默认设置不一致用编辑器查看文件头编码指定 encodingutf-8 或 gbkpcap 解析极慢文件过大或字段过多观察单文件解析耗时用 tshark 过滤器按协议过滤并行处理内存不足一次性载入过多流量数据观察任务管理器或 htop 内存占用分块读取只保留必需字段转 parquet类别严重不均衡攻击样本偏少打印 label 和 attack_type 计数重采样、设置类别权重改用异常检测模型模型指标异常高时间戳、设备IP等字段进入特征检查特征列是否存在高基数标识列移除无关高基数列按时序划分数据代码运行缺少依赖未激活正确 Python 环境执行 pip list 检查包按 requirements.txt 安装想要完整数据集但申请被拒授权条件不满足阅读授权条款联系发布方确认用途在允许范围内再申请遇到问题时最忌讳直接怀疑数据集本身有问题。大部分情况是环境、编码或字段理解不一致导致的。先看日志再复现最小样例能大幅缩短排查时间。9. 最佳实践与合规建议9.1 工程化建议第一建立清晰的目录分层。建议将“原始数据区、处理脚本区、特征输出区、模型结果区”分开不要把原始 pcap 和中间特征混在一个目录里。第二为数据集写一份本地数据字典更新记录字段理解变化时补充说明。第三数据加载逻辑封装成统一函数所有脚本都走同一个入口避免不同脚本对字段名处理不一致。第四固定随机种子并记录依赖版本保证实验可复现。第五先跑小参数验证流程再跑完整样本不要一上来就全量训练。批处理任务要加日志和失败重试。处理过程中建议每个文件输出成功后立即标记失败时记录错误原因处理完一批后统一查看日志而不是盯着终端输出。9.2 合规建议使用 OT/ICS 安全训练数据时授权边界是第一位的。下载前确认许可协议是否允许研究、教学、商用或二次分发。论文和报告中引用数据时按发布方要求规范标注来源。涉及真实设备的 IP、主机名、地理位置等敏感信息做分析和展示时要脱敏。所有检测实验只建议在仿真环境或测试床上进行不要以任何理由对真实工控系统做攻击验证。发布模型、代码和评测文章前再检查一遍是否包含未脱敏数据。10. 总结与下一步这个 5% 公开样本最值得尝试的点是可以用很小的成本验证一套 OT/ICS 数据是否适合自己的实验流程。拿到数据后最先做的事情应该是打开 provenance 文件和字段字典确认数据来源和标签定义再跑一遍目录检查和标签分布统计。最容易踩的坑集中在三个阶段pcap 解析阶段容易因为字段选择过多导致解析慢特征工程阶段容易让时间戳和设备 IP 泄漏进模型评测阶段容易因为类别不均衡导致准确率虚高。这三个坑提前规避后续流程会顺很多。如果样本验证通过下一步可以做三件事申请完整数据集并对比样本与完整集的分布差异尝试用 AutoEncoder、Isolation Forest 一类异常检测模型做无监督基线将数据集特征接入现有 IDS 规则引擎看看规则检测和机器学习检测的互补性。无论选哪条路先把 5% 样本的流程跑通后面就不会因为数据处理细节反复返工。