L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Productivité · SKILL.md

implementing-purdue-model-network-segmentation

implementing-purdue-model-network-segmentation

基于Purdue企业参考架构(PERA)模型实施网络隔离,将工业控制系统网络划分为从0级物理过程到5级企业的层次化安全区域,在OT和IT域之间强制执行严格的流量控制。

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentation de la Skill

GitHub

name: implementing-purdue-model-network-segmentation description: > 基于Purdue企业参考架构(PERA)模型实施网络隔离,将工业控制系统网络划分为从0级物理过程到5级企业的层次化安全区域,在OT和IT域之间强制执行严格的流量控制。 domain: cybersecurity subdomain: ot-ics-security tags: [ot-security, ics, purdue-model, network-segmentation, iec62443, defense-in-depth, dmz, scada] version: "1.0" author: mahipal license: Apache-2.0

实施Purdue模型网络隔离

适用场景

  • 为ICS/SCADA环境设计或改造网络架构时
  • 在棕地工厂中实施IEC 62443区域和通道要求时
  • 创建IT/OT DMZ(3.5级)以控制企业网络和控制网络之间的数据流时
  • 修复有关OT网络扁平化或IT到OT直接连接的审计发现时
  • 在收购或合并后对融合的IT/OT网络进行隔离时

不适用于单个Purdue级别内的微隔离(参见implementing-zone-conduit-model-for-ics)、没有传统ICS网络的云原生环境,或纯IT环境中的网络隔离。

前置条件

  • 包含每台设备Purdue级别分类的完整OT资产清单
  • 显示当前拓扑、VLAN和防火墙位置的网络架构图
  • 具备OT协议深度包检测(DPI)能力的工业防火墙(Palo Alto、Fortinet、Cisco)
  • 了解Purdue级别之间所需的数据流(历史服务器复制、远程访问、补丁分发)
  • 工厂运营部门对网络变更的变更管理审批

工作流程

步骤 1:将当前架构映射到Purdue级别

按照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)

步骤 2:配置工业DMZ(3.5级)

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级DMZIT(4级)和OT(3级)之间的隔离区,所有跨边界数据交换在此发生
纵深防御(Defense in Depth)分层安全方法,要求攻击者突破多个边界才能到达关键控制系统
数据二极管(Data Diode)硬件强制执行的单向通信设备,确保数据只能从OT流向IT,不能反向
区域(Zone)按IEC 62443定义的,共享相同安全要求的资产逻辑分组
通道(Conduit)区域之间具有定义安全策略的受控通信路径

常见场景

场景:扁平OT网络修复

背景:审计发现企业IT系统可以直接与控制网络上的PLC通信。IT和OT之间没有DMZ,也没有防火墙。

方法:

  1. 执行全面流量分析,识别所有跨越IT/OT边界的合法数据流
  2. 设计包含历史服务器副本、跳板服务器和补丁暂存的DMZ架构
  3. 在IT和DMZ之间部署工业防火墙(北向防火墙),在DMZ和OT之间部署防火墙(南向防火墙)
  4. 逐一迁移数据流:从通过DMZ的历史服务器复制开始
  5. 为远程访问实施跳板服务器,逐步废弃直接RDP访问OT系统
  6. 迁移所有流量通过DMZ后,在北向防火墙阻断直接IT到OT的流量
  7. 通过来自IT网络的渗透测试验证,确认没有直接到达1级控制器的路径

注意事项:不要一次性切换所有流量——逐个迁移数据流并制定回滚计划。旧版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中继服务器

防火墙规则: 已生成 [数量] 条规则
迁移步骤: 已规划 [数量] 个阶段
Skills enregistrées