Introduction
Les systèmes OT (Operational Technology) et ICS (Industrial Control Systems) comme SCADA, PLC et RTU pilotent les infrastructures critiques : énergie, eau, manufacturing. En 2026, les attaques comme Triton ou Industroyer soulignent l'urgence d'une cybersécurité dédiée, distincte de l'IT classique. Contrairement aux réseaux IT, les OT priorisent la disponibilité (99,999% uptime) sur la confidentialité, avec des protocoles legacy non chiffrés (Modbus, DNP3, Profibus).
Ce tutoriel avancé vous guide pas à pas pour implémenter une défense en profondeur : identification des assets, segmentation Purdue, détection d'anomalies via IDS/IPS, et monitoring temps réel. Chaque étape inclut du code complet, fonctionnel sur Linux (ex: Ubuntu Server en bastion OT). À la fin, vous disposerez d'une stack sécurisée, conforme NIST 800-82 et IEC 62443, prête pour production. Idéal pour ingénieurs cybersécurité industrielle bookmarkant des références actionnables. (128 mots)
Prérequis
- Linux (Ubuntu 22.04+ LTS) avec droits root
- Connaissances avancées : réseaux industriels (Purdue Model), protocoles ICS (Modbus TCP, DNP3), Python 3.10+
- Outils installés : Nmap 7.9+, Wireshark 4.0+, Scapy 2.5+
- Accès lab virtuel (VMware/ Proxmox) simulant PLC (ex: OpenPLC)
- Lecture : NIST SP 800-82r3
Installation des outils essentiels
#!/bin/bash
apt update && apt upgrade -y
apt install -y nmap wireshark sniffer tcpdump python3 python3-pip snort iptables-persistent netfilter-persistent
pip3 install scapy pyshark
systemctl enable snort
ufw enable
echo 'Installation terminée. Vérifiez avec: nmap --version'Ce script bash unifie l'installation des outils clés pour OT/ICS : Nmap pour scanning passif/agressif, Wireshark/Scapy pour analyse protocoles, Snort pour IDS, iptables pour segmentation. Exécutez-le sur un bastion dédié (niveau 3 Purdue). Piège : activez 'sniffer' pour Wireshark non-root ; persistance iptables évite redémarrages.
Modèle Purdue et scanning initial
Adoptez le modèle Purdue pour segmenter : niveau 0-2 (OT pur), 3 (DMZ), 4-5 (IT). Commencez par un scan passif pour éviter DoS sur PLC sensibles. Identifiez assets : PLC (ports 502 Modbus), HMI (80/443), RTU (20000 DNP3).
Scan Nmap passif et actif ICS
#!/bin/bash
NETWORK="192.168.1.0/24" # Remplacez par votre réseau OT
# Scan passif (TCP SYN stealth)
nmap -sS -T2 --top-ports 100 -O -sV $NETWORK -oN nmap-passif.txt
# Scan UDP pour DNP3/Modbus (agressif, lab only)
nmap -sU --top-ports 50 -p 102,502,20000 --script=modbus-discover $NETWORK -oN nmap-udp.txt
# Scan spécifique ICS
nmap -p 44818,2222,4480 --script enip-info $NETWORK -oN nmap-ics.txt
echo 'Rapports générés. grep "Modbus" nmap-*.txt'Script Nmap adapté OT : -T2 timing lent évite surcharge PLC ; scripts NSE (modbus-discover, enip-info) détectent vendors (Schneider, Rockwell). Sorties en fichiers pour audit. Piège : scans UDP lents (30min+), testez lab-only ; intégrez à cron pour monitoring périodique.
Segmentation réseau avec iptables
Segmentez niveaux Purdue : bloquez tout IT->OT sauf flux autorisés (ex: OPC UA chiffré). Utilisez VLANs + firewalls stateful. Règle d'or : Data Diodes pour flux unidirectionnels (OT->IT monitoring uniquement).
Configuration iptables pour segmentation OT
#!/bin/bash
iptables -F
iptables -t nat -F
# Variables
OT_NET="192.168.10.0/24" # Niv 0-2
DMZ_NET="192.168.20.0/24" # Niv 3
IT_NET="192.168.1.0/24" # Niv 4-5
# Politique par défaut: DROP
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Autoriser loopback et established
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# OT->DMZ: monitoring SNMP/OPC UA (ports 161,4840)
iptables -A FORWARD -s $OT_NET -d $DMZ_NET -p udp --dport 161 -j ACCEPT
iptables -A FORWARD -s $OT_NET -d $DMZ_NET -p tcp --dport 4840 -j ACCEPT
# Bloquer tout IT->OT
iptables -A FORWARD -s $IT_NET -d $OT_NET -j DROP
netfilter-persistent save
echo 'Segmentation appliquée. iptables -L -v -n'Ce script implémente zero-trust : DROP par défaut, flux whitelistés OT->DMZ uniquement. Conntrack gère réponses. Sauvegarde persistante. Piège : testez avec tcpdump avant prod ; ajustez ports (Modbus 502 bloqué par défaut pour sécurité).
Règles Snort pour détection ICS
alert tcp $OT_NET any -> $OT_NET 502 (msg:"Modbus TCP Scan"; flow:to_server,established; content:"|00 00|"; depth:2; content:"|00 01 00 00|"; distance:2; sid:1000001; rev:1;)
alert udp $OT_NET any -> $OT_NET 20000 (msg:"DNP3 Anomalie"; content:"|05 64|"; sid:1000002; rev:1; classtype:protocol-command-decode;)
alert tcp any any -> $OT_NET 44818 (msg:"EtherNet/IP Unauthorized"; content:"|65 00|"; sid:1000003; rev:1;)
alert icmp $EXTERNAL_NET any -> $OT_NET any (msg:"ICMP Ping Sweep OT"; itype:8; sid:1000004; rev:1; droprule;)
# Activation dans /etc/snort/snort.conf: include $RULE_PATH/ics.rulesRègles Snort custom pour protocoles ICS : détecte scans Modbus/DNP3, accès EtherNet/IP non auth. Classtype et droprule pour IPS. Ajoutez à local.rules. Piège : signatures shallow (pas deep inspection payload sensible) ; testez avec Scapy replay.
Déploiement IDS/IPS et monitoring
Configurez Snort en mode IDS (SPAN port) ou IPS (inline). Intégrez ELK pour SIEM. Pour OT, priorisez anomalies comportementales : trafic volume spike = DoS potentiel.
Script Python monitoring trafic ICS avec Scapy
from scapy.all import *
import sys
import json
from collections import defaultdict
OT_NET = "192.168.10.0/24"
stats = defaultdict(int)
def packet_handler(pkt):
if IP in pkt and pkt[IP].src.startswith('192.168.10.'):
proto = pkt[IP].proto
sport = pkt[TCP].sport if TCP in pkt else pkt[UDP].sport
stats[f'{proto}:{sport}'] += 1
if stats[f'{proto}:{sport}'] > 100: # Anomalie: >100 pkts/sec
print(f'ALERTE: Flood {proto}:{sport} from {pkt[IP].src}')
print('Monitoring OT démarré. Ctrl+C pour arrêter.')
sniff(filter=f'net {OT_NET}', prn=packet_handler, store=0)
# Exemple sortie JSON: with open('stats.json', 'w') as f: json.dump(stats, f)Script Scapy temps réel : sniff trafic OT, compteur par proto/port, alerte flood (>100pkts). Stateful sans DB lourde. Lancez : python3 ics-monitor.py. Piège : root requis ; filtre BPF optimise perf (10Gbps+ capable).
Configuration Suricata YAML pour ICS
%YAML 1.1
---
vars:
address-groups:
OT_NET: "[192.168.10.0/24]"
EXTERNAL_NET: "any"
rule-files:
- /etc/suricata/rules/ics.rules
outputs:
- eve-log:
enabled: yes
filetype: regular
filename: eve.json
types:
- alert:
payload: yes
packet: yes
- anomaly:
enabled: yes
af-packet:
- interface: eth1 # SPAN OT
threads: auto
cluster-id: 99
cluster-type: cluster_flow
defrag: yesConfig Suricata (alternative Snort) : groupes nets, EVE JSON pour ELK, af-packet multithread perf OT. Inclut ics.rules (comme Snort). Piège : defrag=yes pour Modbus fragments ; intégrez Kibana dashboard ICS-specific.
Bonnes pratiques
- Patch management : air-gappé, test lab (ex: PLC snapshots)
- Zero Trust : MFA sur HMI, certificats mTLS pour OPC UA
- Backup offline : 3-2-1 rule, tested quarterly
- Incident Response : playbook IEC 62443, tabletop exercises
- Conformité : auditez NIST 800-82, intégrez Purple Team OT
Erreurs courantes à éviter
- Scanner agressif en prod : cause shutdown PLC (utilisez -T1/-sn)
- Oublier legacy protocols : Modbus clair = MITM facile (forcez VPN IPsec)
- Pas de logging centralisé : alertes Snort perdues (ELK mandatory)
- Ignorer supply chain : firmware PLC vérifié (SBOM + signatures)
Pour aller plus loin
Plongez dans nos formations Learni sur la cybersécurité OT/ICS. Ressources : S4x25 conference, MITRE ICS ATT&CK, outils GrassMarlin (asset mapping), Nozomi Guardian (OT SIEM). Lab gratuit : ICS Village GitHub.