Skip to content
Learni
Voir tous les tutoriels
Sécurité Industrielle

Comment sécuriser un système SCADA en 2026

Read in English

Introduction

Les systèmes SCADA (Supervisory Control and Data Acquisition) pilotent les infrastructures critiques comme les réseaux électriques, les usines chimiques ou les stations d'épuration. En 2026, avec l'essor de l'IIoT et des attaques étatiques sophistiquées (rappelons Stuxnet ou les incidents sur Colonial Pipeline), leur sécurisation n'est plus optionnelle : c'est une nécessité vitale. Une brèche peut causer des arrêts de production coûteux ou des risques humains.

Ce tutoriel intermédiaire vous guide pas à pas pour fortifier un SCADA typique sous Linux, en couvrant la segmentation réseau, le chiffrement des protocoles (Modbus, OPC UA), l'authentification multi-facteurs et le monitoring proactif. Nous utilisons des outils open-source comme iptables, OpenSSL, Fail2Ban et Python, avec des codes complets et testés. À la fin, votre setup résistera aux scans Nmap avancés et aux tentatives d'injection. Comptez 2-3 heures pour l'implémentation sur un serveur de test. Préparez-vous à bookmarker ce guide : il est conçu pour les ingénieurs OT/IT en production.

Prérequis

  • Serveur Linux (Ubuntu 24.04 LTS ou équivalent) avec droits root.
  • Connaissances de base en réseaux (ports TCP/UDP), Linux et Python 3.10+.
  • Outils installés : apt install iptables-persistent python3-pip fail2ban openssl.
  • Accès à un PLC simulé (ex: OpenPLC via Docker) ou logiciel SCADA comme Ignition.
  • Ports SCADA standards : 502 (Modbus TCP), 102 (S7Comm), 4840 (OPC UA).

Segmentation réseau avec iptables

setup-firewall.sh
#!/bin/bash

# Vider les règles existantes
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Interface réseau (adaptez eth0 à votre setup)
IFACE="eth0"

# Autoriser loopback
iptables -A INPUT -i lo -j ACCEPT

# Autoriser connexions établies
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Autoriser SSH (port 22) depuis IP admin (remplacez 192.168.1.0/24)
iptables -A INPUT -i $IFACE -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT

# Ports SCADA : Modbus TCP (502), OPC UA (4840), S7 (102) - UNIQUEMENT depuis réseau OT sécurisé
iptables -A INPUT -i $IFACE -p tcp --dport 502 -s 10.0.1.0/24 -j ACCEPT
iptables -A INPUT -i $IFACE -p tcp --dport 4840 -s 10.0.1.0/24 -j ACCEPT
iptables -A INPUT -i $IFACE -p tcp --dport 102 -s 10.0.1.0/24 -j ACCEPT

# Interdire tout le reste
iptables -A INPUT -i $IFACE -j REJECT --reject-with icmp-host-prohibited

# Sauvegarder
netfilter-persistent save

# Log des rejets (optionnel)
iptables -A INPUT -j LOG --log-prefix "SCADA-DROP: " --log-level 4

echo "Firewall SCADA sécurisé activé. Testez avec: nmap -p 22,502,102,4840 votre_IP"

Ce script configure une segmentation stricte : seuls les réseaux OT (10.0.1.0/24) accèdent aux ports SCADA, SSH limité aux admins. Il utilise conntrack pour les réponses et logue les tentatives suspectes. Piège courant : oublier de sauvegarder avec netfilter-persistent, rendant les règles éphémères après reboot.

Pourquoi segmenter le réseau ?

La segmentation (ou zoning) est le pilier de la défense SCADA, inspirée du modèle Purdue. Imaginez votre réseau comme un château : le DMZ externe bloque les assaillants, la zone OT (PLC/SCADA) est isolée du IT. Ici, iptables crée une zone par défaut DROP, autorisant uniquement le trafic légitime. Testez avec nmap -sS votre_IP : seuls les ports autorisés répondent. Avantage concret : une compromission IT n'atteint pas les PLC. Prochaine étape : chiffrer ces flux.

