Le contexte

Une grande raffinerie possède deux unités sensibles :

  • Unité A — Distillation atmosphérique : pilotée par une CPU Siemens S7-1517F-3 PN/DP sur le sous-réseau 10.20.10.0/24. Atmosphère ATEX zone 1, SIL 2 sur les sécurités process.
  • Unité B — Hydrocraqueur : pilotée par une CPU Siemens S7-1518F-4 PN/DP sur le sous-réseau 10.20.20.0/24. Atmosphère ATEX zone 1, SIL 3 sur certaines boucles ESD.

Le besoin métier est simple : l’Unité B doit lire en continu 12 variables process de l’Unité A (températures de coupes, débits, niveau de la colonne) pour optimiser sa propre régulation. Latence acceptable : 200 ms. Pas de commande aller-retour — flux A → B uniquement.

Le besoin cybersécurité ne l’est pas : impossible de mettre les deux automates sur la même plage IP. Une compromission d’A ne doit pas permettre de pivoter vers B. Triton/Trisis (2017) a démontré qu’une fois dans le SIS de l’Unité A, un attaquant aurait pu désactiver les protections explosion.

C’est la situation typique de dizaines de milliers de sites industriels dans le monde.

Ce qu’il NE faut PAS faire

Trois anti-patterns classiques qui résolvent le problème métier mais cassent la posture OT.

Anti-patternPourquoi ça « marche »Pourquoi c’est dangereux
Mettre les 2 CPU sur le même VLAN« Simple, ça communique direct en S7 »Le VLAN n’est pas une vraie segmentation. Un PLC compromis voit l’autre. Et le Put/Get S7 requiert d’autoriser des fonctions dangereuses (force outputs, stop CPU).
Router le trafic via le firewall IT du siège« Le firewall central voit tout »Le firewall IT n’est pas qualifié pour les protocoles industriels. Il laisse passer S7 sans inspection, et il devient un single point of failure. Pire : une coupure WAN coupe la régulation.
VPN site-to-site IPsec entre les deux unités« Tunnel chiffré, isolation logique »Une fois le tunnel monté, les deux réseaux se voient mutuellement. Un ransomware qui chiffre A se propage à B en 30 secondes (cf. NotPetya / Maersk 2017).

Les 3 options OT-compliant

┌────────────────────────────────────────────────────────────────────────────────┐
│  Option 1 — PN/PN COUPLER             ▶ Câblage physique, pas de routage IP   │
│                                                                                │
│    CPU A ── PROFINET ── ┤PN/PN├ ── PROFINET ── CPU B                          │
│                                                                                │
│    + Sécurité maximale (galvanique, isolation absolue)                         │
│    + Aucune configuration IP/firewall — Plug & Play                            │
│    + Certifié pour SIL si on choisit la variante safety                        │
│    − Débit limité (1 408 octets / direction)                                   │
│    − Câble physique direct → adapté aux unités voisines uniquement             │
│    − Pas d'audit ni de logs natifs                                             │
└────────────────────────────────────────────────────────────────────────────────┘

┌────────────────────────────────────────────────────────────────────────────────┐
│  Option 2 — OPC UA via SCALANCE SC + DMZ INDUSTRIELLE      ◀ RECOMMANDÉ ▶     │
│                                                                                │
│  Unité A           ┌───────────── DMZ ───────────┐          Unité B            │
│  10.20.10.0/24     │  10.20.99.0/24              │          10.20.20.0/24     │
│                    │                              │                            │
│  CPU A ───SC1──┤ FW1 │── proxy OPC UA ──┤ FW2 │── SC2 ─── CPU B               │
│   (OPC UA          │                              │            (OPC UA         │
│   server)          │                              │             client)        │
│                                                                                │
│    + Chiffrement Sign + Encrypt OPC UA bout-en-bout                            │
│    + Authentification mutuelle par certificats X.509                           │
│    + Règles firewall fines (un seul port, une seule IP, un seul certificat)    │
│    + Audit complet (qui, quand, quelles variables)                             │
│    + Scalable : on peut ajouter une 3ᵉ unité sans toucher A ni B               │
│    − Configuration plus longue (certificats, règles)                           │
└────────────────────────────────────────────────────────────────────────────────┘

