Claude
Skills
Sign in
Back

implementing-conduit-security-for-ot-remote-access

Included with Lifetime
$97 forever

Implement secure conduit architecture for OT remote access following IEC 62443 zones and conduits model, deploying jump servers, MFA-enabled gateways, session recording, and approval-based workflows to control vendor and engineer access to industrial control systems without exposing OT networks directly.

Securityot-securityicsremote-accessiec62443jump-serverzero-trustconduitmfascripts

What this skill does


# Implementing Conduit Security for OT Remote Access

## When to Use

- When replacing direct VPN connections from IT or vendors into OT control networks
- When implementing IEC 62443-compliant conduit architecture for remote access paths
- When deploying secure remote access for third-party vendor maintenance of ICS equipment
- When building approval-based access workflows for privileged OT system access
- When remediating audit findings about uncontrolled remote access to SCADA systems

**Do not use** for designing the overall Purdue Model segmentation (see implementing-purdue-model-network-segmentation), for deploying IT-only remote access solutions, or for configuring local console access to PLCs.

## Prerequisites

- IT/OT DMZ (Level 3.5) deployed with dual-firewall architecture
- Jump server or privileged access management (PAM) platform (CyberArk, BeyondTrust)
- Multi-factor authentication (MFA) infrastructure for OT remote access users
- Session recording capability for compliance and forensic purposes
- Approval workflow system (ServiceNow, ticketing) for access requests

## Workflow

### Step 1: Design Conduit Architecture for Remote Access

```yaml
# IEC 62443 Conduit Security Architecture for OT Remote Access
# All remote access terminates in DMZ - never passes through to OT directly

conduit_architecture:
  remote_access_conduit:
    conduit_id: "RA-001"
    source_zone: "Enterprise IT (Level 4)"
    destination_zone: "OT DMZ (Level 3.5)"
    security_level_target: "SL3"

    components:
      external_gateway:
        type: "VPN Concentrator"
        location: "Enterprise DMZ"
        ip: "10.200.1.10"
        protocols: ["IPsec", "SSL-VPN"]
        authentication: "MFA required (certificate + OTP)"

      dmz_jump_server:
        type: "Privileged Access Workstation"
        location: "OT DMZ (Level 3.5)"
        ip: "10.10.150.20"
        os: "Windows Server 2022 (hardened)"
        controls:
          - "Local admin accounts disabled"
          - "USB ports disabled"
          - "Clipboard transfer disabled by default"
          - "Session recording enabled (all keystrokes and screen)"
          - "Maximum session duration: 4 hours"
          - "Automatic logoff after 15 minutes idle"
          - "Application whitelisting enforced"

      ot_access_gateway:
        type: "Industrial Remote Access Gateway"
        location: "OT DMZ / Level 3 boundary"
        ip: "10.10.150.25"
        controls:
          - "Only pre-approved destination IPs reachable"
          - "Protocol-level filtering (RDP, SSH, VNC only)"
          - "Time-limited sessions with automatic expiry"
          - "Approval-based access (plant manager must authorize)"

    data_flow:
      - step: 1
        description: "User authenticates via enterprise VPN with MFA"
        source: "Remote user"
        destination: "VPN concentrator"
        protocol: "IPsec/SSL-VPN"
      - step: 2
        description: "User connects to jump server in OT DMZ"
        source: "VPN tunnel"
        destination: "DMZ jump server"
        protocol: "RDP with NLA"
      - step: 3
        description: "From jump server, user accesses specific OT system"
        source: "DMZ jump server"
        destination: "Approved OT target"
        protocol: "RDP/SSH/VNC"
        condition: "Only after manager approval and within time window"

    prohibited_flows:
      - "Direct VPN tunnel from external to Level 1/2 OT devices"
      - "Split tunneling allowing internet access during OT session"
      - "File transfer from jump server to OT without scanning"
      - "Persistent VPN connections (auto-reconnect disabled)"

  vendor_access_conduit:
    conduit_id: "VA-001"
    source_zone: "Vendor External Network"
    destination_zone: "OT DMZ (Level 3.5)"
    security_level_target: "SL3"

    workflow:
      request:
        - "Vendor submits access request via portal (24h advance)"
        - "Request includes: purpose, target systems, duration, personnel"
        - "Plant operations manager reviews and approves/rejects"
        - "Time-limited credentials generated upon approval"
      session:
        - "Vendor connects via dedicated vendor VPN gateway"
        - "MFA authentication (vendor receives OTP via SMS/app)"
        - "Session lands on vendor-specific jump server (isolated from internal jump)"
        - "All actions recorded (video + keystroke logging)"
        - "OT engineer monitors vendor session in real-time"
      termination:
        - "Session auto-terminates at approved end time"
        - "Credentials automatically revoked"
        - "Session recording archived for 90 days"
        - "Access log forwarded to SIEM"
```

