ids.py) is the runtime heart of the system. It captures raw network packets via Scapy, runs each packet through six heuristic detectors in sequence, orchestrates ML classification, persists findings to SQLite and CSV, and pushes thread-safe signals to the GUI.
ComunicadorIDS — Qt signal bus
ComunicadorIDS is a QObject subclass that acts as the message bus between the engine (which runs in the Scapy sniffer thread) and the PyQt5 UI (which runs in the main thread). Using pyqtSignal makes all cross-thread updates safe without locks.
ids.py
| Signal | Type | Consumers |
|---|---|---|
nuevo_evento | list[7] | Events table in the GUI |
nuevo_bloqueo | list[5] | IPS panel in the GUI |
nuevo_trafico | str | ”Tráfico en Vivo” text panel |
Global state variables
| Variable | Type | Purpose |
|---|---|---|
sniffing_activo | bool | Guards against double-starting the sniffer |
ips_activo | bool | Enables or disables the active-response (IPS) path |
sniffer | AsyncSniffer | None | Reference kept so detener_monitoreo() can call .stop() |
ids.py. The GUI toggles ids.ips_activo directly via the IPS checkbox.
IP whitelist
Two collections define trusted sources that are skipped by the exploit and SQL injection detectors.ids.py
IPS_CONFIABLES or add a CIDR block to RANGOS_CONFIABLES. The helper ip_en_rangos(ip) checks membership using Python’s ipaddress module.
The detectors for SYN Flood, DDoS, Port Scan, and UDP Flood do not consult the whitelist — they fire on volume thresholds regardless of source. Only the exploit and SQL injection detectors perform a whitelist check first.
SQLite schema
The engine opensintrusiones.db at startup with check_same_thread=False so the sniffer thread can write directly.
IF NOT EXISTS, so restarting the application is safe and never truncates historical data.
Functions
iniciar_monitoreo
ids.py
AsyncSniffer on the given interface. The sniffer runs in its own internal thread managed by Scapy, so the call returns immediately without blocking the Qt event loop.
Network interface name (e.g.
"Ethernet", "Wi-Fi"). When None, Scapy uses the system default interface.- Sets
sniffing_activo = Truebefore starting (guards re-entry). - Creates
AsyncSniffer(iface=iface, prn=procesar_paquete, store=False)—store=Falseprevents unbounded memory growth. - On failure, resets
sniffing_activo = Falseand prints an error.
detener_monitoreo
ids.py
sniffer.stop() and then sets the reference to None so the object can be garbage collected. Sets sniffing_activo = False.
procesar_paquete
ids.py
prn callback passed to AsyncSniffer. It runs in Scapy’s sniffer thread for every captured packet. The outer try/except ensures that an exception in one detector does not crash the sniffer process.
Only packets with an IP layer are passed to the detectors. Raw Ethernet frames (ARP, etc.) are still forwarded to mostrar_paquete for the live traffic panel.
guardar_ataque
ids.py
- Self-exclusion — returns early if
ip_src == MI_IP(the local machine’s own IP, auto-detected at startup). - Throttle — skips if the same IP triggered an alert within the last
TIEMPO_ENTRE_ALERTAS(2) seconds. - ML classification — calls
clasificar_ataque_ml()whenips_activo and usar_ml. If ML confidence ≥ 70%, uses the ML label; otherwise falls back to the heuristic label. SQL injection detectors passusar_ml=Falsebecause the payload was already analyzed. - SQLite write —
INSERT INTO ataqueswith parameterized placeholders to prevent second-order SQL injection. - CSV write — calls
guardar_evento_en_dataset()to append to the feedback dataset. - Signal emit —
comunicador.nuevo_evento.emit([timestamp, ip_src, ip_dst, puerto, protocolo, flag, tipo_final]). - Telegram alert — fires
_enviar_alerta_async()in a daemon thread. - IPS blocking — if
ips_activoand thees_criticoflag is set, callsrespuesta_activa.bloquear_ip()and emitsnuevo_bloqueo.
Source IP address of the attacking host.
Heuristic label assigned by the detector (e.g.
"SYN Flood", "Posible Exploit").Transport protocol string:
"TCP" or "UDP".Destination port number.
Destination IP address.
TCP flag string from Scapy (e.g.
"S" for SYN, "SA" for SYN-ACK).Set to
False to skip ML classification. Used by the SQL injection detector since the payload analysis already confirms the attack type.preprocesar_datos
ids.py
CEREBRO.py but uses hash(ip) % (10**8) instead of socket.inet_aton because it operates without loading the IP encoders at runtime.
features_seleccionadas.pkl. Unknown protocols or flags fall back to -1.