Linux の netstat コマンドでネットワークポートとセッションを分析する

CompTIABeginner
オンラインで実践に進む

はじめに

この実験 (Lab) では、Linux システム上でネットワークアクティビティを分析するために netstat コマンドを使用する方法を学びます。ネットワークポート、ソケット、アクティブな接続といった基本的な概念を探求し、サービスがネットワーク上でどのように通信するかについての洞察を得ます。

まず、すべてのアクティブなソケットを一覧表示し、次に結果をフィルタリングして、リスニング中の TCP および UDP ポートに焦点を当て、それらを実行中のサービスにマッピングします。これらの概念を実際に確認するために、ウェブサイトを閲覧して新しい接続を生成し、その後 netstat を使用して新しく作成された ESTABLISHED セッションとその関連するエフェメラルポートを特定します。

netstat -a ですべてのアクティブおよびリスニングソケットを一覧表示する

このステップでは、netstat コマンドを使用してシステムのネットワークアクティビティの探索を開始します。このコマンドは、ネットワーク管理者はもちろん、開発者にとっても基本的なツールであり、ネットワーク接続、ルーティングテーブル、インターフェイス統計に関する洞察を提供します。まず -a オプションを使用します。これは、netstat に対して、リモートシステムへの接続と、新しい着信接続を「リスニング」しているポートの両方を含む、すべてのアクティブなソケットを表示するように指示します。

まず、デフォルトの作業ディレクトリにいることを確認してください。この実験 (Lab) のすべてのコマンドはターミナルから実行されます。

それでは、すべてのソケットを一覧表示しましょう。ターミナルで次のコマンドを入力し、Enter キーを押します。

netstat -a

大量の出力が表示されます。心配しないでください。後で詳しく見ていきます。出力には、tcpudp、および UNIX ドメインソケットを含む、すべての種類のソケットが表示されます。

出力の構造を見てみましょう。以下のような形式になっているはずです(お使いのシステムでの正確な詳細は異なる場合があります)。

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN
tcp        0      0 localhost:6010          0.0.0.0:*               LISTEN
tcp        0     52 labex-vm:ssh            192.168.0.10:54321      ESTABLISHED
tcp6       0      0 [::]:http-alt           [::]:*                  LISTEN
udp        0      0 0.0.0.0:bootpc          0.0.0.0:*
...
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   Path
unix  2      [ ]         DGRAM                    23456    /run/systemd/notify
unix  2      [ ACC ]     STREAM     LISTENING     34567    /tmp/.X11-unix/X0
...

インターネット接続に関する最も重要な列の内訳は次のとおりです。

  • Proto: ソケットが使用するプロトコルです。例えば tcp (TCPv4 用)、tcp6 (TCPv6 用)、または udp などがあります。
  • Local Address: この接続に使用されている、お使いのシステムの IP アドレスと ポート番号 です。ポートはコロン (:) の後の番号です。アドレスが 0.0.0.0 または [::] の場合、そのポートはマシン上のすべての利用可能なネットワークインターフェイスでリスニングしていることを意味します。
  • Foreign Address: リモートシステムの IP アドレスとポート番号です。状態が LISTEN の場合、通常は 0.0.0.0:* または [::]:* となり、任意のからの接続を待機していることを示します。
  • State: これは TCP 接続にとって非常に重要です。
    • LISTEN: アプリケーションは、指定された Local Address のポートで着信接続を待機しています。これはサーバー側の状態です。
    • ESTABLISHED: 接続がアクティブであり、ローカルアドレスとリモートアドレス間でデータを転送できます。
    • TIME_WAITCLOSE_WAIT のような他の状態は、TCP 接続を閉じるプロセスに関連しています。

少し時間を取って出力をスクロールし、LISTEN 状態のエントリを特定してください。これらは、ネットワーク接続を受け入れる準備ができているシステム上のサービスを表します。これは、トランスポート層(レイヤー 4)が実際に動作している様子を直接確認できるものです。

sudo netstat -tulnp でリスニング中の TCP/UDP ポートをフィルタリングする

