ホームページ  >  記事  >  バックエンド開発  >  Python を使用した基本的なポート スキャナー

Python を使用した基本的なポート スキャナー

Linda Hamilton
Linda Hamiltonオリジナル
2024-10-23 13:31:30157ブラウズ

Basic Port Scanner using Python

ソースコードはここをクリックしてください

これは、ユーザーがホストをスキャンして開いているポートとポート上で実行されているサービスを見つけることができる基本的なポート スキャナ ツールです...

まずコードを見て、それから分析するためにコードを分割してみましょう...

import socket
from datetime import datetime
import sys
import os 

def usage():
    """Prints the usage information for this script."""
    usage_info = """
    Tool Name: SimplePortScanner 

    Developed by : Bharath Kumar

    Usage:
        python3 port_scanner.py [options]

    Options:
        -h, --help           Show this help message and exit.
        -t, --target <ip>    Specify the target hostname or IP address (required).
        -p, --port <port>    Specify a port (or) range of ports to scan (e.g. -p 80 (or) -p 1-1024).

    Description:
        This script performs a port scan on a specified hostname or IP address
        for a specific port or a range of ports, checking which ports are open. 

    Examples:
        python3 port_scanner.py -t example.com (or) 192.0.0.1 
        python3 port_scanner.py -t example.com (or) 192.168.1.1 -p 80
        python3 port_scanner.py -t example.com (or) 192.168.1.1 --ports 1-1024
    """
    print(usage_info)

start_time = datetime.now()

def scan_port(ip, port):

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(1)
    try:
        result = s.connect_ex((ip, port))
        service = socket.getservbyport(int(port))
    except:
        service = "None"
    if result == 0:
        print(" Port: {}\t State: Open\t Service: {}".format(port, service))

    else:
        pass

    s.close()


def host(target):
    try:
        ip = socket.gethostbyname(target)
        print('_'*51)
        print("[#] Resolved {} to {}".format(target,ip))
        return ip
    except:
        print('_'*51)
        print("[#] Error: Unable to resolve hostname {}".format(target))
        sys.exit(1)

def check_host_up(ip):

    ping = os.system("ping {} -c 1 > /dev/null".format(ip))

    if ping == 0:
       print("[#] {} host is up and running".format(ip))
       return True
    else:
        print("[#] {} host is down".format(ip))
        print("Exiting...")
        exit()
        return False





if __name__ == "__main__":

    target_ip = None
    start_port = 1
    end_port = 65535

    try:
        for i, arg in enumerate(sys.argv):
            if arg in ("-t", "--target"):
                target_ip = sys.argv[i + 1]
            elif arg in ("-p", "--ports"):
                port_range = sys.argv[i + 1]
                if "-" in port_range:
                    start_port, end_port = map(int, port_range.split('-'))
                else:
                    start_port = end_port = int(port_range)

        if target_ip is None:
            print("[#] Error: Target hostname or IP address is required.")
            usage()
            sys.exit(1)

        if start_port is None or end_port is None:
            print("[#] Error: Port range is required.")
            usage()
            sys.exit(1)

        target_ip = host(target_ip)

        if not check_host_up(target_ip):
            sys.exit(1)

        print(f"[#] Scanning {target_ip} from port {start_port} to {end_port}...")
        print("[#] Scanning started at: {}".format(start_time))
        print('_'*51)

        for port in range(start_port, end_port + 1):
            scan_port(target_ip, port)

    except (IndexError, ValueError):
        print("[#] Error: Invalid arguments provided.")
        usage()
        sys.exit(1)

start_time = start_time.now() - start_time
print('_'*51)
print("Scanning is completed in ",start_time)

インポートソケット: 2 つのノード (サーバー、クライアント) が相互に通信する方法。

from datetime import datetime: スキャンに費やされた計算時間が使用されます。

Import sys: は、システム固有のパラメーター (argv) にアクセスします。

