LAN IP スキャナー

Home PDF Audio

LAN IP スキャナー

このPythonスクリプトは、ローカルネットワーク上のアクティブなIPアドレスをスキャンします。ホストが到達可能かどうかを確認するためにpingコマンドを使用し、スキャン処理の高速化のためにマルチスレッディングを採用しています。セマフォは、システムに過剰な負荷をかけるのを避けるために、同時実行スレッド数を制限します。スクリプトはネットワークアドレス(例:「192.168.1.0/24」)を入力として受け取り、ネットワーク内の各IPアドレスが稼働中か停止中かをプリントします。

このスクリプトは、有線ブリッジモードで動作するTP-LINKメッシュルーターなど、ネットワーク上のデバイスをアクティブなIPアドレスをスキャンすることで特定するのに役立ちます。

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

MAX_THREADS = 50  # 最大スレッド数

def is_host_up(host, port=None):
    """
    pingまたはtelnetを使用してホストが稼働中かどうかを確認します。
    portが指定されている場合は、telnetを使用してポートが開いているかどうかを確認します。
    それ以外の場合は、pingを使用します。
    ホストが稼働中の場合はTrue、それ以外の場合はFalseを返します。
    """
    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: パケットを1つだけ送信
            # -W 1: 応答を1秒間待機
            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):
    """
    単一のIPアドレスをスキャンし、そのステータスをプリントします。
    """
    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):
    """
    スレッドを使用してライブホストをネットワークでスキャンし、同時実行スレッド数を制限します。
    """
    print(f"Scanning network: {network}")
    threads = []
    semaphore = threading.Semaphore(MAX_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="ネットワーク上のライブホストをスキャンします。")
    parser.add_argument("network", nargs='?', default="192.168.1.0/24", help="スキャンするネットワーク(例:192.168.1.0/24)")
    parser.add_argument("-p", "--port", type=int, help="確認するポート(オプション)")
    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)


ローカルIPのバイパス

スクリプトはアクティブなIPアドレスを識別します。適切なネットワーク通信を確保するには、プロキシ設定がこれらのローカルIPをバイパスするように構成されていることを確認してください。

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

サブネットマスク

私の2台目のマシンは通常192.168.1.16にあります。

そのため、以下のコマンドを使用すると動作します。

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

なぜなら、32 - 27 = 5、2^5 = 32なので、192.168.1.0から192.168.1.31を試行するからです。

しかし、192.168.1.0/28を使用すると動作しません。なぜなら、2^4 = 16なので、192.168.1.0から192.168.1.15を試行することになり、192.168.1.16は含まれないからです。


Back 2025.02.22 Donate