OT远程访问安全_securing-remote-access-to-ot-environment

以下为本文档的中文说明

securing-remote-access-to-ot-environment(保障 OT 环境远程访问安全)是一个专注于工业控制系统(ICS)和运营技术(OT)网络远程访问安全加固的高专业度技能。OT 环境涵盖电力能源、石油化工、水处理、交通运输和制造业等国家关键基础设施,其安全需求与传统的企业 IT 系统存在本质区别。使用场景包括:为工业设施设计和部署安全的远程运维访问方案、对工控网络的边界实施严格访问控制和流量监控、审计和评估现有 OT 远程访问架构的安全漏洞和改进空间。核心特点包括:深入阐释 OT 安全与 IT 安全的五个根本差异:可用性优先于机密性(系统停机比数据泄露后果更严重)、实时性和确定性通信要求(微秒级延迟影响生产质量)、专有的工控协议(Modbus/TCP、DNP3、PROFINET、OPC UA 等缺乏内置安全机制)、长生命周期设备(PLC/RTU 通常运行 10-20 年无法升级)和物理安全与环境安全的特殊考量;提供多种经过验证的远程访问安全架构方案,包括安全跳板机(Jump Box/Bastion Host)的堡垒机架构、专用加密 VPN 网关连接方案、遵循零信任原则的网络访问(ZTNA)架构;涵盖工控核心协议的安全加固技术措施,如 Modbus/TCP 的深度包检测(DPI)和功能码白名单;提供多因素认证(MFA/RSA SecurID)和基于角色的访问控制(RBAC)实施指南;提供遵从 IEC 62443 系列工业通信网络安全标准的审计检查清单。该技能对于工业控制系统安全工程师而言是不可或缺的参考资料。


Securing Remote Access to OT Environment

When to Use

  • When implementing or upgrading remote access architecture for OT environments
  • When onboarding vendors who require remote access to OT systems for support and maintenance
  • When implementing CIP-005-7 R2 requirements for remote access management including MFA
  • When replacing legacy direct VPN access to OT networks with a secure jump server architecture
  • When responding to an incident involving unauthorized remote access to industrial control systems

Do not usefor securing IT-only remote access without OT components, for configuring VPN for corporate workers (see general VPN guides), or for physical access control to OT facilities.

Prerequisites

  • DMZ infrastructure (Level 3.5) between corporate IT and OT networks
  • Jump server/bastion host platform (CyberArk, BeyondTrust, or hardened Windows/Linux server)
  • Multi-factor authentication solution (Duo, RSA SecurID, YubiKey, smart cards)
  • Session recording capability for audit trail compliance
  • Firewall rules permitting remote access only through the DMZ intermediate system

Workflow

Step 1: Design Secure Remote Access Architecture

Implement a defense-in-depth remote access architecture with an intermediate system in the DMZ that prevents any direct network connectivity between external users and OT systems.

# OT Remote Access Architecture# Key principle: NO direct connection from external networks to OT systemsarchitecture: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)

Step 2: Configure Jump Server with Privileged Access Management

Deploy and harden the jump server in the DMZ with session management, recording, and role-based access controls.

