Skip to main content
The project includes four test files that cover different layers of the system: network interface discovery, packet capture behavior, IPS blocking logic, and full end-to-end attack simulation.

Test files overview

FileWhat it covers
test_scapy.pyVerifies Scapy can list interfaces and capture packets
test_scapy_l3.pyTests Layer 3 raw socket sniffing on Windows
test_ips_mocked.pyUnit tests for IPS blocking logic with all heavy dependencies mocked
test_ips_simulation.pyIntegration test that exercises guardar_ataque() with a live ML override

Running the tests

test_scapy.py, test_scapy_l3.py, and test_ips_simulation.py interact with the real network stack and require administrator privileges on Windows. test_ips_mocked.py has no network dependency and can run without elevated rights.
# Mocked unit test — no admin required
python test_ips_mocked.py

# Scapy interface and capture verification — requires admin + Npcap
python test_scapy.py

# Layer 3 socket test — requires admin + Npcap
python test_scapy_l3.py

# Integration simulation — requires admin + Windows (uses netsh/PowerShell)
python test_ips_simulation.py

test_ips_mocked.py — IPS blocking logic

This is the primary unit test for the IPS decision engine. It mocks every heavy dependency (Scapy, PyQt5, sklearn, joblib, xgboost) so the test runs in any Python environment without requiring a GPU, trained model files, or a live interface. What it mocks:
sys.modules['joblib'] = MagicMock()
sys.modules['scapy'] = MagicMock()
sys.modules['scapy.all'] = MagicMock()
sys.modules['PyQt5'] = MagicMock()
sys.modules['PyQt5.QtCore'] = MagicMock()
sys.modules['PyQt5.QtWidgets'] = MagicMock()
sys.modules['xgboost'] = MagicMock()
sys.modules['sklearn'] = MagicMock()
# ... and more
Scenario 1 — High-confidence attack (should block): The test simulates an SQL Injection detection with 95% ML confidence. It patches clasificar_ataque_ml to return ("SQL Injection", 0.95) and then calls guardar_ataque(). The test asserts that _ejecutar_comando_firewall was called and that the generated command contains the correct attacker IP.
with patch('ids.clasificar_ataque_ml') as mock_ml:
    mock_ml.return_value = ("SQL Injection", 0.95)

    ids.guardar_ataque(
        ip_src=ip_test,
        tipo_ataque="SQL Injection",
        protocolo="TCP",
        puerto=80,
        ip_dst="192.168.1.1",
        flag="S",
        usar_ml=True
    )

    if mock_fw.called:
        print("[OK] ÉXITO: El sistema intentó bloquear la IP maliciosa.")
Scenario 2 — Low-confidence detection (should not block): The test simulates a borderline port scan with only 40% ML confidence. The test asserts that the firewall command is not called, confirming the system correctly withholds automatic blocking below the confidence threshold.
with patch('ids.clasificar_ataque_ml') as mock_ml:
    mock_ml.return_value = ("Posible Escaneo", 0.40)

    ids.guardar_ataque(
        ip_src=ip_test_safe,
        tipo_ataque="Port Scan",
        protocolo="TCP",
        puerto=443,
        ip_dst="192.168.1.1",
        flag="S",
        usar_ml=True
    )

    if not mock_fw.called:
        print("[OK] ÉXITO: El sistema NO bloqueó la IP debido a la baja confianza.")
The 70% confidence threshold governs when the ML verdict alone triggers a block. When ML confidence is below 70%, the heuristic engine takes over — if the heuristic classifies the event as a critical attack (Exploit, SYN Flood, etc.), the IP is still blocked.

test_ips_simulation.py — Integration simulation

This test exercises the full guardar_ataque() pipeline against real module code (no mocks), using a monkey-patch to control the ML model’s output. It simulates a SQL Injection attack from 10.99.99.99 with 98% model confidence:
ids.clasificar_ataque_ml = lambda *args: ("SQL Injection", 0.98)

ids.guardar_ataque(
    ip_src="10.99.99.99",
    tipo_ataque="SQL Injection",
    protocolo="TCP",
    puerto=80,
    ip_dst="192.168.1.100",
    flag="PA",  # Push Ack — data traffic
    usar_ml=True
)

# Restore original function
ids.clasificar_ataque_ml = original_clasificar
After running, verify results in two places:
  • logs_bloqueos.txt — the block log file should contain an entry for 10.99.99.99.
  • intrusiones.dbbloqueos table — the SQLite database should have a new row for the blocked IP.
This test is designed for Windows. On non-Windows platforms, netsh and PowerShell firewall commands will fail. The test prints a warning if run outside Windows but continues execution.

test_scapy.py — Interface discovery and basic capture

This diagnostic script confirms that Scapy can enumerate network interfaces and capture live packets through Npcap:
from scapy.all import get_if_list, sniff

print("Interfaces detected by Scapy:")
try:
    interfaces = get_if_list()
    for i, iface in enumerate(interfaces):
        print(f"{i}: {iface}")
except Exception as e:
    print(f"Error listing interfaces: {e}")

print("\nAttempting to sniff 5 packets...")
try:
    packets = sniff(count=5, timeout=10)
    print(f"Captured {len(packets)} packets.")
    for p in packets:
        print(p.summary())
except Exception as e:
    print(f"Error sniffing: {e}")
Run this first when setting up a new machine to confirm Npcap is installed and the Scapy driver is working. If it captures 0 packets, the IDS sniffer will also fail to capture traffic.

test_scapy_l3.py — Layer 3 raw socket sniffing

This test verifies the alternative Layer 3 capture path using L3RawSocket, which is a lower-level Windows socket that bypasses the Npcap PCAP layer:
from scapy.all import conf, L3RawSocket, sniff

# Attempt to use L3RawSocket which is native to Windows (needs Admin)
conf.L3socket = L3RawSocket
print(f"Current L3socket: {conf.L3socket}")

def pkt_callback(pkt):
    print(f"Captured: {pkt.summary()}")

print("Sniffing 2 packets at L3...")
sniff(count=2, prn=pkt_callback, timeout=10)
The production IDS uses conf.use_pcap = True (Npcap/Layer 2) rather than L3RawSocket. This test was used during development to diagnose why the original sniffer wasn’t capturing packets on Windows — Layer 3 raw sockets are invisible to the Npcap driver, confirming that sendp() and conf.use_pcap = True are the correct approach.

End-to-end verification

To confirm the complete detection and blocking pipeline is working:
1

Start the IDS

Run python interfasc.py as administrator. Confirm the sniffer starts and the live traffic table is active.
2

Run the simulator

In a second elevated terminal, run python simular_varios_ataques.py. Select an attack mode — DDoS or Port Scan produces the clearest detections.
3

Observe detections

Watch the Tráfico en Vivo table in the IDS interface. New rows should appear with the attack type and ML confidence score within seconds of the packets being sent.
4

Verify the IPS block

Switch to the Respuesta Activa tab. The attacker IP should appear as Bloqueado with a countdown timer. If the system lacks admin rights, the status will show Bloqueo simulado instead — monitoring and alerting still work normally.
5

Check the logs

Confirm the block was recorded in logs_bloqueos.txt and the bloqueos table in intrusiones.db.

Build docs developers (and LLMs) love