Python を使ってポートスキャナを構築する

PythonPythonBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

このプロジェクトでは、Pythonを使ってサーバーのオープンポートを検出するサーバーポートスキャナを開発します。このツールは、セキュリティポリシーを検証するシステム管理者と、ホスト上の稼働中のネットワークサービスを特定する潜在的な攻撃者の両方にとって重要です。私たちの旅は、ポートスキャニングの重要な側面、その手法と影響についてもカバーします。Pythonの機能を活用して、効率とパフォーマンスを向上させるためのマルチスレッドアプローチに焦点を当てて、シンプルで効果的なポートスキャナを作成します。

ポートスキャニングとは、サーバーの複数のポートに要求を送信して、どのポートがオープンしているかを判断するプロセスです。このステップは、セキュリティの維持と攻撃者が脆弱なサービスを見つけるためにともに重要です。まずは、ポートスキャニングの基本とその影響について調べます。

キーコンセプト:

  • ポートスキャナは、サーバーまたはホスト上のオープンポートを検出するのに役立ちます。
  • セキュリティ評価に使用され、攻撃者によって脆弱なサービスを特定するために使用されます。
  • ポートスキャニングの最も単純な形式は、複数のポートに対するTCP接続を試みることです。

👀 プレビュー

これから作成するポートスキャナツールの予告編を見てみましょう:

python port_scanner.py 127.0.0.1 5000-9000

出力:

Opened Port: 8081
Scanning completed.

🎯 タスク

このプロジェクトで学ぶことは以下の通りです。

  • Pythonのソケットプログラミング機能を使ってネットワークポートとやり取りする方法。
  • Pythonでマルチスレッドアプローチを実装して、ネットワークスキャニングタスクの効率を向上させる方法。
  • ユーザー入力を受け取って柔軟なポートスキャニングができるPythonのコマンドラインツールを開発する方法。

🏆 成果

このプロジェクトを完了すると、以下のことができるようになります。

  • Pythonのソケットライブラリを使ってネットワーク接続を作成し、ポートの可用性をテストし、ネットワーク例外を処理する。
  • Pythonでマルチスレッドを理解して適用して並行タスクを実行し、ネットワーク集約的な操作のパフォーマンスを大幅に向上させる。
  • 実用的なコマンドラインポートスキャナツールを構築し、Pythonのスクリプト作成スキルとコマンドライン引数解析の理解を深める。

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/FileHandlingGroup(["File Handling"]) python(("Python")) -.-> python/AdvancedTopicsGroup(["Advanced Topics"]) python(("Python")) -.-> python/NetworkingGroup(["Networking"]) python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/ModulesandPackagesGroup(["Modules and Packages"]) python/FunctionsGroup -.-> python/function_definition("Function Definition") python/FunctionsGroup -.-> python/arguments_return("Arguments and Return Values") python/FunctionsGroup -.-> python/build_in_functions("Build-in Functions") python/ModulesandPackagesGroup -.-> python/standard_libraries("Common Standard Libraries") python/FileHandlingGroup -.-> python/with_statement("Using with Statement") python/AdvancedTopicsGroup -.-> python/threading_multiprocessing("Multithreading and Multiprocessing") python/NetworkingGroup -.-> python/socket_programming("Socket Programming") subgraph Lab Skills python/function_definition -.-> lab-415965{{"Python を使ってポートスキャナを構築する"}} python/arguments_return -.-> lab-415965{{"Python を使ってポートスキャナを構築する"}} python/build_in_functions -.-> lab-415965{{"Python を使ってポートスキャナを構築する"}} python/standard_libraries -.-> lab-415965{{"Python を使ってポートスキャナを構築する"}} python/with_statement -.-> lab-415965{{"Python を使ってポートスキャナを構築する"}} python/threading_multiprocessing -.-> lab-415965{{"Python を使ってポートスキャナを構築する"}} python/socket_programming -.-> lab-415965{{"Python を使ってポートスキャナを構築する"}} end

TCP接続テストの確立

最初のステップは、対象のIP上のTCPポートがオープンしているかどうかをテストする関数を書くことです。この関数は、指定されたポートに接続してその状態を判断します。

/home/labex/project ディレクトリにある port_scanner.py という名前のファイルを開き、次のPython関数を追加します。

import argparse
from queue import Queue
from socket import AF_INET, gethostbyname, socket, SOCK_STREAM
import threading

def tcp_test(port: int, target_ip: str) -> None:
    with socket(AF_INET, SOCK_STREAM) as sock:
        sock.settimeout(1)
        result = sock.connect_ex((target_ip, port))
        if result == 0:
            print(f"Opened Port: {port}")