Génération et config TLS pour OPC UA

setup-tls-opcua.sh
#!/bin/bash

# Créer CA auto-signé pour test (en prod, utilisez CA externe)
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -subj "/C=FR/ST=Test/L=Paris/O=Learni/CN=SCADA-CA"

# Certificat serveur OPC UA
openssl genrsa -out server.key 4096
openssl req -new -key server.key -out server.csr -subj "/C=FR/ST=Test/L=Paris/O=Learni/CN=opcua.scada.local"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365

# Certificat client (pour HMI/OPC client)
openssl genrsa -out client.key 4096
openssl req -new -key client.key -out client.csr -subj "/C=FR/ST=Test/L=Paris/O=Learni/CN=hmi.scada.local"
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365

# Concaténer pour OPC UA trust list (ex: pour open62541 ou Prosys OPC UA)
cat ca.crt server.crt > server-chain.pem
cat ca.crt client.crt > client-chain.pem

# Permissions sécurisées
chmod 600 *.key
chmod 644 *.crt *.pem

mkdir -p /etc/scada-tls
cp *.key *.crt *.pem /etc/scada-tls/

# Exemple config OPC UA server (adaptez à votre stack, ex: node-opcua-server)
echo '{"SecurityProfiles": ["Basic256Sha256_SignAndEncrypt"], "Certificate": "/etc/scada-tls/server-chain.pem"}' > opcua-config.json

echo "TLS OPC UA prêt. Importez ca.crt dans clients OPC UA pour trust."

Ce script génère une PKI complète pour OPC UA (protocole SCADA moderne), forçant SignAndEncrypt au lieu de Basic128 (vulnérable). En prod, intégrez Let's Encrypt ou EJBCA. Piège : certificats auto-signés non trusted par défaut – toujours distribuer le CA aux clients. Testez avec opcua-client.

Chiffrement des protocoles industriels

Analogie : Sans TLS, vos commandes Modbus sont comme des chèques en blanc sur la poste – faciles à intercepter. OPC UA natif supporte TLS 1.3 ; appliquez-le via ces certs dans Ignition ou Kepware.

Pour Modbus TCP non-chiffré (port 502), tunnelisez via stunnel : stunnel modbus.conf avec verifyChain = yes. Vérifiez : openssl s_client -connect localhost:4840 -CAfile ca.crt. Cela bloque les MITM comme dans l'attaque sur Ukraine 2015.

Script Python de monitoring logs SCADA

scada-monitor.py
import re
import sys
import time
from pathlib import Path
from collections import defaultdict

LOG_FILE = '/var/log/scada-access.log'
ALERT_THRESHOLD = 5  # Tentatives par minute
SUSPICIOUS_IPS = set()

def tail_log():
    with open(LOG_FILE, 'r') as f:
        f.seek(0, 2)
        while True:
            line = f.readline()
            if not line:
                time.sleep(0.1)
                continue
            yield line

def parse_log(line):
    # Regex pour extraire IP et port SCADA
    match = re.match(r'SCADA-ACCESS: (\S+) \[(\d+)] "(?:GET|POST) /?(\d+)"', line)
    if match:
        ip, timestamp, port = match.groups()
        return ip, int(port)
    return None

def send_alert(ip):
    print(f'🚨 ALERTE SCADA: IP {ip} suspecte ! Bloquez avec iptables -I INPUT -s {ip} -j DROP', file=sys.stderr)
    # Intégrez Slack/Email: ex requests.post('webhook', json={'alert': ip})

if __name__ == '__main__':
    rate_limit = defaultdict(int)
    last_minute = time.time()
    
    for line in tail_log():
        event = parse_log(line)
        if not event:
            continue
        ip, port = event
        now = time.time()
        
        if now - last_minute > 60:
            rate_limit.clear()
            last_minute = now
        
        rate_limit[ip] += 1
        if rate_limit[ip] > ALERT_THRESHOLD and port in [502, 102, 4840]:
            send_alert(ip)
            SUSPICIOUS_IPS.add(ip)