┌────────────────────────────────────────────────────────────────────────────────┐
│  Option 3 — DIODE DE DONNÉES UNIDIRECTIONNELLE                                 │
│                                                                                │
│    CPU A ──TX── ▶▶▶ DIODE ▶▶▶ ──RX── CPU B   (matériel optique)               │
│                                                                                │
│    + Sécurité ultime : remontée physiquement impossible                        │
│    + Idéal nucléaire, défense, sécurité fonctionnelle SIL 4                    │
│    − Coût élevé (10–50 k€ par diode)                                          │
│    − Pas de handshake — il faut un protocole tolérant aux pertes               │
│    − Pas d'acquittement → débogage difficile                                   │
└────────────────────────────────────────────────────────────────────────────────┘

Pour notre cas (flux A → B continu, 12 variables, latence 200 ms, sans nucléaire), l’option 2 est le bon compromis : robuste, auditable, évolutive. C’est ce qu’on déploie.

Architecture retenue — OPC UA + DMZ industrielle

═════════════════════════════════════════════════════════════════════════════════
  UNITÉ A                    DMZ INDUSTRIELLE                       UNITÉ B
  10.20.10.0/24 (VLAN 10)    10.20.99.0/24 (VLAN 99)                10.20.20.0/24 (VLAN 20)
═════════════════════════════════════════════════════════════════════════════════

  CPU S7-1517F-3 PN/DP       IPC547G — Proxy OPC UA                 CPU S7-1518F-4 PN/DP
  10.20.10.10                10.20.99.10                            10.20.20.10
  OPC UA Server,             SIMATIC OPC UA                         OPC UA Client
  port 4840                  Aggregating Server                     → 10.20.99.10
       │                            │                                      │
       │ PROFINET                   │ Ethernet                             │ PROFINET
       │                            │                                      │
  SCALANCE XC208             SCALANCE XC208                         SCALANCE XC208
  10.20.10.20                10.20.99.20                            10.20.20.20
       │                            │                                      │
       │ Ethernet uplink            │                                      │ Ethernet uplink
       │ (fibre)                    │ (DMZ interne)                        │ (fibre)
       │                            │                                      │
  ┌────┴───────────┐                │                              ┌───────┴─────────┐
  │ SCALANCE       │                │                              │ SCALANCE        │
  │   SC632-2C     │                │                              │   SC632-2C      │
  │      FW1       │ ─.99.1 ────────┼─────────────── .99.2─        │      FW2        │
  │ eth0 : .10.1   │                │                              │ eth0 : .99.2    │
  │ eth1 : .99.1   │                                               │ eth1 : .20.1    │
  └────────────────┘                                               └─────────────────┘

═════════════════════════════════════════════════════════════════════════════════
  Allow FW1 : Proxy 10.20.99.10 ──► CPU A 10.20.10.10   tcp/4840  (OPC UA Sign+Encrypt)
  Allow FW2 : CPU B 10.20.20.10 ──► Proxy 10.20.99.10   tcp/4840  (OPC UA Sign+Encrypt)
  Tout autre trafic → DENY + log SIEM
═════════════════════════════════════════════════════════════════════════════════

Composants matériels utilisés :

RéférenceRôleQuantité
6ES7517-3FP00-0AB0 — S7-1517F-3 PN/DPCPU Unité A (SIL 2)1
6ES7518-4FP00-0AB0 — S7-1518F-4 PN/DPCPU Unité B (SIL 3)1
6GK5208-0BA00-2AC2 — SCALANCE XC208Switch managé industriel (1× par zone : A, DMZ, B)3
6GK5632-2GS00-2AC2 — SCALANCE SC632-2CFirewall industriel L3 / DPI OPC UA (FW1 entre A↔DMZ, FW2 entre DMZ↔B)2
6AG4112-2HH40-1AS2 — IPC547GPC industriel pour proxy OPC UA dans la DMZ1

