diff --git a/vigilancia/asus_api_control.py b/vigilancia/asus_api_control.py index 97a8936..5da1624 100644 --- a/vigilancia/asus_api_control.py +++ b/vigilancia/asus_api_control.py @@ -144,7 +144,12 @@ def cambiar_bloqueo(nombre, blocked): mac = vivo[1] etiqueta = f"{etiqueta} [{vivo[2]} {vivo[0]}]" asyncio.run(_set_block(mac, device["name"], blocked)) - return f"{'Bloqueado' if blocked else 'Activado'}: {etiqueta} ({mac})" + base = f"{'Bloqueado' if blocked else 'Activado'}: {etiqueta} ({mac})" + try: + from router_control import bloqueo_red + return f"{base}\n{bloqueo_red(nombre, mac, blocked)}" + except Exception as e: + return f"{base}\n⚠️ Sin verificacion de red: {e}" async def _aimesh_data(): diff --git a/vigilancia/router_control.py b/vigilancia/router_control.py index f0a10b3..2e640b0 100644 --- a/vigilancia/router_control.py +++ b/vigilancia/router_control.py @@ -143,6 +143,59 @@ def reiniciar(): return _run("reboot") +def _ip_actual(nombre, mac): + """IP vigente del dispositivo: primero lease en vivo (por MAC o por + nombre), si no la reserva DHCP fija. Devuelve (ip, origen) o (None, _).""" + try: + from asus_api_control import normalizar_nombre + except Exception: + normalizar_nombre = lambda x: (x or "").lower() # noqa + try: + devices, by_mac = _inventario() + except Exception: + devices, by_mac = [], {} + mac = (mac or "").upper() + for ip, m, _nombre in devices: + if m == mac: + return ip, "lease en vivo" + pistas = [p for p in (normalizar_nombre(nombre),) if p] + for ip, m, _nombre in devices: + n = normalizar_nombre(_nombre) + if any(p and (p in n or n in p) for p in pistas): + return ip, f"lease en vivo ({_nombre})" + if mac and by_mac.get(mac): + return by_mac[mac], "reserva DHCP" + return None, None + + +def bloqueo_red(nombre, mac, blocked): + """Corta (o reabre) internet por IP+MAC en iptables y lo verifica. + Asi el bloqueo aguanta aunque la tablet rote la MAC: la IP fija cae + siempre y la MAC vigente tambien. Devuelve texto de verificacion.""" + ip, origen = _ip_actual(nombre, mac) + if not ip: + return "⚠️ Sin IP localizada: solo regla parental aplicada." + mac = (mac or "").upper() + if blocked: + _run(f"iptables -C FORWARD -s {ip} -j DROP 2>/dev/null || " + f"iptables -I FORWARD -s {ip} -j DROP") + if mac: + _run(f"iptables -C FORWARD -m mac --mac-source {mac} -j DROP " + f"2>/dev/null || iptables -I FORWARD -m mac " + f"--mac-source {mac} -j DROP") + else: + _run(f"iptables -D FORWARD -s {ip} -j DROP 2>/dev/null; " + f"iptables -D FORWARD -m mac --mac-source {mac} -j DROP " + f"2>/dev/null; true") + comprueba = _run(f"iptables -C FORWARD -s {ip} -j DROP 2>/dev/null " + f"&& echo CORTADO || echo ABIERTO") + if blocked: + estado = "CORTADO ✅" if "CORTADO" in comprueba else "FALLO ❌" + return f"🌐 IP {ip} ({origen}): internet {estado}." + estado = "ABIERTO ✅" if "ABIERTO" in comprueba else "SIGUE CORTADO ❌" + return f"🌐 IP {ip} ({origen}): internet {estado}." + + QOS_TIPOS = { "0": "Traditional (por prioridades)", "1": "Adaptive (auto gaming/streaming)",