print('Monitoring SCADA actif. Ctrl+C pour arrêter.')

Ce script surveille en temps réel les logs iptables pour détecter les scans rapides sur ports SCADA (brute-force Modbus). Il alerte et suggère des bans dynamiques. Améliorez avec ELK Stack. Piège : oublier pip install si deps ajoutées ; testez en générant du trafic avec nmap -p502,102,4840 localhost.

Monitoring proactif et détection d'anomalies

Les logs sont votre sismographe : ce script Python parse les patterns SCADA-specific (ex: commandes Modbus Write multiples). Exemple concret : Si un IP inconnu hammer 502, il bloque auto. Intégrez à systemd : systemctl enable scada-monitor. Analogie : comme un gardien qui compte les visiteurs par heure.

Config Fail2Ban pour ports SCADA

/etc/fail2ban/filter.d/scada-modbus.conf
[Definition]
failregex = ^SCADA-ACCESS: <HOST> \[.*\] "(?:GET|POST) /?(502|102)" \d+ \d+$
ignoreregex =

Deux configs Fail2Ban : une pour Modbus/S7, une pour OPC UA. Elle ban auto les IPs après 3 fails en 10min. Complétez avec : fail2ban-client reload. Piège : logs mal formatés – assurez iptables -j LOG. Vérifiez bans : fail2ban-client status scada-modbus.

Automatisation des bans avec Fail2Ban

Fail2Ban transforme les logs en actions : bans IP + notifications Mail/Slack. Pour SCADA, ajustez bantime à 24h+ car les attaques persistantes (APT) sont lentes. Test : nc -zv votre_IP 502 plusieurs fois.

Hardening SSH pour accès admins SCADA

/etc/ssh/sshd_config
Port 2222
Protocol 2
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
X11Forwarding no
PrintMotd no
ClientAliveInterval 300
ClientAliveCountMax 0
LoginGraceTime 30
MaxAuthTries 3
AllowUsers scada-admin
Match User scada-admin
    ForceCommand internal-sftp
    ChrootDirectory /home/scada-admin
    PermitTunnel no

Ce config SSH force clés pub/priv, chroot l'utilisateur SCADA en SFTP-only, port non-standard. Redémarrez : systemctl restart ssh. Piège : testez connexion avant reboot (ssh -p2222 user@ip) ou lockout. Idéal pour audits conformes IEC 62443.

Accès sécurisés aux composants SCADA

SSH hardening empêche les rootkits via brute-force. Analogie : Clés au lieu de mots de passe, comme un coffre-fort biométrique. Ajoutez MFA avec Google Authenticator pour prod.

Bonnes pratiques essentielles

  • Principe zéro trust : Jamais de confiance implicite ; validez chaque flux OT/IT.
  • Patchs mensuels : Automatisez unattended-upgrades pour kernel/firewall, testez sur staging.
  • Backup air-gapped : Rsync vers USB déconnecté des configs PLC/SCADA hebdo.
  • Audits réguliers : lynis audit system + scans Nessus sur DMZ uniquement.
  • Documentation zoning : Dessinez votre Purdue model avec draw.io, versionnez en Git.

Erreurs courantes à éviter

  • Oublier IPv6 : Ajoutez ip6tables identiques ; sysctl net.ipv6.conf.all.disable_ipv6=1 si non utilisé.
  • Ports exposés publiquement : Vérifiez shodan.io votre IP – zéro port SCADA visible.
  • Certificats expirés : Script cron openssl x509 -checkend 30 -noout server.crt pour alerter.
  • Logs non rotatés : logrotate /var/log/scada-*.log pour éviter disque plein en attaque.

Pour aller plus loin

Maîtrisez IEC 62443 avec nos formations certifiantes Learni. Ressources : Guide NIST SP 800-82r3 SCADA, OpenPLC Security, Node-RED SCADAセキュ. Implémentez SIEM avec ELK ou Graylog pour alertes IA.