Skip to main content
The IDS/IPS UNIPAZ ML system is a real-time network intrusion detection and prevention tool built in Python. It combines Scapy packet capture, six purpose-built heuristic attack detectors, and a trained ensemble machine learning model to classify and block malicious traffic — all surfaced through a PyQt5 SOC dashboard. It was designed and refined at UNIPAZ, addressing the specific constraints of a Windows-first campus network: low-level packet capture via Npcap, admin-aware firewall integration, and a GUI that stays responsive while the sniffer runs in a background thread.

Who Is This For?

AudienceUse case
Security operatorsMonitor live network traffic, review the IPS block table, and manually unblock IPs
SOC analystsInvestigate detected attack events stored in SQLite with full metadata (timestamp, IP, protocol, port, confidence)
StudentsLearn how a real IDS is structured — from raw packet parsing through ML inference to firewall enforcement
ResearchersRetrain the ensemble model on new datasets using CEREBRO.py, or extend the heuristic detectors in ids.py

Core Capabilities

6 Attack Detectors

Heuristic rules for SYN Flood, DDoS, Port Scan, Exploit attempts, SQL Injection, and UDP Flood — each tuned to avoid false positives on normal browsing traffic.

ML Classification

A VotingClassifier ensemble (Random Forest + MLP + XGBoost) trained with SMOTE balancing on 20,000 synthetic records. Achieves 91.90% accuracy. Predictions are shown inline with confidence percentages, e.g. SYN Flood (ML: 98.4%).

Automatic IP Blocking

The IPS layer calls New-NetFirewallRule via PowerShell to create inbound block rules. Blocks auto-expire after 60 seconds via a daemon thread. Falls back to “Bloqueo simulado” when not running as Administrator.

Telegram Alerts

Every confirmed attack triggers an async HTTP POST to the Telegram Bot API. Runs in a daemon thread so HTTP latency never stalls packet capture.

SOC GUI Dashboard

A PyQt5 window with a live traffic panel, an events table with per-attack-type color coding, an IPS block table with live countdowns, and an embedded Matplotlib chart — all updated via Qt signals across threads.

SQLite Persistence

All detected attacks are written to an ataques table and all blocks to a bloqueos table in intrusiones.db. Parametric placeholders prevent second-order SQL injection into the IDS’s own database.

Key Design Decisions

Graceful degradation — heuristic fallback

Every ML component is loaded inside a try/except block. If any .pkl file is missing, the corresponding variable is set to None and the system continues with heuristic-only detection:
# ids.py
try:
    modelo_ml = joblib.load(ruta_modelo)
    print("[OK] Modelo de Machine Learning cargado correctamente.")
except FileNotFoundError:
    print(f"[X] Error: no se encontró {ruta_modelo}")
    modelo_ml = None  # El sistema usará solo detección heurística
This means the system is operational even during initial setup before the model has been trained.

Confidence-gated ML verdicts

The system does not blindly trust the ML model. The 70% confidence threshold governs how labels are composed:
# ids.py — guardar_ataque()
if pred_ml and pred_ml != "Normal" and confianza >= 0.70:
    tipo_final = f"{pred_ml} (ML: {confianza*100:.1f}%)"
else:
    tipo_final = f"{tipo_ataque} (Heurística)"
This design deliberately preserves heuristic authority. A confirmed heuristic hit on a critical attack type (exploit, flood, SQLi) triggers a block even when the ML is uncertain — preventing the IPS from being silenced by low model confidence.

Whitelist and CIDR filtering

To avoid false-positive alerts on CDN and cloud traffic, the exploit and SQL injection detectors check every source IP against an explicit set and a list of CIDR ranges before firing:
# ids.py
IPS_CONFIABLES = {
    "104.22.1.235",  # Cloudflare
    "2.22.20.72",    # Akamai
    # ...
}

RANGOS_CONFIABLES = [
    ipaddress.ip_network('104.16.0.0/12'),   # Cloudflare
    ipaddress.ip_network('140.82.0.0/16'),   # GitHub
    ipaddress.ip_network('34.192.0.0/12'),   # Google Cloud
    # ...
]

Thread-safe Qt signal architecture

Scapy’s AsyncSniffer runs in its own thread. The PyQt5 UI runs in the main thread. Direct cross-thread widget calls are not safe in Qt. ComunicadorIDS solves this by acting as a signal bus — the sniffer thread emits, the UI slot receives, and Qt’s event loop marshals the call safely:
# ids.py
class ComunicadorIDS(QObject):
    nuevo_evento  = pyqtSignal(list)   # Attack event data
    nuevo_bloqueo = pyqtSignal(list)   # IPS block action
    nuevo_trafico = pyqtSignal(str)    # Raw packet summary for the live panel

comunicador = ComunicadorIDS()  # Global singleton — shared across all modules

Admin-aware simulated blocking

If the process is not running with Administrator privileges, New-NetFirewallRule will fail. Rather than crashing or silently ignoring the failure, the system records 'SIMULADO' in the bloqueos table and emits a “Bloqueo simulado” event to the IPS panel, preserving full audit visibility:
# ids.py — guardar_ataque()
estado_bd = 'ACTIVO' if bloqueo_real else 'SIMULADO'
cursor.execute(
    'INSERT INTO bloqueos (timestamp, ip_src, tipo_ataque, duracion, estado) VALUES (?, ?, ?, ?, ?)',
    (timestamp, ip_src, tipo_final, duracion, estado_bd)
)

Build docs developers (and LLMs) love