Import os: は、ping コマンドの実行に使用されます。

def_usage(): このスクリプトの使用法情報を出力します。

start_time = datetime.now(): は、現在の時刻と日付を取得して、スキャンに費やされた時間を計算するために使用されます。

def scan_port(ip, port):

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(1)
    try:
        result = s.connect_ex((ip, port))
        service = socket.getservbyport(int(port))
    except:
        service = "None"
    if result == 0:
        print(" Port: {}\t State: Open\t Service: {}".format(port, service))

    else:
        pass

    s.close()


このコード ブロックは、ソケットを使用して指定された IP アドレスの特定のポートが開いているかどうかをチェックする関数 scan_port(ip, port) を定義します。

ソケットの作成:socket.socket(socket.AF_INET,ソケット.SOCK_STREAM) TCP を使用して IPv4 用の新しいソケットを作成します。

タイムアウト: s.settimeout(1) ソケット時間を 1 秒に設定します。その時間内に接続が成功しない場合、試行は停止します。

接続テスト:s.connect_ex((ip, port)) 特定の IP とポートへの接続を試行します。成功した場合、結果は 0 になります。それ以外の場合は、別の値になります。

サービス検出:socket.getservbyport(int(port))指定されたポートで実行されているサービスを検出します。ポート 80 の HTTP と同様です。

エラー処理: エラー (ポート上にサービスがないなど) が発生した場合、Exception ブロックはサービスを「なし」に設定します。

出力: ポートが開いている場合 (結果 == 0)、ポート番号、状態 (「オープン」)、およびサービス名が出力されます。

接続の終了: s.close() はソケットを閉じてリソースを解放します。

def host(target):
    try:
        ip = socket.gethostbyname(target)
        print('_'*51)
        print("[#] Resolved {} to {}".format(target,ip))
        return ip
    except:
        print('_'*51)
        print("[#] Error: Unable to resolve hostname {}".format(target))
        sys.exit(1)

このコード ブロックは、socket.gethostname() を使用して、指定されたターゲット (ホスト名) を対応する IP アドレスに解決する関数 host(target) を定義します

def check_host_up(ip):

    ping = os.system("ping {} -c 1 > /dev/null".format(ip))

    if ping == 0:
       print("[#] {} host is up and running".format(ip))
       return True
    else:
        print("[#] {} host is down".format(ip))
        print("Exiting...")
        exit()
        return False

この関数 check_host_up(ip) は、os.system() ping メソッドを使用して特定のターゲット IP 上の特定のポートが起動しているか停止しているかを確認します。

if __name__ == "__main__":

    target_ip = None
    start_port = 1
    end_port = 65535

    try:
        for i, arg in enumerate(sys.argv):
            if arg in ("-t", "--target"):
                target_ip = sys.argv[i + 1]
            elif arg in ("-p", "--ports"):
                port_range = sys.argv[i + 1]
                if "-" in port_range:
                    start_port, end_port = map(int, port_range.split('-'))
                else:
                    start_port = end_port = int(port_range)


コマンドライン引数の解析

sys.argv 配列には、スクリプトに渡される引数のリストが含まれます。これらの引数をループして、ターゲット IP (-t または --target) とポート範囲 (-p または --ports) をチェックします。

ターゲット IP/ホスト名は target_ip に保存されます。
ポート範囲が解析され、start_port と end_port に分割されます。範囲が指定されていない場合、デフォルトで 1 ~ 65535 のすべてのポートがスキャンされます。

import socket
from datetime import datetime
import sys
import os 