前のステップでは、netstat -a コマンドを使用してすべてのアクティブなソケットの完全なリストを取得しましたが、そのリストは非常に長くなりがちでした。この情報をより有用にするために、フィルタリングが必要です。このステップでは、netstat の特定のオプションを使用して、リスニング中の TCP および UDP ポートのみを表示し、最も重要なこととして、それらのポートを使用しているプログラムを特定する方法を学びます。

ポートに関連付けられたプログラム名を表示するには、多くの場合、管理者権限が必要です。なぜなら、そのプロセスはシステムまたは別のユーザーによって所有されている可能性があるからです。そのため、sudo コマンドを使用します。LabEx 環境では、パスワードなしで sudo を使用できます。

より焦点を絞った netstat コマンドを実行しましょう。ターミナルで次のように入力します。

sudo netstat -tulnp

これらのオプションはよく組み合わせて使用されるため、分解して見ていきましょう。

  • t: TCP 接続を表示します。
  • u: UDP 接続を表示します。
  • l: listening (リスニング) ソケットのみを表示します。これは、どのサービスが接続を待機しているかを確認するための主要なフィルタです。
  • n: numerical (数値) アドレスを表示します。これにより、netstat は IP アドレスやポート番号をホスト名やサービス名に解決しようとしなくなります(例:ssh の代わりに 22 を表示します)。これにより、コマンドの実行が大幅に高速化されます。
  • p: ソケットが属するプログラムの process ID (PID) と名前を表示します。すべてのプロセスを表示するには sudo が必要です。

Enter キーを押すと、出力ははるかに短く、より有益になります。以下のような形式になります。

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      779/systemd-resolve
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      3422/sshd
udp        0      0 127.0.0.53:53           0.0.0.0:*                           779/systemd-resolve

末尾に新しい列があることに注意してください:PID/Program name。これが重要な情報です。これで、リスニング中のポートを、それを開いた正確なアプリケーションに直接マッピングできます。たとえば、上記の出力では、ポート 22 (SSH の標準ポート) がプロセス ID 3422 を持つ sshd プログラムによって使用されていることがわかります。

このコマンドはシステム管理者にとって非常に強力です。どのサービスが実行されており、ネットワークに公開されているかを迅速に確認できるため、トラブルシューティングとセキュリティ監査の両方に不可欠です。

リスニングポートと実行中のサービスをマッピングする

このステップでは、実行中のアプリケーションとリスニング中のネットワークポートとの間の関連性についての理解を深めます。netstat を使用して既存のサービスを一覧表示する方法を見てきました。次に、簡単な Web サービスを起動し、それが netstat の出力に表示されるのを観察することで、この関係をリアルタイムで実証します。

Python の組み込み http.server モジュールを使用して、Web サーバーを迅速に起動します。これは開発やテストに便利なツールです。

  1. まず、Web サーバーを起動しましょう。ポート 8080 でリッスンするように指示します。これは Web サービスでよく使用される代替ポートです。ターミナルで次のコマンドを実行してください。サーバーが現在アクティブに実行されているため、ターミナルが「ハング」したように見えることに注意してください。

    python3 -m http.server 8080
    

    サーバーが起動したことを示す出力が表示されるはずです。

    Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
    
  2. このターミナルは現在、Web サーバープロセスによって占有されています。他のコマンドを実行するには、新しいターミナルが必要です。LabEx 環境では、ターミナルウィンドウの「プラス」アイコンをクリックするか、メニュー (File -> New Tab) を使用して新しいターミナルタブを開くことができます。

  3. 新しいターミナルタブで、リスニングポートのリストを表示するために netstat コマンドを再度実行します。

    sudo netstat -tulnp
    
  4. 出力を注意深く調べてください。ポート 8080 の新しいエントリが表示されるはずです。

    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      779/systemd-resolve
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      3422/sshd
    tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      12345/python3
    udp        0      0 127.0.0.53:53           0.0.0.0:*                           779/systemd-resolve
    ...
    

    ご覧のとおり、システムは現在、プログラム python3 (例:12345 のような特定の PID を持つ) がポート 8080LISTEN 状態にあると報告しています。サービスを正常に起動し、ネットワーク接続をリッスンしていることを確認しました。

  5. 次に、サービスを停止しましょう。最初のターミナルタブ(Python サーバーを実行しているタブ)に戻り、Ctrl+C を押します。これにより、サーバープロセスが中断され終了します。

  6. 2 番目のターミナルタブに戻り、最後に netstat コマンドを実行します。

    sudo netstat -tulnp
    

    ポート 8080 の行は消えているはずです。これは、アプリケーションが終了すると、そのポートでリッスンしなくなることを証明しています。