このコードは、tcp_test という関数を定義しています。この関数は、対象のIPアドレスの指定されたポートにTCP接続を確立しようとします。各ポートでの長時間の待機を避けるためにタイムアウトを設定し、接続を試みるために connect_ex を使用します。

connect_ex が0を返す場合、接続が成功したことを示しており、つまりポートがオープンしていることを意味し、関数はオープンしたポートを示すメッセージを表示します。

✨ 解答を確認して練習

並列ポートチェックの設定

次に、各スレッドがキューからポートを処理し、各ポートの状態を確認するために tcp_test 関数を利用する worker 関数を作成します。

port_scanner.py に次のコードを追加します。

def worker(target_ip: str, queue: Queue) -> None:
    while not queue.empty():
        port = queue.get()
        tcp_test(port, target_ip)
        queue.task_done()

worker 関数は、複数のスレッドによって実行されるように設計されています。この関数は、キューからポート番号を継続的に取得し、事前に定義された tcp_test 関数を使用して、対象のIP上のそれらのポートがオープンしているかどうかを確認します。

ポートをテストした後、キュー内のタスクを完了としてマークします。この関数により、ポートの並列スキャニングが可能になり、処理速度が大幅に向上します。

✨ 解答を確認して練習

スキャニングプロセスの調整

main 関数は、キューを設定し、ワーカースレッドを初期化し、指定されたポート範囲でのスキャニング操作を管理することで、スキャニングプロセスを調整します。

続けて、port_scanner.pymain 関数を追加します。

def main(host: str, start_port: int, end_port: int) -> None:
    target_ip = gethostbyname(host)
    queue = Queue()
    for port in range(start_port, end_port + 1):
        queue.put(port)
    for _ in range(100):  ## 必要に応じてスレッド数を調整してください
        t = threading.Thread(target=worker, args=(target_ip, queue,))
        t.daemon = True
        t.start()
    queue.join()
    print("Scanning completed.")

main 関数は、全体のポートスキャニングプロセスを調整します。

まず、対象のホスト名をIPアドレスに解決し、次にスキャニング対象のポート番号用のキューを作成します。指定された範囲内のすべてのポートをキューに格納し、複数のワーカースレッド(この例では100個)を生成して、各ポートをチェックすることでキューを並列処理します。この関数は、すべてのポートの処理が完了するまで待機し(queue.join())、その後、スキャニングが完了したことを示すメッセージを表示します。

✨ 解答を確認して練習

ポートスキャナの実行

最後に、私たちのポートスキャナを実行しましょう。ツールをテストするために、localhost上の複数のポートをスキャンします。

port_scanner.py の末尾に次の行を追加して、スクリプトを実行可能にします。

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='TCP Port Scanner')
    parser.add_argument('host', help='Host to scan')
    parser.add_argument('ports', help='Port range to scan, formatted as start-end')
    args = parser.parse_args()

    start_port, end_port = map(int, args.ports.split('-'))
    main(args.host, start_port, end_port)

このコードは、コマンドライン引数解析を使ってポートスキャナスクリプトを作成し、もっと汎用性が高くユーザーにやさしくなっています。

argparse ライブラリを使って、2つの必須引数を定義しています。hostports です。

  • host 引数は、スキャンしたい対象のホストのアドレスまたはホスト名を指定するために使用されます。
  • ports 引数は、スキャンするポートの範囲を定義する文字列を期待しており、"start-end" の形式で指定します(例:"5000-8000")。スクリプトは - 区切り文字を使ってこれを start_portend_port に分割し、その後整数に変換します。これにより、ユーザーはコマンドラインからスクリプトを実行する際に、対象とポート範囲を簡単に指定できます。

次に、ターミナルで次のコマンドを実行してスキャナを実行します。

python port_scanner.py 127.0.0.1 5000-9000

出力:

Opened Port: 8081
Scanning completed.

ポートスキャナを使ってオープンしているポート(8081)を特定したので、そこにWebサーバーが稼働しているはずです。そこにホストされているものを調べることができます。

これを行うには、まず追加ボタンをクリックして、「Webサービス」オプションを選択します。

Select Web Service option

次に、ポート8081を入力して、「アクセス」ボタンをクリックします。

Enter port and access web server

システム内でポート8081を監視しているWebサーバーが稼働していることがわかります。

Web server running on port 8081
✨ 解答を確認して練習

まとめ

このプロジェクトでは、Pythonを使って基本的なポートスキャナを構築しました。最初は基本的な tcp_test 関数から始め、多スレッドのスキャニング手法まで進めました。プロセスを管理可能なステップに分解し、最終的には対象サーバー上のオープンポートを特定できる機能的なツールを作成しました。この実践的な経験を通じて、ネットワークセキュリティに対する理解を深めるだけでなく、Pythonプログラミングと並列処理管理のスキルも磨きました。