界面已本地化;技能介绍与说明文档按所选语言由 AI 自动翻译,代码、命令、路径和专业术语保留原文,以原作者文档为准。
探索技能
效率与协作 · SKILL.md

implementing-purdue-model-network-segmentation

implementing-purdue-model-network-segmentation

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

独立 GitHub 快照 · 自动分类 · 以原作者文档为准

技能说明

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中继服务器

防火墙规则: 已生成 [数量] 条规则
迁移步骤: 已规划 [数量] 个阶段
我的收藏