### Step 2: Implement Access Control and Monitoring

```python
#!/usr/bin/env python3
"""OT Remote Access Conduit Manager.

Manages approval-based remote access to OT systems through
secure conduit architecture with session recording, MFA
enforcement, and time-limited access windows.
"""

import json
import sys
from datetime import datetime, timedelta
from typing import Dict, List, Optional
from enum import Enum


class AccessRequestStatus(Enum):
    PENDING = "pending"
    APPROVED = "approved"
    REJECTED = "rejected"
    ACTIVE = "active"
    EXPIRED = "expired"
    REVOKED = "revoked"


class RemoteAccessRequest:
    """Represents an OT remote access request."""

    def __init__(self, requestor: str, requestor_type: str, purpose: str,
                 target_systems: List[str], duration_hours: int,
                 requested_start: str):
        self.id = f"OT-RA-{datetime.now().strftime('%Y%m%d-%H%M%S')}"
        self.requestor = requestor
        self.requestor_type = requestor_type  # "internal_engineer" or "vendor"
        self.purpose = purpose
        self.target_systems = target_systems
        self.duration_hours = duration_hours
        self.requested_start = requested_start
        self.status = AccessRequestStatus.PENDING
        self.created = datetime.now().isoformat()
        self.approved_by = None
        self.session_id = None
        self.audit_trail = []

    def approve(self, approver: str, conditions: str = ""):
        """Approve the access request."""
        self.status = AccessRequestStatus.APPROVED
        self.approved_by = approver
        self.audit_trail.append({
            "timestamp": datetime.now().isoformat(),
            "action": "APPROVED",
            "actor": approver,
            "conditions": conditions,
        })

    def reject(self, rejector: str, reason: str):
        """Reject the access request."""
        self.status = AccessRequestStatus.REJECTED
        self.audit_trail.append({
            "timestamp": datetime.now().isoformat(),
            "action": "REJECTED",
            "actor": rejector,
            "reason": reason,
        })


class OTConduitManager:
    """Manages OT remote access conduit security."""

    def __init__(self):
        self.access_requests: Dict[str, RemoteAccessRequest] = {}
        self.active_sessions: Dict[str, dict] = {}
        self.policy = self._load_policy()

    def _load_policy(self) -> dict:
        """Load remote access policy."""
        return {
            "max_session_hours": 4,
            "idle_timeout_minutes": 15,
            "mfa_required": True,
            "session_recording": True,
            "clipboard_transfer": False,
            "file_transfer": "scan_required",
            "advance_notice_hours": 24,
            "vendor_escort_required": True,
            "prohibited_targets": ["SIS-*", "SAFETY-*"],
            "allowed_protocols": ["RDP", "SSH", "VNC"],
            "blocked_protocols": ["Telnet", "FTP", "SMB"],
        }

    def submit_request(self, request: RemoteAccessRequest) -> str:
        """Submit a new remote access request."""
        # Validate against policy
        violations = []

        if request.duration_hours > self.policy["max_session_hours"]:
            violations.append(
                f"Duration {request.duration_hours}h exc

Related in Security