Principes architecturaux à retenir :

  1. La DMZ industrielle (10.20.99.0/24) est un sous-réseau distinct, ni A ni B. C’est elle qui contient le proxy OPC UA — pas A, pas B.
  2. Aucun flux direct A ↔ B. Toute communication passe par le proxy, et chaque firewall n’autorise qu’un seul flux unidirectionnel.
  3. Le proxy agrège : il lit les 12 variables d’A et les expose à B. Si B fait une requête anormale, le proxy refuse — il ne « tunnelise » pas vers A.
  4. Deux firewalls distincts en série — FW1 entre Unité A et DMZ, FW2 entre DMZ et Unité B. C’est la défense en profondeur réseau : compromettre un firewall ne suffit pas à atteindre l’autre unité.
  5. PROFINET reste à l’intérieur de chaque unité (PLC ↔ switch). Le PROFINET RT (couche 2) ne traverse JAMAIS un firewall L3 — c’est OPC UA encapsulé en TCP/IP qui fait le pont entre les zones.

Plan d’adressage et VLAN

Sous-réseauVLANUsageHosts autorisés
10.20.10.0/2410OT Unité A (PROFINET, S7)CPU A, IHM A, capteurs distribués A
10.20.20.0/2420OT Unité B (PROFINET, S7)CPU B, IHM B, capteurs distribués B
10.20.99.0/2499DMZ industrielleProxy OPC UA, jump server, NDR
10.20.100.0/24100Management des switches/firewallsConsole d’admin uniquement

Les VLAN sont configurés sur les SCALANCE XC208 avec trunk vers les SCALANCE SC632-2C. Pas de routage inter-VLAN au niveau switch — c’est le firewall qui décide.

Configuration step-by-step

Étape 1 — Activer OPC UA Server sur la CPU A (TIA Portal V19+)

Dans les propriétés de la CPU S7-1517F :

  1. Protection & Security → Connection mechanisms : décocher Permit access with PUT/GET communication. (On désactive S7 legacy — on ne passera QUE par OPC UA.)
  2. OPC UA → Server → General : activer Activate OPC UA server. Port 4840 (standard).
  3. OPC UA → Server → Security :
    • Security policy : Basic256Sha256 — Sign and Encrypt uniquement. Décocher toutes les politiques None et Sign only.
    • User authentication : décocher Allow guest access. Cocher Allow authentication via user name and password + activer la liste d’utilisateurs.
    • Créer un utilisateur dédié, ex : opcua-proxy-readonly avec un mot de passe fort stocké en coffre-fort (Vault, CyberArk).
  4. OPC UA → Server → Server interfaces : créer une interface qui expose UNIQUEMENT les 12 variables nécessaires (et rien d’autre). On crée un type d’objet personnalisé contenant ces 12 variables.

Le principe Allow-list : on ne publie que ce qui est explicitement nécessaire. Si on publie toute la mémoire CPU, le proxy a beaucoup trop de visibilité.

Étape 2 — Installer le certificat X.509 du proxy sur la CPU A

# Génération du CSR sur la CPU A (TIA Portal)
TIA Portal → CPU A → Certificate Manager →
  Generate certificate signing request (CSR) →
  Subject: CN=cpu-A-opcua, O=Raffinerie, C=FR

# Le CSR est signé par la PKI interne (Microsoft AD CS, HashiCorp Vault,
# ou Siemens SIMATIC Logon Service Center).

# Import du certificat signé sur la CPU A et du certificat du proxy
# dans le "Trusted certificates" de la CPU.

Toujours certificat mutuel. Le proxy authentifie la CPU, la CPU authentifie le proxy. Renouvellement annuel automatisé via la PKI.

Étape 3 — Configurer le proxy OPC UA (Siemens SIMATIC OPC UA aggregating server)

Sur l’IPC547G dans la DMZ, on installe le SIMATIC OPC UA Aggregating Server (alternatives équivalentes : Kepware KEPServerEX, Matrikon UA Tunneller).

# Configuration aggregator (extrait simplifié)
endpoints:
  # Endpoint exposé côté B (interface 10.20.99.10)
  - name: server-for-unit-b
    url: opc.tcp://10.20.99.10:4840
    security: Basic256Sha256
    auth: certificate-only
    allowed_clients:
      - cn=cpu-B-opcua,o=Raffinerie  # SEUL le certificat de B est accepté

  # Client vers CPU A (sortie 10.20.99.10 → 10.20.10.10)
