Implements Purdue model network segmentation for ICS/OT environments, mapping assets to levels 0-5, assigning VLANs/protocols, and defining firewall rules for IT/OT isolation.
npx claudepluginhub killvxk/cybersecurity-skills-zhThis skill uses the workspace's default tool permissions.
- 为ICS/SCADA环境设计或改造网络架构时
Implements Purdue Model network segmentation for ICS/OT, mapping assets to levels 0-5, assigning VLANs/protocols, and enforcing firewall rules between security zones.
Implements Purdue PERA model network segmentation for ICS/SCADA, mapping assets to levels 0-5, assigning VLANs/protocols, and defining firewall rules for OT/IT isolation.
Implements network segmentation in OT environments using VLANs, industrial firewalls, data diodes, SDN based on Purdue model. Covers zero-downtime migration from flat networks, DPI firewall config for industrial protocols, and traffic analysis verification.
Share bugs, ideas, or general feedback.
不适用于单个Purdue级别内的微隔离(参见implementing-zone-conduit-model-for-ics)、没有传统ICS网络的云原生环境,或纯IT环境中的网络隔离。
按照Purdue模型层次结构对所有网络资产和数据流进行分类。
#!/usr/bin/env python3
"""Purdue模型网络隔离规划器。
将现有OT/IT网络资产映射到Purdue模型级别,并生成
包括防火墙规则和VLAN分配的隔离建议。
"""
import json
import csv
import sys
from collections import defaultdict
from datetime import datetime
from typing import Dict, List
PURDUE_LEVELS = {
0: {
"name": "物理过程",
"description": "传感器、执行器、现场仪器",
"typical_devices": ["传感器", "执行器", "驱动器", "电机启动器"],
"vlan_range": "100-109",
"allowed_protocols": ["HART", "Profibus", "Foundation Fieldbus", "IO-Link"],
},
1: {
"name": "基本控制",
"description": "PLC、RTU、安全控制器",
"typical_devices": ["PLC", "RTU", "安全控制器", "DCS控制器"],
"vlan_range": "110-119",
"allowed_protocols": ["EtherNet/IP", "Profinet", "Modbus/TCP", "S7comm", "OPC UA"],
},
2: {
"name": "监控控制",
"description": "HMI、SCADA服务器、工程师工作站",
"typical_devices": ["HMI", "SCADA服务器", "工程师工作站", "批处理服务器"],
"vlan_range": "120-129",
"allowed_protocols": ["OPC UA", "OPC DA", "Modbus/TCP", "DNP3", "HTTPS"],
},
3: {
"name": "站点运营",
"description": "历史服务器、MES、资产管理",
"typical_devices": ["历史服务器", "MES服务器", "资产管理", "报警服务器"],
"vlan_range": "130-139",
"allowed_protocols": ["OPC UA", "SQL", "HTTPS", "MQTT"],
},
3.5: {
"name": "IT/OT DMZ",
"description": "IT和OT之间的隔离区",
"typical_devices": ["跳板服务器", "历史服务器镜像", "补丁服务器", "AV更新服务器", "远程访问网关"],
"vlan_range": "150-159",
"allowed_protocols": ["HTTPS", "RDP(仅到跳板服务器)", "SSH", "SQL(只读副本)"],
},
4: {
"name": "企业IT",
"description": "企业应用、邮件、ERP",
"typical_devices": ["ERP服务器", "邮件服务器", "业务应用", "Active Directory"],
"vlan_range": "200-249",
"allowed_protocols": ["HTTPS", "LDAPS", "SMTP", "SQL"],
},
5: {
"name": "企业网络/互联网",
"description": "外部连接、云服务、合作伙伴网络",
"typical_devices": ["互联网网关", "VPN集中器", "云服务"],
"vlan_range": "250-254",
"allowed_protocols": ["HTTPS", "IPsec VPN"],
},
}
class PurdueSegmentationPlanner:
"""规划Purdue模型网络隔离。"""
def __init__(self):
self.assets = []
self.data_flows = []
self.firewall_rules = []
def load_asset_inventory(self, filepath: str):
"""从CSV文件加载资产清单。"""
with open(filepath, "r") as f:
self.assets = list(csv.DictReader(f))
print(f"[*] 已加载 {len(self.assets)} 个资产")
def classify_assets(self):
"""根据类型和功能将资产分类到Purdue级别。"""
classification = defaultdict(list)
for asset in self.assets:
level = asset.get("purdue_level", "")
try:
level = float(level)
except (ValueError, TypeError):
level = self._infer_purdue_level(asset)
classification[level].append(asset)
asset["assigned_level"] = level
return classification
def _infer_purdue_level(self, asset: dict) -> float:
"""如果未明确分配,从设备类型推断Purdue级别。"""
device_type = asset.get("type", "").lower()
mapping = {
"sensor": 0, "actuator": 0, "drive": 0,
"plc": 1, "rtu": 1, "safety": 1, "dcs": 1,
"hmi": 2, "scada": 2, "engineering": 2,
"historian": 3, "mes": 3, "alarm": 3,
"jump": 3.5, "patch": 3.5, "remote_access": 3.5,
"erp": 4, "email": 4, "directory": 4,
}
for keyword, level in mapping.items():
if keyword in device_type:
return level
return -1
def generate_vlan_plan(self, classification: dict) -> list:
"""基于Purdue级别生成VLAN分配计划。"""
vlan_plan = []
for level, info in PURDUE_LEVELS.items():
assets_at_level = classification.get(level, [])
vlan_plan.append({
"purdue_level": level,
"level_name": info["name"],
"vlan_range": info["vlan_range"],
"asset_count": len(assets_at_level),
"allowed_protocols": info["allowed_protocols"],
})
return vlan_plan
def generate_firewall_rules(self) -> list:
"""生成强制执行Purdue模型边界的跨级别防火墙规则。"""
rules = [
{
"rule_id": 1,
"name": "阻止IT直接访问1级",
"action": "DENY",
"source_zone": "Level_4_Enterprise",
"dest_zone": "Level_1_Control",
"service": "ANY",
"log": True,
"description": "禁止企业IT直接访问基本控制PLC",
},
{
"rule_id": 2,
"name": "阻止IT直接访问2级",
"action": "DENY",
"source_zone": "Level_4_Enterprise",
"dest_zone": "Level_2_Supervisory",
"service": "ANY",
"log": True,
"description": "禁止企业IT直接访问HMI/SCADA",
},
{
"rule_id": 3,
"name": "允许DMZ到历史服务器副本",
"action": "ALLOW",
"source_zone": "Level_3_Operations",
"dest_zone": "Level_35_DMZ",
"service": "SQL/1433(只读副本推送)",
"log": True,
"description": "历史服务器将数据推送到DMZ副本供IT使用",
},
{
"rule_id": 4,
"name": "允许IT访问DMZ跳板服务器",
"action": "ALLOW",
"source_zone": "Level_4_Enterprise",
"dest_zone": "Level_35_DMZ",
"service": "RDP/3389, SSH/22",
"log": True,
"description": "IT用户仅通过DMZ中的跳板服务器访问OT",
},
{
"rule_id": 5,
"name": "允许DMZ跳板服务器访问2级",
"action": "ALLOW",
"source_zone": "Level_35_DMZ",
"dest_zone": "Level_2_Supervisory",
"service": "RDP/3389(仅限跳板服务器IP)",
"log": True,
"description": "跳板服务器提供对HMI/SCADA的受控访问",
},
{
"rule_id": 6,
"name": "允许2级访问1级",
"action": "ALLOW",
"source_zone": "Level_2_Supervisory",
"dest_zone": "Level_1_Control",
"service": "Modbus/502, EtherNet-IP/44818, S7comm/102",
"log": True,
"description": "HMI/SCADA使用工业协议与PLC通信",
},
{
"rule_id": 7,
"name": "阻止1级出站到互联网",
"action": "DENY",
"source_zone": "Level_1_Control",
"dest_zone": "Level_5_Internet",
"service": "ANY",
"log": True,
"description": "PLC不得直接访问互联网",
},
{
"rule_id": 8,
"name": "允许DMZ补丁分发到2级",
"action": "ALLOW",
"source_zone": "Level_35_DMZ",
"dest_zone": "Level_2_Supervisory",
"service": "WSUS/8530",
"log": True,
"description": "DMZ中的补丁服务器向监控系统分发更新",
},
{
"rule_id": 9,
"name": "默认拒绝所有跨区域流量",
"action": "DENY",
"source_zone": "ANY",
"dest_zone": "ANY",
"service": "ANY",
"log": True,
"description": "默认拒绝所有未明确允许的流量",
},
]
self.firewall_rules = rules
return rules
def print_segmentation_plan(self, classification: dict):
"""打印完整的隔离计划。"""
print(f"\n{'='*70}")
print("PURDUE模型网络隔离计划")
print(f"{'='*70}")
print(f"生成时间: {datetime.now().isoformat()}")
vlan_plan = self.generate_vlan_plan(classification)
print(f"\n--- VLAN分配 ---")
for v in vlan_plan:
print(f"\n {v['level_name']} (Purdue {v['purdue_level']})")
print(f" VLAN范围: {v['vlan_range']}")
print(f" 资产数量: {v['asset_count']}")
print(f" 允许的协议: {', '.join(v['allowed_protocols'])}")
print(f"\n--- 跨区域防火墙规则 ---")
rules = self.generate_firewall_rules()
for rule in rules:
action_symbol = "+" if rule["action"] == "ALLOW" else "X"
print(f"\n [{action_symbol}] 规则 {rule['rule_id']}: {rule['name']}")
print(f" {rule['source_zone']} -> {rule['dest_zone']}")
print(f" 服务: {rule['service']}")
print(f" 原因: {rule['description']}")
if __name__ == "__main__":
planner = PurdueSegmentationPlanner()
if len(sys.argv) >= 2:
planner.load_asset_inventory(sys.argv[1])
classification = planner.classify_assets()
planner.print_segmentation_plan(classification)
DMZ是IT和OT之间的关键边界。所有数据交换必须通过它进行——不允许直接连接。
# 3.5级DMZ架构配置
# 所有IT-OT数据交换流量都通过DMZ
dmz_architecture:
zone_name: "IT_OT_DMZ"
purdue_level: 3.5
vlan: 150
components:
historian_replica:
purpose: "OT历史服务器数据的只读副本,供IT/业务访问"
direction: "OT将数据推送到DMZ(单向)"
ip: "10.10.150.10"
services:
- port: 1433
protocol: "SQL"
direction: "仅接受来自3级历史服务器的入站"
- port: 443
protocol: "HTTPS"
direction: "出站到4级供IT消费者访问"
jump_server:
purpose: "OT维护的受控远程访问点"
ip: "10.10.150.20"
services:
- port: 3389
protocol: "RDP"
direction: "接受来自4级并需要MFA的入站"
- port: 3389
protocol: "RDP"
direction: "仅出站到2级HMI"
security_controls:
- "需要多因素认证"
- "启用会话录制"
- "最大会话时长: 4小时"
- "基于审批的访问工作流"
patch_server:
purpose: "OT部署前已测试补丁的暂存区"
ip: "10.10.150.30"
services:
- port: 8530
protocol: "WSUS"
direction: "从4级WSUS拉取,推送到2-3级"
antivirus_relay:
purpose: "向OT端点分发AV签名"
ip: "10.10.150.40"
services:
- port: 443
protocol: "HTTPS"
direction: "从4级拉取定义,分发到2-3级"
firewall_rules:
north_firewall: # DMZ和4级企业之间
- allow: "4级 -> DMZ跳板服务器:3389(需MFA)"
- allow: "4级 -> DMZ历史服务器副本:443(只读)"
- allow: "DMZ补丁服务器 -> 4级WSUS:8530(仅拉取)"
- deny: "所有其他流量"
south_firewall: # DMZ和3级运营之间
- allow: "3级历史服务器 -> DMZ副本:1433(推送方向)"
- allow: "DMZ跳板服务器 -> 2级HMI:3389(会话限制)"
- allow: "DMZ补丁服务器 -> 2/3级:8530(计划任务)"
- deny: "所有其他流量"
critical_rule: "流量不得端到端穿越DMZ。DMZ必须中断所有连接。"
| 术语 | 定义 |
|---|---|
| Purdue模型(PERA) | 按功能和信任度将工业网络组织为0-5级的层次化参考架构 |
| 3.5级DMZ | IT(4级)和OT(3级)之间的隔离区,所有跨边界数据交换在此发生 |
| 纵深防御(Defense in Depth) | 分层安全方法,要求攻击者突破多个边界才能到达关键控制系统 |
| 数据二极管(Data Diode) | 硬件强制执行的单向通信设备,确保数据只能从OT流向IT,不能反向 |
| 区域(Zone) | 按IEC 62443定义的,共享相同安全要求的资产逻辑分组 |
| 通道(Conduit) | 区域之间具有定义安全策略的受控通信路径 |
背景:审计发现企业IT系统可以直接与控制网络上的PLC通信。IT和OT之间没有DMZ,也没有防火墙。
方法:
注意事项:不要一次性切换所有流量——逐个迁移数据流并制定回滚计划。旧版OT系统可能使用无法通过执行DPI的防火墙的协议;先在实验室彻底测试。在活跃生产环境中部署DMZ时,必须在商定的维护窗口内进行。
PURDUE模型隔离报告
====================================
评估日期: YYYY-MM-DD
设施: [工厂名称]
当前状态:
网络类型: [扁平/部分隔离/完全隔离]
IT-OT边界: [无/防火墙/双防火墙DMZ]
直接IT到PLC路径: [数量]
推荐架构:
0-1级: VLAN 110(控制网络)
2级: VLAN 120(监控网络)
3级: VLAN 130(运营网络)
3.5级: VLAN 150(IT/OT DMZ)
4-5级: VLAN 200+(企业)
DMZ组件:
- 历史服务器副本
- 跳板服务器(启用MFA)
- 补丁暂存服务器
- AV中继服务器
防火墙规则: 已生成 [数量] 条规则
迁移步骤: 已规划 [数量] 个阶段