关于 securing-remote-access-to-ot-environment
用于设计和管理 OT 环境安全远程访问的技能,重点包括基于 DMZ 的跳板服务器、多因素认证、会话录制和供应商访问控制。
主要功能
- 01通过 DMZ 转接访问
- 02以跳板服务器作为中间系统
- 03为远程会话启用 MFA
- 04录制会话以供审计
- 05按角色和时间控制访问
适用场景
- 01为 OT 维护接入供应商
- 02替换直连 OT 的 VPN 访问
- 03实施 CIP-005-7 R2 访问控制
- 04应对未经授权的 OT 访问
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill securing-remote-access-to-ot-environment安装后在 Claude Code 中输入/securing-remote-access-to-ot-environment确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSEreferences/api-reference.mdscripts/agent.py详细介绍
保护 OT 环境的远程访问
适用场景
- 为 OT 环境实施或升级远程访问架构时
- 为需要远程访问 OT 系统以提供支持和维护服务的供应商开通访问权限时
- 实施 CIP-005-7 R2 远程访问管理要求(包括 MFA)时
- 以安全的跳转服务器架构替代传统的 OT 网络直接 VPN 访问时
- 响应涉及未经授权远程访问工业控制系统的事件时
不适用于:保护不含 OT 组件的纯 IT 远程访问、为企业员工配置 VPN(请参阅通用 VPN 指南),或控制 OT 设施的物理访问。
前置条件
- 位于企业 IT 与 OT 网络之间的 DMZ 基础设施(Level 3.5)
- 跳转服务器/堡垒主机平台(CyberArk、BeyondTrust,或经过加固的 Windows/Linux 服务器)
- 多因素身份验证解决方案(Duo、RSA SecurID、YubiKey、智能卡)
- 满足审计追踪合规要求的会话录制功能
- 配置防火墙规则,仅允许通过 DMZ 中间系统进行远程访问
工作流
步骤 1:设计安全的远程访问架构
实施纵深防御远程访问架构,在 DMZ 中设置中间系统,防止外部用户与 OT 系统之间存在任何直接网络连接。
# OT Remote Access Architecture
# Key principle: NO direct connection from external networks to OT systems
architecture:
external_access_point:
location: "Internet-facing firewall"
service: "VPN gateway (IKEv2/IPsec or SSL VPN)"
authentication: "Certificate + MFA (CIP-005-7 R2.4)"
controls:
- "Source IP allowlisting for vendor access"
- "Time-based access windows"
- "Bandwidth rate limiting"
dmz_intermediate_system:
location: "Level 3.5 DMZ"
platform: "CyberArk Privileged Access Security or hardened jump server"
function: "Session broker - terminates external connection, initiates new internal connection"
controls:
- "All sessions terminate at jump server (no pass-through)"
- "Session recording with keystroke logging"
- "Clipboard and file transfer restrictions"
- "Session timeout after 30 minutes inactivity"
- "Concurrent session limits per user"
ot_internal_access:
location: "Level 3 / Level 2 OT network"
method: "Jump server initiates RDP/SSH/VNC to OT systems"
controls:
- "Firewall allows only jump server IP to reach OT"
- "Protocol restricted (RDP 3389, SSH 22, VNC 5900)"
- "Destination-specific per user role"
vendor_access:
description: "Third-party vendor remote access"
additional_controls:
- "Vendor account disabled by default; enabled on request"
- "Time-limited access windows (enable/disable per session)"
- "OT operator must co-attend vendor sessions"
- "Real-time session monitoring by OT security"
- "No persistent credentials - one-time access tokens"
# Network flow:
# User -> VPN -> Firewall -> DMZ Jump Server -> Internal FW -> OT System
# (Two separate authenticated connections; no direct routing)
步骤 2:配置具备特权访问管理功能的跳转服务器
在 DMZ 中部署并加固跳转服务器,提供会话管理、录制和基于角色的访问控制。
#!/usr/bin/env python3
"""OT Remote Access Session Manager.
Manages authorized remote access sessions to OT environments
including session creation, monitoring, recording, and termination.
Integrates with PAM solutions for credential vaulting.
"""
import json
import hashlib
import sys
from dataclasses import dataclass, field, asdict
from datetime import datetime, timedelta
from enum import Enum
class SessionState(str, Enum):
PENDING_APPROVAL = "pending_approval"
APPROVED = "approved"
ACTIVE = "active"
TERMINATED = "terminated"
EXPIRED = "expired"
DENIED = "denied"
class UserRole(str, Enum):
OT_OPERATOR = "ot_operator"
OT_ENGINEER = "ot_engineer"
VENDOR = "vendor"
SECURITY_ANALYST = "security_analyst"
@dataclass
class RemoteAccessSession:
session_id: str
user_id: str
user_role: str
source_ip: str
target_system: str
target_ip: str
protocol: str
purpose: str
state: str = SessionState.PENDING_APPROVAL
mfa_verified: bool = False
approved_by: str = ""
created_at: str = ""
started_at: str = ""
ended_at: str = ""
max_duration_minutes: int = 120
recording_path: str = ""
actions_logged: list = field(default_factory=list)
class OTRemoteAccessManager:
"""Manages remote access sessions to OT environment."""
def __init__(self):
self.sessions = {}
self.active_sessions = {}
self.access_policies = {}
self.audit_log = []
def define_access_policy(self, role, allowed_targets, protocols, max_duration):
"""Define access policy for a user role."""
self.access_policies[role] = {
"allowed_targets": allowed_targets,
"allowed_protocols": protocols,
"max_duration_minutes": max_duration,
"requires_co_attendance": role == UserRole.VENDOR,
"requires_approval": role == UserRole.VENDOR,
}
def request_session(self, user_id, user_role, source_ip,
target_system, target_ip, protocol, purpose):
"""Request a new remote access session."""
# Generate unique session ID
session_id = hashlib.sha256(
f"{user_id}{target_ip}{datetime.now().isoformat()}".encode()
).hexdigest()[:16]
# Check access policy
policy = self.access_policies.get(user_role)
if not policy:
return None, "No access policy defined for role"
if target_system not in policy["allowed_targets"]:
self._audit("ACCESS_DENIED", user_id, target_system,
f"Target not in allowed list for role {user_role}")
return None, f"Target {target_system} not authorized for role {user_role}"
if protocol not in policy["allowed_protocols"]:
self._audit("ACCESS_DENIED", user_id, target_system,
f"Protocol {protocol} not allowed for role {user_role}")
return None, f"Protocol {protocol} not authorized"
session = RemoteAccessSession(
session_id=session_id,
user_id=user_id,
user_role=user_role,
source_ip=source_ip,
target_system=target_system,
target_ip=target_ip,
protocol=protocol,
purpose=purpose,
max_duration_minutes=policy["max_duration_minutes"],
created_at=datetime.now().isoformat(),
)
# Vendor sessions require approval
if policy.get("requires_approval"):
session.state = SessionState.PENDING_APPROVAL
else:
session.state = SessionState.APPROVED
self.sessions[session_id] = session
self._audit("SESSION_REQUESTED", user_id, target_system, purpose)
return session_id, "Session created"
def approve_session(self, session_id, approver_id):
"""Approve a pending vendor session."""
session = self.sessions.get(session_id)
if not session:
return False, "Session not found"
if session.state != SessionState.PENDING_APPROVAL:
return False, "Session not in pending approval state"
session.state = SessionState.APPROVED
session.approved_by = approver_id
self._audit("SESSION_APPROVED", approver_id, session.target_system,
f"Approved session {session_id} for {session.user_id}")
return True, "Session approved"
def activate_session(self, session_id, mfa_token):
"""Activate an approved session after MFA verification."""
session = self.sessions.get(session_id)
if not session or session.state != SessionState.APPROVED:
return False, "Session not approved"
# Verify MFA (simplified - real implementation calls MFA provider)
session.mfa_verified = True
session.state = SessionState.ACTIVE
session.started_at = datetime.now().isoformat()
session.recording_path = f"/recordings/{session_id}_{datetime.now().strftime('%Y%m%d')}.mp4"
self.active_sessions[session_id] = session
self._audit("SESSION_ACTIVATED", session.user_id, session.target_system,
f"MFA verified, recording to {session.recording_path}")
return True, "Session active"
def terminate_session(self, session_id, reason="manual"):
"""Terminate an active session."""
session = self.active_sessions.pop(session_id, None)
if not session:
session = self.sessions.get(session_id)
if not session:
return False
session.state = SessionState.TERMINATED
session.ended_at = datetime.now().isoformat()
self._audit("SESSION_TERMINATED", session.user_id, session.target_system, reason)
return True
def check_expired_sessions(self):
"""Terminate sessions that have exceeded their maximum duration."""
now = datetime.now()
expired = []
for sid, session in list(self.active_sessions.items()):
started = datetime.fromisoformat(session.started_at)
if (now - started).total_seconds() > session.max_duration_minutes * 60:
self.terminate_session(sid, "maximum_duration_exceeded")
expired.append(sid)
return expired
def _audit(self, event_type, user_id, target, detail):
"""Write to audit log."""
self.audit_log.append({
"timestamp": datetime.now().isoformat(),
"event": event_type,
"user": user_id,
"target": target,
"detail": detail,
})
def generate_report(self):
"""Generate remote access session report."""
report = []
report.append("=" * 70)
report.append("OT REMOTE ACCESS SESSION REPORT")
report.append(f"Date: {datetime.now().isoformat()}")
report.append("=" * 70)
# Session summary
total = len(self.sessions)
active = sum(1 for s in self.sessions.values() if s.state == SessionState.ACTIVE)
report.append(f"\nTotal Sessions: {total}")
report.append(f"Active Sessions: {active}")
# Active sessions detail
if self.active_sessions:
report.append("\nACTIVE SESSIONS:")
for sid, s in self.active_sessions.items():
report.append(f" [{sid[:8]}] {s.user_id} ({s.user_role})")
report.append(f" Target: {s.target_system} ({s.target_ip})")
report.append(f" Started: {s.started_at}")
report.append(f" MFA: {'Verified' if s.mfa_verified else 'NOT VERIFIED'}")
return "\n".join(report)
if __name__ == "__main__":
manager = OTRemoteAccessManager()
# Define policies
manager.define_access_policy(
UserRole.OT_ENGINEER,
["HMI-01", "HMI-02", "EWS-01", "HISTORIAN-01"],
["RDP", "SSH"],
max_duration=240,
)
manager.define_access_policy(
UserRole.VENDOR,
["DCS-EWS-01"],
["RDP"],
max_duration=120,
)
# Request vendor session
sid, msg = manager.request_session(
"vendor_honeywell_01", UserRole.VENDOR,
"203.0.113.50", "DCS-EWS-01", "10.30.1.20",
"RDP", "DCS firmware update per change request CR-2026-0045")
print(f"Session request: {msg} ({sid})")
if sid:
manager.approve_session(sid, "ot_manager_01")
manager.activate_session(sid, "123456")
print(manager.generate_report())
关键概念
| 术语 | 定义 |
|---|---|
| 中间系统 | DMZ 中用于终止外部连接并代理与 OT 建立新连接的系统,可根据 CIP-005 防止直接网络访问 |
| 跳转服务器 | DMZ 中经过加固的堡垒主机,用于访问 OT 系统的远程会话,并提供会话录制和访问控制 |
| 会话录制 | 记录所有远程访问会话活动(屏幕、按键、命令),用于安全审计和事件调查 |
| 特权访问管理(PAM) | 用于托管凭据、控制访问并审计关键 OT 系统特权会话的系统 |
| 共同监控 | 要求 OT 操作员实时监控供应商远程访问会话 |
| 限时访问 | 仅在特定维护时段启用供应商账户,并在时段结束后自动禁用 |
工具与系统
- CyberArk Privileged Access Security:企业级 PAM,提供会话管理、凭据托管和 OT 远程访问录制功能
- BeyondTrust Privileged Remote Access:专为远程访问打造的解决方案,提供会话录制和精细的访问策略
- Claroty Secure Remote Access (SRA):专为 OT 打造的远程访问解决方案,提供协议感知型会话控制
- Duo Security:MFA 提供商,支持推送通知、硬件令牌和生物识别验证 OT 访问
输出格式
OT Remote Access Security Report
===================================
Active Sessions: [N]
Pending Approval: [N]
Sessions Today: [N]
MFA COMPLIANCE:
All sessions MFA verified: [Yes/No]
Sessions without MFA: [N]
VENDOR ACCESS:
Active vendor sessions: [N]
Co-attended: [N]
Recorded: [N]
评论
支持 Markdown