def usage():
    """Prints the usage information for this script."""
    usage_info = """
    Tool Name: SimplePortScanner 

    Developed by : Bharath Kumar

    Usage:
        python3 port_scanner.py [options]

    Options:
        -h, --help           Show this help message and exit.
        -t, --target <ip>    Specify the target hostname or IP address (required).
        -p, --port <port>    Specify a port (or) range of ports to scan (e.g. -p 80 (or) -p 1-1024).

    Description:
        This script performs a port scan on a specified hostname or IP address
        for a specific port or a range of ports, checking which ports are open. 

    Examples:
        python3 port_scanner.py -t example.com (or) 192.0.0.1 
        python3 port_scanner.py -t example.com (or) 192.168.1.1 -p 80
        python3 port_scanner.py -t example.com (or) 192.168.1.1 --ports 1-1024
    """
    print(usage_info)

start_time = datetime.now()

def scan_port(ip, port):

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(1)
    try:
        result = s.connect_ex((ip, port))
        service = socket.getservbyport(int(port))
    except:
        service = "None"
    if result == 0:
        print(" Port: {}\t State: Open\t Service: {}".format(port, service))

    else:
        pass

    s.close()


def host(target):
    try:
        ip = socket.gethostbyname(target)
        print('_'*51)
        print("[#] Resolved {} to {}".format(target,ip))
        return ip
    except:
        print('_'*51)
        print("[#] Error: Unable to resolve hostname {}".format(target))
        sys.exit(1)

def check_host_up(ip):

    ping = os.system("ping {} -c 1 > /dev/null".format(ip))

    if ping == 0:
       print("[#] {} host is up and running".format(ip))
       return True
    else:
        print("[#] {} host is down".format(ip))
        print("Exiting...")
        exit()
        return False





if __name__ == "__main__":

    target_ip = None
    start_port = 1
    end_port = 65535

    try:
        for i, arg in enumerate(sys.argv):
            if arg in ("-t", "--target"):
                target_ip = sys.argv[i + 1]
            elif arg in ("-p", "--ports"):
                port_range = sys.argv[i + 1]
                if "-" in port_range:
                    start_port, end_port = map(int, port_range.split('-'))
                else:
                    start_port = end_port = int(port_range)

        if target_ip is None:
            print("[#] Error: Target hostname or IP address is required.")
            usage()
            sys.exit(1)

        if start_port is None or end_port is None:
            print("[#] Error: Port range is required.")
            usage()
            sys.exit(1)

        target_ip = host(target_ip)

        if not check_host_up(target_ip):
            sys.exit(1)

        print(f"[#] Scanning {target_ip} from port {start_port} to {end_port}...")
        print("[#] Scanning started at: {}".format(start_time))
        print('_'*51)

        for port in range(start_port, end_port + 1):
            scan_port(target_ip, port)

    except (IndexError, ValueError):
        print("[#] Error: Invalid arguments provided.")
        usage()
        sys.exit(1)

start_time = start_time.now() - start_time
print('_'*51)
print("Scanning is completed in ",start_time)

ホストの解像度と到達可能性

有効な IP アドレスを取得したら、ホストが到達可能かどうかを確認する必要があります。関数 host(target_ip) はホスト名をその IP アドレスに解決し、check_host_up(target_ip) はホストがオンラインかどうかを確認します。

def scan_port(ip, port):

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(1)
    try:
        result = s.connect_ex((ip, port))
        service = socket.getservbyport(int(port))
    except:
        service = "None"
    if result == 0:
        print(" Port: {}\t State: Open\t Service: {}".format(port, service))

    else:
        pass

    s.close()


ポートスキャン

ポート スキャン機能の中核はループ内で発生します。

このループは指定されたポート範囲を繰り返し、各ポートに対して関数 scan_port(target_ip, port) がポートを調べてポートが開いているか閉じているかを確認します。

結論

このガイドに従うことで、コマンドライン引数を受け取り、入力を検証し、特定のターゲット上のポート範囲をスキャンする単純な Python ポート スキャナーを構築する方法を学びました。これは基本的な実装ですが、スレッド化やサービス検出などのより高度な機能の基礎を築きます。

特定のニーズに合わせてこのスクリプトを自由に調整および拡張してください。スキャンを楽しんでください!

以上がPython を使用した基本的なポート スキャナーの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。