Skip to main content
The respuesta_activa.py module implements the active response layer of the IPS. When the IDS engine decides an IP must be blocked, it calls bloquear_ip(), which creates a Windows Firewall inbound rule via PowerShell, schedules automatic unblocking, and logs every action.
This module issues powershell commands that modify the Windows Firewall. It requires the application to be run as Administrator. Without elevated privileges, the firewall command fails and the block is recorded as SIMULADO in SQLite instead of being enforced.

Functions

bloquear_ip

respuesta_activa.py
def bloquear_ip(ip, duracion_minutos=30):
Creates a Windows Firewall inbound block rule for the given IP and schedules automatic removal.
respuesta_activa.py
nombre_regla = f"IDS_BLOCK_{ip}"

comando = (
    f"New-NetFirewallRule -DisplayName '{nombre_regla}' "
    f"-Direction Inbound -Action Block -RemoteAddress {ip} "
    f"-Description 'Bloqueo automático IDS UNIPAZ'"
)
The PowerShell command uses New-NetFirewallRule to create the rule. The rule display name follows the convention IDS_BLOCK_{ip} (e.g. IDS_BLOCK_192.168.1.50), which is also used as the identifier for removal.
ip
str
The IP address to block. Passed directly to -RemoteAddress in the firewall rule.
duracion_minutos
int
default:"30"
How long (in minutes) to keep the block active. A daemon thread calls desbloquear_ip() after this duration. The IDS engine always passes 60 minutes.
Return value: True if the firewall rule was created successfully, False otherwise. After a successful block, bloquear_ip also:
  • Calls registrar_bloqueo(ip, "BLOQUEO_AUTOMATICO", duracion_minutos) to append to logs_bloqueos.txt.
  • Starts a daemon thread running programar_desbloqueo(ip, duracion_minutos).

desbloquear_ip

respuesta_activa.py
def desbloquear_ip(ip):
Removes the inbound block rule created by bloquear_ip.
respuesta_activa.py
nombre_regla = f"IDS_BLOCK_{ip}"
comando = f"Remove-NetFirewallRule -DisplayName '{nombre_regla}'"
Uses Remove-NetFirewallRule with the same naming convention. If the rule no longer exists (e.g. it was already removed manually), the PowerShell command returns a non-zero exit code. This is treated as a non-fatal warning rather than an error. Return value: True if the rule was removed, False if the command failed. After a successful unblock, registrar_bloqueo(ip, "DESBLOQUEO_AUTOMATICO") is called.

programar_desbloqueo

respuesta_activa.py
def programar_desbloqueo(ip, minutos):
    time.sleep(minutos * 60)
    desbloquear_ip(ip)
Runs in a daemon thread (daemon=True). Sleeps for minutos * 60 seconds, then calls desbloquear_ip(). Because the thread is daemonized, it is automatically killed if the main process exits — the firewall rule will persist until manually removed or the system restarts.
If the application is closed before the timer expires, the firewall rule remains active until removed manually via PowerShell or Windows Defender Firewall UI. To remove all IDS rules at once: Get-NetFirewallRule -DisplayName 'IDS_BLOCK_*' | Remove-NetFirewallRule

registrar_bloqueo

respuesta_activa.py
def registrar_bloqueo(ip, accion, duracion=None):
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    msg = f"[{timestamp}] IP: {ip} | Acción: {accion}"
    if duracion:
        msg += f" | Duración: {duracion} min"

    with open(LOG_BLOQUEOS, "a", encoding="utf-8") as f:
        f.write(msg + "\n")
Appends one line per action to logs_bloqueos.txt in the project root. The accion string is either "BLOQUEO_AUTOMATICO" or "DESBLOQUEO_AUTOMATICO".

Blocking criteria

The decision to call bloquear_ip() is made inside guardar_ataque() in ids.py. The IPS must be enabled (ips_activo = True) and the event must meet the criticality threshold:
ids.py
t_lower = tipo_final.lower()
es_critico = (
    "exploit" in t_lower or
    "sql"     in t_lower or
    "flood"   in t_lower or
    "ddos"    in t_lower or
    "escaneo" in t_lower
)
When es_critico is True, the block decision follows this logic:
  • If the event label contains "(ml:" → block only if ML confidence ≥ 70%.
  • If the event label contains "(heurística)" → block unconditionally (heuristic certainty is sufficient).

Severity levels

The severity string is stored in the bloqueos table and displayed in the IPS panel:
SeverityTrigger condition
CRITICA"exploit" or "sql" in the attack label
ALTA"flood" or "ddos" in the attack label
MEDIA"escaneo" or "scan" in the attack label
If none of these keywords match (unlikely given es_critico), the default severity is ALTA.

Simulated blocking

When the application is not running as Administrator, the PowerShell command fails and bloquear_ip() returns False. The engine handles this gracefully:
ids.py
bloqueo_real = False
try:
    bloqueo_real = respuesta_activa.bloquear_ip(ip_src, duracion)
except Exception as e:
    print(f"[!] Bloqueo en firewall no disponible (requiere admin): {e}")

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)
)
The IPS panel always shows the block event. The Estado column displays SIMULADO instead of ACTIVO when no firewall rule was created, so SOC analysts are aware that the block is not enforced at the network level.

Build docs developers (and LLMs) love