#!/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. """importjsonimporthashlibimportsysfromdataclassesimportdataclass,field,asdictfromdatetimeimportdatetime,timedeltafromenumimportEnumclassSessionState(str,Enum):PENDING_APPROVAL="pending_approval"APPROVED="approved"ACTIVE="active"TERMINATED="terminated"EXPIRED="expired"DENIED="denied"classUserRole(str,Enum):OT_OPERATOR="ot_operator"OT_ENGINEER="ot_engineer"VENDOR="vendor"SECURITY_ ANALYST="security_analyst"@dataclassclassRemoteAccessSession:session_id:struser_id:struser_role:strsource_ip:strtarget_system:strtarget_ip:strprotocol:strpurpose:strstate:str=SessionState.PENDING_APPROVAL mfa_verified:bool=Falseapproved_by:str=""created_at:str=""started_at:str=""ended_at:str=""max_duration_minutes:int=120recording_path:str=""actions_logged:list=field(default_factory=list)classOTRemoteAccessManager:"""Manages remote access sessions to OT environment."""def__init__(self):self.sessions={}self.active_sessions={}self.access_policies={}self.audit_log=[]defdefine_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,}defrequest_session(self,user_id,user_role,source_ip,target_system,target_ip,protocol,purpose):"""Request a new remote access session."""# Generate unique session IDsession_id=hashlib.sha256(f"{user_id}{target_ip}{datetime.now().isoformat()}".encode()).hexdigest()[:16]# Check access policypolicy=self.access_policies.get(user_role)ifnotpolicy:returnNone,"No access policy defined for role"iftarget_systemnotinpolicy["allowed_targets"]:self._audit("ACCESS_DENIED",user_id,target_system,f"Target not in allowed list for role{user_role}")returnNone,f"Target{target_system}not authorized for role{user_role}"ifprotocolnotinpolicy["allowed_protocols"]:self._audit("ACCESS_DENIED",user_id,target_system,f"Protocol{protocol}not allowed for role{user_role}")returnNone,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 approvalifpolicy.get("requires_approval"):session.state=SessionState.PENDING_APPROVALelse:session.state=SessionState.APPROVED self.sessions[session_id]=session self._audit("SESSION_REQUESTED",user_id,target_system,purpose)returnsession_id,"Session created"defapprove_session(self,session_id,approver_id):"""Approve a pending vendor session."""session=self.sessions.get(session_id)ifnotsession:returnFalse,"Session not found"ifsession.state!=SessionState.PENDING_APPROVAL:returnFalse,"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}")returnTrue,"Session approved"defactivate_session(self,session_id,mfa_token):"""Activate an approved session after MFA verification."""session=self.sessions.get(session_id)ifnotsessionorsession.state!=SessionState.APPROVED:returnFalse,"Session not approved"# Verify MFA (simplified - real implementation calls MFA provider)session.m fa_verified=Truesession.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}")returnTrue,"Session active"defterminate_session(self,session_id,reason="manual"):"""Terminate an active session."""session=self.active_sessions.pop(session_id,None)ifnotsession:session=self.sessions.get(session_id)ifnotsession:returnFalsesession.state=SessionState.TERMINATED session.ended_at=datetime.now().isoformat()self._audit("SESSION_TERMINATED",session.user_id,session.target_system,reason)returnTruedefcheck_expired_sessions(self):"""Terminate sessions that have exceeded their maximum duration."""now=datetime.now()expired=[]forsid,sessioninlist(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)returnexpireddef_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,})defgenerate_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 summarytotal=len(self.sessions)active=sum(1forsinself.sessions.values()ifs.state==SessionState.ACTIVE)report.append(f"\ Total Sessions:{total}")report.append(f"Active Sessions:{active}")# Active sessions detailifself.active_sessions:report.append("\ ACTIVE SESSIONS:")forsid,sinself.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'ifs.mfa_verifiedelse'NOT VERIFIED'}")return"\ ".join(report)if__name__=="__main__":manager=OTRemoteAccessManager()# Define policiesmanager.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 sessionsid,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})")ifsid:manager.approve_session(sid,"ot_manager_01")manager.activate_session(sid,"123456")print(manager.generate_report())

Key Concepts

TermDefinition
Intermediate SystemSystem in the DMZ that terminates external connections and brokers new connections to OT, preventing direct network access per CIP-005
Jump ServerHardened bastion host in the DMZ used for remote access sessions to OT systems with session recording and access controls
Session RecordingCapture of al
l remote access session activity (screen, keystrokes, commands) for security audit and incident investigation
Privileged Access Management (PAM)System for vaulting credentials, controlling access, and auditing privileged sessions to critical OT systems
Co-AttendanceRequirement for an OT operator to monitor vendor remote access sessions in real time
Time-Limited AccessVendor accounts enabled only for specific maintenance windows and automatically disabled after the window closes

Tools & Systems

  • CyberArk Privileged Access Security: Enterprise PAM with session management, credential vaulting, and recording for OT remote access
  • BeyondTrust Privileged Remote Access: Purpose-built remote access solution with session recording and granular access policies
  • Claroty Secure Remote Access (SRA): OT-specific remote access solution with protocol-aware session controls
  • Duo Security: MFA provider supporting push notifications, hardware tokens, and biometrics for OT access verification

Output Format

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]