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-pattern | Pourquoi ç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érence | Rôle | Quantité |
|---|---|---|
6ES7517-3FP00-0AB0 — S7-1517F-3 PN/DP | CPU Unité A (SIL 2) | 1 |
6ES7518-4FP00-0AB0 — S7-1518F-4 PN/DP | CPU Unité B (SIL 3) | 1 |
6GK5208-0BA00-2AC2 — SCALANCE XC208 | Switch managé industriel (1× par zone : A, DMZ, B) | 3 |
6GK5632-2GS00-2AC2 — SCALANCE SC632-2C | Firewall industriel L3 / DPI OPC UA (FW1 entre A↔DMZ, FW2 entre DMZ↔B) | 2 |
6AG4112-2HH40-1AS2 — IPC547G | PC industriel pour proxy OPC UA dans la DMZ | 1 |
Principes architecturaux à retenir :
- 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.
- Aucun flux direct A ↔ B. Toute communication passe par le proxy, et chaque firewall n’autorise qu’un seul flux unidirectionnel.
- 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.
- 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é.
- 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éseau | VLAN | Usage | Hosts autorisés |
|---|---|---|---|
10.20.10.0/24 | 10 | OT Unité A (PROFINET, S7) | CPU A, IHM A, capteurs distribués A |
10.20.20.0/24 | 20 | OT Unité B (PROFINET, S7) | CPU B, IHM B, capteurs distribués B |
10.20.99.0/24 | 99 | DMZ industrielle | Proxy OPC UA, jump server, NDR |
10.20.100.0/24 | 100 | Management des switches/firewalls | Console 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 :
- Protection & Security → Connection mechanisms : décocher
Permit access with PUT/GET communication. (On désactive S7 legacy — on ne passera QUE par OPC UA.) - OPC UA → Server → General : activer
Activate OPC UA server. Port4840(standard). - OPC UA → Server → Security :
Security policy:Basic256Sha256 — Sign and Encryptuniquement. Décocher toutes les politiquesNoneetSign only.User authentication: décocherAllow guest access. CocherAllow authentication via user name and password+ activer la liste d’utilisateurs.- Créer un utilisateur dédié, ex :
opcua-proxy-readonlyavec un mot de passe fort stocké en coffre-fort (Vault, CyberArk).
- 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-onlysur 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.10→ OK : la règle FW1 le permet. - Depuis le proxy DMZ,
ping 10.20.20.10→ timeout : 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
Writemê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
| Test | Méthode | Résultat attendu |
|---|---|---|
| Lecture variable depuis B | Bloc OPC UA Client dans CPU B → lit UnitA.T_Coupe1 | Valeur correcte, latence < 200 ms |
| Ping direct CPU B → CPU A | ping 10.20.10.10 depuis IPC en VLAN 20 | Timeout (refusé par firewall) |
| Tentative d’écriture depuis B | OPC UA Write call vers une variable de A | BadUserAccessDenied |
| Tentative de browsing massif | Script qui browse 10 000 nodes en 1 s | Blocage DPI au-delà de 100 req/s, alerte SIEM |
| Faux certificat client | Connexion 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
- « Just pour ce test » — on ajoute une règle firewall
allow any any5 minutes pour déboguer. On l’oublie. Elle reste 3 ans. Toujours rouvrir un ticket et lever la règle après débogage. - 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.
- Compte
opcua-proxy-readonlypartagé 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). - Pas de logique fallback côté B : si le proxy tombe, la régulation B reçoit des valeurs
Badet part en sécurité — arrêt non planifié. Toujours implémenterif quality != Good then use_last_known_value. - 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.
- 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.