upstream:
  - name: cpu-a
    url: opc.tcp://10.20.10.10:4840
    security: Basic256Sha256
    user: opcua-proxy-readonly
    password_vault: vault://kv/opc-ua/cpu-a

  # Mapping : ce qui est lu côté A est exposé côté B
  variables:
    - source: "ns=3;s=UnitA.T_Coupe1"
      target: "Variables/TCoupe1"
      access: read-only
    - source: "ns=3;s=UnitA.T_Coupe2"
      target: "Variables/TCoupe2"
      access: read-only
    # ... 10 autres

Trois points clés :

  • read-only sur toutes les variables exposées. Même si B est compromis, il ne peut pas écrire dans A.
  • Authentification certificate-only : pas de mot de passe à voler côté B.
  • Logging activé : chaque session, chaque lecture, est journalisée dans le SIEM (via syslog vers Splunk / Wazuh).

Étape 4 — Configurer les deux SCALANCE SC632-2C

Le SCALANCE SC est un firewall industriel L3 qui parle nativement OPC UA (inspection stateful du protocole). On déploie deux firewalls distincts en série — un seul aller-retour par flux, une seule règle allow par firewall.

# ═══════════════════════════════════════════════════════════════
# FW1 — entre Unité A (eth0 = 10.20.10.1) et DMZ (eth1 = 10.20.99.1)
# ═══════════════════════════════════════════════════════════════
# Seul flux autorisé : Proxy DMZ ──► CPU A (lecture OPC UA)
allow  src 10.20.99.10  dst 10.20.10.10  tcp/4840  proto OPC-UA-secure
allow  src 10.20.10.10  dst 10.20.99.10  established              # réponses
deny   src any          dst any          log

# ═══════════════════════════════════════════════════════════════
# FW2 — entre DMZ (eth0 = 10.20.99.2) et Unité B (eth1 = 10.20.20.1)
# ═══════════════════════════════════════════════════════════════
# Seul flux autorisé : CPU B ──► Proxy DMZ (session OPC UA cliente)
allow  src 10.20.20.10  dst 10.20.99.10  tcp/4840  proto OPC-UA-secure
allow  src 10.20.99.10  dst 10.20.20.10  established              # réponses
deny   src any          dst any          log

Deux règles allow effectives (une par firewall), tout le reste est refusé et journalisé vers le SIEM. C’est le principe de moindre privilège réseau.

Tests de validation immédiats :

  • Depuis n’importe quel poste de l’Unité A, ping 10.20.20.10 (CPU B) → timeout : FW1 bloque toute sortie non explicitement autorisée. ✓
  • Depuis n’importe quel poste de l’Unité B, ping 10.20.10.10 (CPU A) → timeout : double blocage par FW2 puis FW1. ✓
  • Depuis le proxy DMZ, ping 10.20.10.10OK : la règle FW1 le permet.
  • Depuis le proxy DMZ, ping 10.20.20.10timeout : le proxy n’a JAMAIS besoin d’initier vers B (c’est B qui appelle le proxy). FW2 bloque.

Si l’un de ces 4 tests ne donne pas le résultat attendu, il y a un trou dans la règle de refus — à corriger AVANT de mettre en production.

Étape 5 — Activer Deep Packet Inspection OPC UA

Le SCALANCE SC propose une option DPI qui inspecte le contenu OPC UA en plus de l’en-tête TCP. Avantages :

  • Refuse les requêtes Write même si le port et l’IP sont autorisés
  • Refuse les requêtes vers des nœuds non-autorisés (allow-list de NodeID)
  • Détecte les tentatives de browsing massif (énumération d’attaquant)
# Politique DPI OPC UA appliquée sur le SC632
methods_allowed: [Read, Browse, TranslateBrowsePath]
methods_denied:  [Write, Call, AddNodes, DeleteNodes]
namespace_allow: ["ns=3;s=UnitA.*"]   # uniquement notre allow-list
rate_limit:      "100 req / s"        # détection de browsing brutal

