aaroncorvo/otlab

GitHub: aaroncorvo/otlab

在单块树莓派上构建完整 ICS/OT 安全培训实验环境的一体化工控仿真平台

Stars: 1 | Forks: 0

# OTLab — 单块树莓派上的 ICS 培训实验室 ![Dashboard Overview](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/e0f3bd9b56013735.png) 为 [ICS Village](https://icsvillage.com/) (DEF CON 活动村) 构建的工业控制系统动手实践培训实验室。在**单块树莓派**上以容器形式运行完整的 DMZ + 过程控制网架构——包括防火墙、DHCP、DNS、虚拟 PLC、Modbus + DNP3 子站、主站轮询循环、Suricata IDS 和操作员仪表板。 ``` ┌─────── operator browser ──────┐ │ │ ▼ │ ┌───────────── single Raspberry Pi 5 ──────────────────┐│ │ ││ │ ┌── DMZ · dmz-br0 · 192.168.75.0/24 (L3.5) ─────┐ ││ │ │ firewall · dhcp-dmz · OTLab Dashboard │ ││ ←─ https://:8000/ │ └───────────────┬─────────────────────────────────┘ ││ │ │ firewall conduit (iptables) ││ │ ┌── PCN · pcn-br0 · 10.20.30.0/24 (L1/L2) ─────┐ ││ │ │ firewall · dhcp-pcn · modbus-master │ ││ │ │ sensor-sim · dnp3-outstation │ ││ │ │ plc-1-virt · plc-2-virt (OpenPLC) │ ││ │ └─────────────────────────────────────────────────┘ ││ │ ││ │ + Suricata IDS sniffing pcn-br0 ││ │ + Cockpit / Portainer / EdgeShark admin UIs ││ └──────────────────────────────────────────────────────────┘│ │ │ └── wlan0 → internet ────────────────┘ ``` **一块 Pi。一个用于互联网的 wlan。仅此而已。** 其他一切都运行在容器中。 ## 您将获得 一个完整的 ICS / OT 安全教学环境,全部运行在单块 Pi 上: | 类别 | 内容 | |---|---| | **网络分段** | 工业 DMZ (L3.5) + 过程控制网络 (L1/L2),由容器化的 iptables 防火墙通过 SNAT + DNS 转发强制执行 | | **DHCP / DNS** | 每个区域的 dnsmasq DHCP 及静态保留 · 集成到防火墙中的 DNS 转发器 · 记录所有查询以用于“防火墙处的 DNS 渗透”教学 | | **主站 / 子站循环** | `modbus-master` 容器以 10 Hz 频率轮询 `sensor-sim` —— 线路上传输的具有确定性、可观测的 Modbus TCP 流量 | | **OpenPLC** | 两个带有 Web UI(端口 `:8081`、`:8082`)的虚拟 OpenPLC 实例,用于 IEC 61131-3 点击实操课程 | | **DNP3** | 在端口 `:20000` 上运行的纯标准库实现的 DNP3 子站 | | **IDS** | Suricata 嗅探 `pcn-br0`,使用 OTLAB 规则检测来自非主站 IP 的 Modbus FC5/6/15/16 写入操作 + SSH 暴力破解检测 | | **仪表板** | 包含 7 个标签页的 Flask + 原生 JS 操作员界面:概览 · 架构 · IDS · 防火墙 · DHCP · 实时数据 · 教学 | | **管理界面** | Cockpit (Linux),Portainer (Docker),EdgeShark (浏览器中的实时数据包捕获) | ## 快速开始 — 从零开始配置单块 Pi 您需要:**一块带有 WiFi(用于连接互联网)的 Raspberry Pi 5(推荐 16 GB,8 GB 也可运行)**、一张 SD 卡或 NVMe 硬盘,以及一台位于同一网络中的操作员工作站(macOS 或 Linux 笔记本电脑)。 ``` # === 1. 在 SD/NVMe 上镜像全新的 Pi OS Lite (64-bit Bookworm) === # 在 Pi Imager → 高级 中:设置主机名 `l3-mon-01`,配置 WiFi, # 启用 SSH,设置用户名 + 密码。 # === 2. 从操作员工作站克隆此 repo === git clone https://github.com/aaroncorvo/otlab.git cd otlab # === 3. 将 ssh 密钥推送到新镜像的 Pi === ssh-copy-id @l3-mon-01.local # === 4. 引导程序 (创建 otadmin + otuser,安装 Docker,lab venv) === ./scripts/bootstrap-users.sh @l3-mon-01.local ./scripts/bootstrap-pi.sh otadmin@l3-mon-01.local ./scripts/bootstrap-l3-mon-role.sh otadmin@l3-mon-01.local # === 5. 部署 lab fabric === ./scripts/install-virtual-lab.sh otadmin@l3-mon-01.local # === 6. 添加 Suricata IDS + admin UI (可选但推荐) === ./scripts/install-suricata.sh otadmin@l3-mon-01.local ./scripts/install-cockpit.sh otadmin@l3-mon-01.local ./scripts/install-portainer.sh otadmin@l3-mon-01.local ./scripts/install-edgeshark.sh otadmin@l3-mon-01.local ``` 总耗时:首次运行约 **~30 分钟**(大部分时间用于 OpenPLC 源码编译 —— 再次运行时会被缓存)。 部署完成后,请浏览访问: | URL | 内容 | 登录信息 | |---|---|---| | `https://l3-mon-01:8000/` | **OTLab 仪表板** (主要界面) | `otlab` / `P@ssw0rd!` | | `https://l3-mon-01:9090/` | Cockpit (Linux 管理) | `otadmin` / 您的 sudo 密码 | | `https://l3-mon-01:9443/` | Portainer CE (Docker UI) | 首次访问时设置 | | `http://l3-mon-01:5001/` | EdgeShark (浏览器中实时抓包) | 无 | | `http://l3-mon-01:8081/` | 虚拟 OpenPLC #1 Web UI | `openplc` / `P@ssw0rd!` | | `http://l3-mon-01:8082/` | 虚拟 OpenPLC #2 Web UI | 同上 | 完整的分步操作指南:**[`docs/setup-from-scratch.md`](docs/setup-from-scratch.md)**。 ## 仪表板展示内容 ![Demo flow](https://raw.githubusercontent.com/aaroncorvo/otlab/main/reference/screenshots/demo.gif) *30 秒演示:在 Teaching 标签页发起一次 Modbus FC6 写入操作 → 在 IDS 标签页看到其作为 OTLAB-1004 警报出现 → 在 Firewall 标签页看到防火墙计数器跳动。(如果上面的 GIF 图片丢失,请查看 [`reference/screenshots/`](reference/screenshots/) 获取捕获操作手册。)* 七个标签页 —— 完整的图文导览请见 **[`docs/dashboard-tour.md`](docs/dashboard-tour.md)**: | 标签页 | 内容 | 截图 | |---|---|---| | **Overview** | 实时过程状态(动态 SVG 简图)+ 每个容器的信息卡 + 来自主站的实时 Modbus 轮询遥测数据 | [`overview.png`](reference/screenshots/overview.png) | | **Architecture** | Purdue 模型,实验室的实际资产放置在其规范层级 + 自动发现的网络拓扑 | [`architecture.png`](reference/screenshots/architecture.png) | | **IDS** | Suricata 统计数据 — 计数 (5分钟 / 1小时 / 24小时)、24小时时间轴、热门签名、热门来源、热门目标、最新警报 | [`ids.png`](reference/screenshots/ids.png) | | **Firewall** | 实时 iptables (5 个链) 及数据包计数器 · conntrack 快照 · DNS 查询统计 + 日志 | [`firewall.png`](reference/screenshots/firewall.png) | | **DHCP** | 各区域 (DMZ + PCN) 的租约表 + 静态保留 + 最近的租约事务 | [`dhcp.png`](reference/screenshots/dhcp.png) | | **Live Data** | 系统健康状态、审计日志、pcap 捕获 | [`live-data.png`](reference/screenshots/live-data.png) | | **Teaching** | 风险提示、操作指南、可运行的测试库、Modbus 写入试验场、注入故障、队列重置 | [`teaching.png`](reference/screenshots/teaching.png) | ## 扩展实验室 当单 Pi 设置正常工作后,您可以对其进行扩展以实现更丰富的教学场景: | 扩展项 | 增加的内容 | 文档 | |---|---|---| | **添加物理 OpenPLC Pi** | 真实的 GPIO、线路上的真实 Modbus、第二阶段硬件(继电器、指示灯、按钮) | [`setup-from-scratch.md` § Stage 2](docs/setup-from-scratch.md) | | **添加物理 Conpot Pi** | 在独立的物理机上运行三个供应商蜜罐角色 (Siemens / Schneider / Rockwell) | [`setup-from-scratch.md` § Stage 2](docs/setup-from-scratch.md) | | **添加 RS485 Modbus 设备** | 通过 Waveshare RS485-to-Ethernet 网关连接真实的工业传感器(温度、电能表等) | [`setup-from-scratch.md` § Stage 3](docs/setup-from-scratch.md) | | **添加无线 IoT** | 通过 WiFi 加入 PCN 网段的 ESP32 Modbus 客户端 | [`setup-from-scratch.md` § Stage 4](docs/setup-from-scratch.md) | 每个阶段都是**独立且可选的**。单 Pi 实验室本身已经完全可用 —— 您不需要这些扩展即可教授核心课程。 ## 仓库布局 ``` . ├── README.md ← you are here ├── docs/ # Architecture + setup + curriculum │ ├── setup-from-scratch.md ← linear from-zero playbook (start here) │ ├── dashboard-tour.md ← 7-tab dashboard walkthrough │ ├── lab-architecture.md ← deep-dive build doc │ ├── virtualization.md ← ContainerLab fabric architecture │ ├── naming-schema.md ← canonical names, IPs, MAC reservations │ ├── network-topology.md ← physical NIC ↔ virtual fabric │ ├── architecture-evolution.md ← phase plan + decision log │ ├── curriculum.md ← lessons, MITRE ATT&CK coverage │ ├── phase-1-modbus-loop.md ← first lesson walkthrough │ └── arduino-setup.md ← Arduino UNO breakout boards ├── virtual/ # ContainerLab fabric │ ├── topologies/otlab.clab.yaml # full topology (9 nodes + 2 bridges) │ └── dockerfiles/ # 7 OTLab images ├── dashboard/ # Dashboard source (mounted into container) ├── plc/ # Python services + OpenPLC programs + scenarios ├── honeypot/ # Conpot persona configs (optional Pi #3) ├── scripts/ # Bootstrap + install scripts └── reference/ # Diagrams, BOMs, vendor OIDs, pcaps ``` ## 操作实验室 ``` # Topology 状态 ssh otadmin@l3-mon-01.local 'sudo containerlab inspect -t /home/otuser/lab/virtual/topologies/otlab.clab.yaml --format table' # Tail 容器日志 ssh otadmin@l3-mon-01.local 'sudo docker logs -f clab-otlab-modbus-master' # 实时 firewall 计数器 ssh otadmin@l3-mon-01.local 'sudo docker exec clab-otlab-fw-dmz-pcn iptables -nvL FORWARD' # 最近的 IDS 告警 ssh otadmin@l3-mon-01.local 'sudo grep "event_type\":\"alert" /var/log/suricata/eve.json | tail -10' # 各组之间的重置 (浏览器):Teaching 标签页 → 为下一组 Reset Lab # 灾难恢复 — 彻底清除 + 重新部署 ./scripts/install-virtual-lab.sh otadmin@l3-mon-01.local ``` ## 许可证 [MIT](LICENSE)。您可以自由使用、分支(Fork) 并用于教学。感谢但非必须注明出处。 ## 构建初衷 为 DEF CON 的 [ICS Village](https://icsvillage.com/) 而构建。非常感谢 ICS Village 社区多年来激发的好奇心,以及鼓励我们将这些内容公之于众。
标签:ContainerLab, DEF CON, DHCP, DMZ隔离, DNP3, DNS, Docker容器, ICS Village, ICS安全, L3.5层, Metaprompt, OpenPLC, OT安全, PCN, SCADA, Suricata, 入侵检测系统, 哈希传递, 安全实验环境, 安全数据湖, 工业控制系统, 工控协议, 工控安全测试, 工控靶场, 攻击面发现, 数据可视化, 流量捕获, 漏洞修复, 现代安全运营, 红队培训, 网络安全培训, 网络拓扑, 网络靶场, 蓝队培训, 虚拟PLC, 请求拦截, 过程控制网络, 防火墙