ウェブサイトを閲覧して新しい接続を作成する

このステップでは、サーバー側のリスニングポートからクライアント側のアクティブな接続に焦点を移します。これまでは、他の接続を待機しているサービスを観察してきました。今度は、ご自身のマシンからリモートサーバーへの接続を開始し、接続が形成されるのを観察します。コマンドラインツール curl を使用して、ウェブサイトへのアクセスをシミュレートします。

この一時的なイベントを観察するために、watch コマンドを使用します。これは別のコマンドを繰り返し実行し、netstat の出力をほぼリアルタイムで変更を確認できるようにします。

  1. まず、監視ウィンドウを設定しましょう。ターミナルで次のコマンドを実行します。これにより、2 秒ごとに netstat -antp が実行され、結果が表示され、画面が継続的に更新されます。

    watch netstat -antp
    
    • a: すべてのソケットを表示します。
    • n: 数値アドレスを表示します。
    • t: TCP 接続のみを表示します。
    • p: PID/プログラム名を表示します。

    ターミナルには netstat の出力が表示され、自動的に更新されます。このターミナルを開いたまま表示しておいてください。

  2. 次に、接続を作成するコマンドを発行するために、新しいターミナルタブを開く必要があります。ターミナルのタブバーにある「プラス」アイコンをクリックしてください。

  3. 新しいターミナルタブで、curl を使用して LabEx ウェブサイトのホームページを取得します。> 記号は、HTML 出力を /dev/null にリダイレクトするため、画面が乱雑になるのを防ぎます。

    curl https://www.labex.io > /dev/null
    
  4. Enter を押すとすぐに、最初のターミナルタブwatch を実行しているタブ)に素早く切り替えてください。数秒間、新しい接続が表示されるはずです。以下のような表示になります。

    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    ...
    tcp        0      0 172.17.0.2:45678        104.21.5.141:443        ESTABLISHED 13579/curl
    ...
    
    • StateESTABLISHED になっていることに注意してください。これはアクティブな接続を示しています。
    • Foreign Addresslabex.io サーバーの IP アドレスとポート 443 (HTTPS の標準ポート) を表示します。
    • PID/Program name 列は、この接続を開始したプログラムが curl であることを明確に識別します。
    • Local Address は、高番台のランダムなポート(例では 45678 のような)を使用します。これはエフェメラルポートであり、次のステップで詳しく説明します。
  5. curl コマンドのダウンロードが完了すると(非常に高速です)、接続状態が TIME_WAIT または FIN_WAIT に変化してから、リストから完全に消えるのがわかります。

  6. これで watch コマンドを停止できます。最初のターミナルタブに移動して Ctrl+C を押してください。2 番目のターミナルタブを閉じることもできます。

ESTABLISHED セッションとエフェメラルポートを特定する

この最終ステップでは、永続的なアクティブな接続を調べることで、理解を統合します。これにより、ネットワークの「セッション」を明確に特定し、システムがクライアント側の通信に一時的な、または「エフェメラル」ポートをどのように使用するかを確認できます。

netstat の出力における ESTABLISHED 接続は、アクティブなセッション(OSI レイヤー 5)を表し、2 つのアプリケーションがデータを交換する準備ができている状態です。前のステップの curl セッションは非常に短時間でした。セッションをより簡単に調査するために、SSH を使用して開いたままの状態を作成します。