Étape 6 — Activer la sonde NDR / OT-IDS

Un Dragos, Nozomi ou Claroty CTD est branché en mirror port sur le SCALANCE XC208 côté DMZ. Il :

  • Construit l’inventaire automatique (CPU A, CPU B, proxy)
  • Apprend la baseline de trafic OPC UA pendant 7 jours
  • Alerte sur toute déviation : nouveau client, nouvelle variable lue, nouveau pattern temporel

L’IDS OT est ce qui détecte un Triton à temps. Indispensable sous NIS2 (article 21 § 2 b).

Étape 7 — Tester et valider

TestMéthodeRésultat attendu
Lecture variable depuis BBloc OPC UA Client dans CPU B → lit UnitA.T_Coupe1Valeur correcte, latence < 200 ms
Ping direct CPU B → CPU Aping 10.20.10.10 depuis IPC en VLAN 20Timeout (refusé par firewall)
Tentative d’écriture depuis BOPC UA Write call vers une variable de ABadUserAccessDenied
Tentative de browsing massifScript qui browse 10 000 nodes en 1 sBlocage DPI au-delà de 100 req/s, alerte SIEM
Faux certificat clientConnexion avec cert auto-signé non importéBadCertificateUntrusted

Vérifications cyber à effectuer ensuite

  • Inventaire IDS : la CPU A, la CPU B et le proxy apparaissent bien. Aucun équipement inattendu.
  • Logs OPC UA centralisés : 100 % des sessions sont vues côté SIEM, avec horodatage et identité.
  • Test de coupure du proxy : si le proxy tombe, B continue à fonctionner sur sa dernière valeur connue (logique fallback dans le programme CPU B).
  • Rotation des certificats : un cron PKI renouvelle les certificats 30 jours avant expiration.
  • Backup : l’image du proxy IPC547G est sauvegardée air-gapped trimestriellement.
  • Plan d’incident écrit : si A est compromis, qui isole le proxy ? Procédure ≤ 15 min.
  • Audit fournisseur : la maintenance Siemens passe par un jump server PAM (Wallix), pas par accès direct au proxy.

Pièges classiques

  1. « Just pour ce test » — on ajoute une règle firewall allow any any 5 minutes pour déboguer. On l’oublie. Elle reste 3 ans. Toujours rouvrir un ticket et lever la règle après débogage.
  2. Certificat auto-signé sur le proxy en prod. Marche, mais l’avertissement est ignoré par les opérateurs qui finissent par cliquer sur n’importe quoi. Toujours PKI signée.
  3. Compte opcua-proxy-readonly partagé entre tous les proxys. Si un proxy est compromis, le mot de passe permet de lire les autres CPU. Un compte par couple (proxy, CPU).
  4. Pas de logique fallback côté B : si le proxy tombe, la régulation B reçoit des valeurs Bad et part en sécurité — arrêt non planifié. Toujours implémenter if quality != Good then use_last_known_value.
  5. DMZ « pour le moment » sur le même VLAN que l’IT. La DMZ industrielle est une zone DÉDIÉE — ni IT, ni OT. Si on partage avec l’IT, NotPetya peut sauter dedans.
  6. PROFINET en routage : ne JAMAIS router PROFINET RT entre VLAN. Le multicast L2 ne survit pas. PROFINET reste interne à chaque unité, OPC UA fait le pont.

Pour aller plus loin

  • Le hub Cybersécurité OT couvre le modèle Purdue et la section interconnexion multi-sites en détail.
  • Le hub PLC détaille les CPU Siemens S7-1500F et leurs capacités OPC UA.
  • Le hub Bus industriels compare PROFINET, OPC UA et les autres protocoles.
  • La fiche IEC 62443 donne le cadre normatif complet de cette architecture.

Une dernière chose : ce qu’on vient de faire ressemble à du sur-équipement quand on le voit pour la première fois. Quatre interfaces firewall, un proxy, des certificats, du DPI… Comparez au coût d’un Triton sur votre hydrocraqueur. La conversation est rapide.