Escáner de IP LAN

Home PDF Audio

Escáner de IP LAN

Este script de Python escanea una red local en busca de direcciones IP activas. Utiliza el comando ping para comprobar si un host es accesible y emplea multithreading para acelerar el proceso de escaneo. Un semáforo limita el número de subprocesos concurrentes para evitar sobrecargar el sistema. El script toma una dirección de red (por ejemplo, “192.168.1.0/24”) como entrada e imprime si cada dirección IP de la red está activa o inactiva.

Este script ayuda a identificar dispositivos en la red, como un router mesh TP-LINK que funciona en modo puente cableado, mediante el escaneo de direcciones IP activas.

import subprocess
import ipaddress
import threading
import os
import socket
import argparse

MAX_THREADS = 50  # Número máximo de subprocesos a utilizar

def is_host_up(host, port=None):
    """
    Comprueba si un host está activo usando ping o telnet.
    Si se especifica el puerto, utiliza telnet para comprobar si el puerto está abierto.
    De lo contrario, utiliza ping.
    Devuelve True si el host está activo, False en caso contrario.
    """
    if port:
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(1)
            result = sock.connect_ex((host, port))
            if result == 0:
                return True
            else:
                return False
        except socket.error as e:
            return False
        finally:
            sock.close()
    else:
        try:
            # -c 1: Enviar solo 1 paquete
            # -W 1: Esperar 1 segundo una respuesta
            subprocess.check_output(["ping", "-c", "1", "-W", "1", host], timeout=1)
            return True
        except subprocess.CalledProcessError:
            return False
        except subprocess.TimeoutExpired:
            return False

def scan_ip(ip_str, up_ips, port=None):
    """
    Escanea una sola dirección IP e imprime su estado.
    """
    if is_host_up(ip_str, port):
        print(f"{ip_str} está activa")
        up_ips.append(ip_str)
    else:
        print(f"{ip_str} está inactiva")

def scan_network(network, port=None):
    """
    Escanea una red en busca de hosts activos usando subprocesos, limitando el número de subprocesos concurrentes.
    """
    print(f"Escaneando red: {network}")
    threads = []
    semaphore = threading.Semaphore(MAX_THREADS)  # Limita el número de subprocesos concurrentes
    up_ips = []

    def scan_ip_with_semaphore(ip_str):
        semaphore.acquire()
        try:
            scan_ip(ip_str, up_ips, port)
        finally:
            semaphore.release()

    for ip in ipaddress.IPv4Network(network):
        ip_str = str(ip)
        thread = threading.Thread(target=scan_ip_with_semaphore, args=(ip_str,))
        threads.append(thread)
        thread.start()

    for thread in threads:
        thread.join()
    
    return up_ips

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Escanea una red en busca de hosts activos.")
    parser.add_argument("network", nargs='?', default="192.168.1.0/24", help="La red a escanear (por ejemplo, 192.168.1.0/24)")
    parser.add_argument("-p", "--port", type=int, help="El puerto a comprobar (opcional)")
    args = parser.parse_args()

    network_to_scan = args.network
    port_to_scan = args.port

    up_ips = scan_network(network_to_scan, port_to_scan)
    print("\nIPs activas:")
    for ip in up_ips:
        print(ip)


Omitiendo IPs locales

El script identifica las direcciones IP activas. Para asegurar una comunicación de red adecuada, verifique que la configuración del proxy esté configurada para omitir estas IPs locales.

192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,127.0.0.1,localhost,*.local,timestamp.apple.com,sequoia.apple.com,seed-sequoia.siri.apple.com, 192.168.1.0/16

Máscaras de subred

Mi segunda máquina suele estar en 192.168.1.16.

Así que funciona usando el siguiente comando.

python scripts/ip_scan.py 192.168.1.0/27 -p 22

porque 32 - 27 = 5, 2^5 = 32, por lo que intentará desde 192.168.1.0 hasta 192.168.1.31.

Pero no funciona cuando se usa 192.168.1.0/28, porque 2^4 = 16, por lo que intentará desde 192.168.1.0 hasta 192.168.1.15, lo que no cubre 192.168.1.16.


Back 2025.02.22 Donate