LAN IP Scanner

Home PDF Audio

LAN IP Scanner

This Python script scans a local network for active IP addresses. It uses the ping command to check if a host is reachable and employs multithreading to speed up the scanning process. A semaphore limits the number of concurrent threads to avoid overwhelming the system. The script takes a network address (e.g., “192.168.1.0/24”) as input and prints whether each IP address in the network is up or down.

This script helps identify devices on the network, such as a TP-LINK mesh router operating in wired bridge mode, by scanning for active IP addresses.

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

MAX_THREADS = 50  # Maximum number of threads to use

def is_host_up(host, port=None):
    """
    Checks if a host is up using ping or telnet.
    If port is specified, uses telnet to check if the port is open.
    Otherwise, uses ping.
    Returns True if the host is up, False otherwise.
    """
    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: Send only 1 packet
            # -W 1: Wait 1 second for a response
            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):
    """
    Scans a single IP address and prints its status.
    """
    if is_host_up(ip_str, port):
        print(f"{ip_str} is up")
        up_ips.append(ip_str)
    else:
        print(f"{ip_str} is down")

def scan_network(network, port=None):
    """
    Scans a network for live hosts using threads, limiting the number of concurrent threads.
    """
    print(f"Scanning network: {network}")
    threads = []
    semaphore = threading.Semaphore(MAX_THREADS)  # Limit the number of concurrent threads
    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="Scan a network for live hosts.")
    parser.add_argument("network", nargs='?', default="192.168.1.0/24", help="The network to scan (e.g., 192.168.1.0/24)")
    parser.add_argument("-p", "--port", type=int, help="The port to check (optional)")
    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("\nLive IPs:")
    for ip in up_ips:
        print(ip)


Bypassing Local IPs

The script identifies active IP addresses. To ensure proper network communication, verify that proxy settings are configured to bypass these local IPs.

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

Subnet Masks

My second machine is usually at 192.168.1.16.

So it works using the command below.

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

because 32 - 27 = 5, 2^5 = 32, so it will try 192.168.1.0 to 192.168.1.31.

But it doesn’t work when using 192.168.1.0/28, because 2^4 = 16, so it will try 192.168.1.0 to 192.168.1.15, which doesn’t cover 192.168.1.16.


Back 2025.02.22 Donate