まず、重要な概念であるエフェメラルポートを定義しましょう。コンピューター(クライアント)が既知のポート(SSH のポート 22 や HTTPS のポート 443 など)でサーバーに接続する場合、オペレーティングシステムは会話の自機側のためにポートを割り当てる必要があります。これは、高番台の範囲(通常は 32768 以上)から一時的な未使用ポートを選択します。これはエフェメラルポートと呼ばれます。このメカニズムにより、単一のコンピューターが同じサーバーポートに対して多くの個別の接続を持つことができます。例えば、同じウェブサイトに対して複数のブラウザタブを開くことができます。

  1. 安定した観測可能なセッションを作成するために、ラボマシンから自身に SSH で接続します。ターミナルで次のコマンドを実行してください。

    ssh localhost
    

    初めてこれを行う場合、ホストの認証に関するメッセージが表示されることがあります。これは正常です。

    The authenticity of host 'localhost (127.0.0.1)' can't be established.
    ED25519 key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
    Are you sure you want to continue connecting (yes/no/[fingerprint])?
    

    yes と入力して Enter を押して続行します。

    パスワードを入力するように求められます。パスワードを入力する必要はありません。そのまま待機してください。

  2. 「プラス」アイコンをクリックして、新しいターミナルタブを開きます。アクティブな SSH セッションを妨げずに netstat を実行するために、この新しいターミナルが必要です。

  3. 新しいターミナルで netstat を再度実行しますが、今回は grep コマンドを使用して出力をフィルタリングし、ESTABLISHED を含む行のみを表示します。これにより、アクティブなセッションを見つけやすくなります。

    netstat -antp | grep ESTABLISHED
    
  4. 出力には、現在アクティブなすべての TCP 接続が表示されます。すべてのプロセスを特定できなかったという警告が表示される場合があります。これは、sudo を使用していないため予想されることです。ラボ環境への元の SSH 接続と、先ほど作成した localhost への新しい接続が表示されるはずです。

    (Not all processes could be identified, non-owned process info
     will not be shown, you would have to be root to see it all.)
    tcp        0      0 172.16.50.192:22        47.251.66.143:36882     ESTABLISHED -
    tcp        0      0 127.0.0.1:46280         127.0.0.1:22            ESTABLISHED 5449/ssh
    tcp        0      0 127.0.0.1:22            127.0.0.1:46280         ESTABLISHED -
    

    127.0.0.1 アドレスで識別される新しい localhost 接続を分析しましょう。

    • 接続のサーバー側は 127.0.0.1:22 であり、これはポート 22 でリッスンしている SSH サーバー(sshd)です。127.0.0.1:46280 から確立された接続があります。sshd プロセスは root ユーザーが所有しており、sudo を使用しなかったため、プログラム情報は - となっています。
    • クライアント側は 127.0.0.1:46280127.0.0.1:22 に接続しています。プログラムは 5449/ssh として明確に識別されています。
    • ポート 46280エフェメラルポートです。システムはこの特定の SSH セッションのクライアント側のためにランダムに選択しました。別の ssh localhost 接続を開くと、異なるエフェメラルポートが使用されます。
  5. 最後に、セッションを閉じます。ssh localhost を実行したターミナルタブに切り替えて exit と入力し、Enter を押します。

    exit
    

    これにより、接続が終了します。別のターミナルで netstat -antp | grep ESTABLISHED を再度実行すると、localhost セッションが消えているのがわかります。

まとめ

この実験では、Linux システム上のネットワークアクティビティを分析するために netstat コマンドを使用する方法を学びました。まず netstat -a を使用して、TCP、UDP、UNIX ドメインソケットを含むすべてのアクティブおよびリスニングソケットを一覧表示しました。次に、-t-u-l-n-p などのフラグを適用して、リスニング TCP および UDP ポートを具体的にフィルタリングし、数値アドレスを表示し、各ポートに関連付けられたプロセス ID と名前を特定することで、この出力を絞り込みました。

これを基に、コマンドの出力を解釈してリスニングポートを対応するサービスにマッピングする練習をしました。接続が動作している様子を観察するために、ウェブサイトに接続して新しいネットワークセッションを開始しました。これにより、ESTABLISHED 状態の接続を特定し、ネットワーク通信のクライアント側に割り当てられる一時的なポートであるエフェメラルポートの役割を理解することができました。