ソース情報
- リポジトリ
- JohnNuwan/EVA_CORE
- ソースの最終更新活動
- 2026年7月18日 08:30
- 検出された SKILL.md の言語
- フランス語
- スター
- 0
- フォーク
- 0
インストール方法
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
ソースファイルを確認
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
メニュー
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
SOC 職業分類に基づく
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/JohnNuwan/EVA_CORE --skill industrial-ebpf-diagnosticsコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
SKILL.md を表示中
Concevoir et maintenir un watchdog auto-correcteur pour services HTTP — checks de santé, auto-restart, état persistant, rapports et pièges bash.
Serveur de messagerie sécurisé auto-hébergé (Signal-like) avec Flask + WebSocket + AES-256-GCM + pont EVA
ADAM-SENTINEL — Veilleur technologique 24h/24h. Scanne 10 domaines, cree des rapports, met a jour les skills, alerte sur les CVE et breaking changes.
| name | industrial-ebpf-diagnostics |
| description | Diagnostic réseau et filtrage de paquets OT via eBPF. |
| version | 1.0.0 |
| author | EVA |
| license | Privée EVA St-Étienne |
| metadata | {"EVA":{"maturity":"pilot","tags":["ebpf","kernel","networking","ot-security","modbus-tcp","bcc","python"],"related_skills":["low-level-assembly-optimization","industrial-ai-pipeline"]}} |
Vous êtes un ingénieur systèmes et réseaux Linux senior et un expert en cybersécurité industrielle (OT). Votre rôle est de concevoir, développer et déployer des programmes eBPF (Extended Berkeley Packet Filter) en C pour intercepter, analyser et filtrer à ultra-haute vitesse et au niveau du noyau Linux les flux de protocoles industriels (Modbus TCP, OPC UA, S7comm) afin de détecter les anomalies et les intrusions.
Les solutions de supervision réseau classiques (comme Wireshark ou tcpdump) nécessitent la copie de tous les paquets réseau du noyau Linux vers l'espace utilisateur (user space), ce qui engendre une surcharge CPU importante sur les PC industriels d'atelier (Edge).
eBPF permet d'exécuter du code sécurisé directement au sein du noyau Linux (au niveau du socket buffer ou de la couche XDP - eXpress Data Path). L'agent peut ainsi filtrer ou rejeter des requêtes industrielles malveillantes (ex: une commande d'écriture d'automate non autorisée) sans aucun surcoût de copie mémoire.
+------------------------------------+
| USER SPACE |
| Loader Python (BCC) |
+-----------------+------------------+
^
| Ring Buffer (Perf Event)
+-----------------------------------------------------+------------------+
| KERNEL SPACE |
| |
| [Paquet Modbus TCP] ──► [Interface Réseau] ──► [Hook XDP / tc] |
| | |
| ▼ |
| [Vérificateur eBPF] |
| | |
| ▼ |
| [Filtre eBPF (C)] ──► Map Array |
+------------------------------------------------------------------------+
Pour analyser la charge utile Modbus TCP au niveau du noyau, le filtre eBPF doit naviguer manuellement à travers les en-têtes réseau en appliquant des offsets précis :
Ce programme se charge de lire les paquets, de valider de manière sécurisée les accès mémoire (exigence stricte du vérificateur Linux), et d'isoler les commandes d'écriture industrielle.
#include <uapi/linux/ptrace.h>
#include <net/sock.h>
#include <bcc/proto.h>
#include <linux/ip.h>
#include <linux/tcp.h>
// Structure envoyée au user space lors d'une détection
struct modbus_alert_t {
u32 src_ip;
u32 dst_ip;
u16 src_port;
u8 function_code;
u8 unit_id;
};
// Map de type Ring Buffer pour transmettre les alertes
BPF_PERF_OUTPUT(modbus_alerts);
// Compteur global des écritures interceptées
BPF_ARRAY(write_counter, u64, 1);
int monitor_modbus(struct __sk_buff *skb) {
// 1. Accès sécurisé à l'en-tête IP
u32 ip_offset = ETH_HLEN;
// Charger le protocole IP (doit être TCP = 6)
u8 protocol = load_byte(skb, ip_offset + offsetof(struct iphdr, protocol));
if (protocol != IPPROTO_TCP) {
return 0;
}
// Déterminer la longueur de l'en-tête IP dynamiquement (IHL * 4)
u8 ihl = load_byte(skb, ip_offset + offsetof(struct iphdr, ihl)) & 0x0F;
u32 tcp_offset = ip_offset + (ihl * 4);
// 2. Accès à l'en-tête TCP
// Port de destination (Modbus = 502)
u16 dport = load_half(skb, tcp_offset + offsetof(struct tcphdr, dest));
if (dport != 502) {
return 0;
}
u8 data_offset = (load_byte(skb, tcp_offset + offsetof( tcphdr, doff)) & ) >> ;
u32 payload_offset = tcp_offset + (data_offset * );
u8 unit_id = load_byte(skb, payload_offset + );
u8 function_code = load_byte(skb, payload_offset + );
(function_code == || function_code == || function_code == || function_code == ) {
index = ;
u64 *value = write_counter.lookup(&index);
(value) {
__sync_fetch_and_add(value, );
}
{};
alert.src_ip = load_word(skb, ip_offset + offsetof( iphdr, saddr));
alert.dst_ip = load_word(skb, ip_offset + offsetof( iphdr, daddr));
alert.src_port = load_half(skb, tcp_offset + offsetof( tcphdr, source));
alert.function_code = function_code;
alert.unit_id = unit_id;
modbus_alerts.perf_submit(skb, &alert, (alert));
}
;
}
Ce chargeur compile le code eBPF, l'injecte dans le noyau, et résout les adresses réseaux IP et ports (conversion Network Byte Order).
from bcc import BPF
import socket
import struct
# Initialisation du compilateur BCC à la volée
b = BPF(src_file="modbus_filter.c")
# Attachement au raw socket sur l'interface de rebouclage ou Ethernet industrielle
fn = b.load_func("monitor_modbus", BPF.SOCKET_FILTER)
BPF.attach_raw_socket(fn, "eth0")
def network_to_ip(ip_network_order):
"""Convertit un entier 32-bit réseau en chaîne IP standard."""
return socket.inet_ntoa(struct.pack("<I", ip_network_order))
def handle_event(cpu, data, size):
"""Callback recevant les données binaires du noyau."""
# Décodage de la structure modbus_alert_t
# src_ip (u32), dst_ip (u32), src_port (u16), function_code (u8), unit_id (u8)
struct_format = "<IIHBB"
unpacked = struct.unpack(struct_format, data[:struct.calcsize(struct_format)])
src_ip = network_to_ip(unpacked[0])
dst_ip = network_to_ip(unpacked[1])
src_port = socket.ntohs(unpacked[2])
fun_code = unpacked[3]
unit_id = unpacked[4]
print(f"🚨 [CYBER OT] Tentative d'écriture détectée !")
print(f" IP Source : {src_ip}:{src_port} ──► IP Automate : {dst_ip}:502")
print(f" Modbus Unit ID : {unit_id} | Code Fonction : {fun_code}")
# Ouvrir la map d'événements et démarrer l'écoute cyclique
b["modbus_alerts"].open_perf_buffer(handle_event)
()
:
:
b.perf_buffer_poll()
KeyboardInterrupt:
stats = b[]
()
Pour un déploiement de type Cybersécurité, il est crucial de comprendre où attacher le code eBPF selon le besoin :
XDP_DROP pour rejeter instantanément un paquet d'écriture malveillant en moins d'une microseconde.float ou double). Tous les calculs sémantiques doivent être convertis en arithmétique entière ou délégués au user space.skb->data_end. Sur un Socket Filter, préférez toujours les helpers système du compilateur comme load_byte ou load_half qui gèrent ces vérifications de sécurité de manière native.eth0, enp0s3).root (privilèges d'exécution noyau).