はじめに
この実験 (Lab) では、Linux システム上でネットワークアクティビティを分析するために netstat コマンドを使用する方法を学びます。ネットワークポート、ソケット、アクティブな接続といった基本的な概念を探求し、サービスがネットワーク上でどのように通信するかについての洞察を得ます。
まず、すべてのアクティブなソケットを一覧表示し、次に結果をフィルタリングして、リスニング中の TCP および UDP ポートに焦点を当て、それらを実行中のサービスにマッピングします。これらの概念を実際に確認するために、ウェブサイトを閲覧して新しい接続を生成し、その後 netstat を使用して新しく作成された ESTABLISHED セッションとその関連するエフェメラルポートを特定します。
netstat -a ですべてのアクティブおよびリスニングソケットを一覧表示する
このステップでは、netstat コマンドを使用してシステムのネットワークアクティビティの探索を開始します。このコマンドは、ネットワーク管理者はもちろん、開発者にとっても基本的なツールであり、ネットワーク接続、ルーティングテーブル、インターフェイス統計に関する洞察を提供します。まず -a オプションを使用します。これは、netstat に対して、リモートシステムへの接続と、新しい着信接続を「リスニング」しているポートの両方を含む、すべてのアクティブなソケットを表示するように指示します。
まず、デフォルトの作業ディレクトリにいることを確認してください。この実験 (Lab) のすべてのコマンドはターミナルから実行されます。
それでは、すべてのソケットを一覧表示しましょう。ターミナルで次のコマンドを入力し、Enter キーを押します。
netstat -a
大量の出力が表示されます。心配しないでください。後で詳しく見ていきます。出力には、tcp、udp、および 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_WAITやCLOSE_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 サーバーを迅速に起動します。これは開発やテストに便利なツールです。
まず、Web サーバーを起動しましょう。ポート
8080でリッスンするように指示します。これは Web サービスでよく使用される代替ポートです。ターミナルで次のコマンドを実行してください。サーバーが現在アクティブに実行されているため、ターミナルが「ハング」したように見えることに注意してください。python3 -m http.server 8080サーバーが起動したことを示す出力が表示されるはずです。
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...このターミナルは現在、Web サーバープロセスによって占有されています。他のコマンドを実行するには、新しいターミナルが必要です。LabEx 環境では、ターミナルウィンドウの「プラス」アイコンをクリックするか、メニュー (
File -> New Tab) を使用して新しいターミナルタブを開くことができます。新しいターミナルタブで、リスニングポートのリストを表示するために
netstatコマンドを再度実行します。sudo netstat -tulnp出力を注意深く調べてください。ポート
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 を持つ) がポート8080でLISTEN状態にあると報告しています。サービスを正常に起動し、ネットワーク接続をリッスンしていることを確認しました。次に、サービスを停止しましょう。最初のターミナルタブ(Python サーバーを実行しているタブ)に戻り、
Ctrl+Cを押します。これにより、サーバープロセスが中断され終了します。2 番目のターミナルタブに戻り、最後に
netstatコマンドを実行します。sudo netstat -tulnpポート
8080の行は消えているはずです。これは、アプリケーションが終了すると、そのポートでリッスンしなくなることを証明しています。
ウェブサイトを閲覧して新しい接続を作成する
このステップでは、サーバー側のリスニングポートからクライアント側のアクティブな接続に焦点を移します。これまでは、他の接続を待機しているサービスを観察してきました。今度は、ご自身のマシンからリモートサーバーへの接続を開始し、接続が形成されるのを観察します。コマンドラインツール curl を使用して、ウェブサイトへのアクセスをシミュレートします。
この一時的なイベントを観察するために、watch コマンドを使用します。これは別のコマンドを繰り返し実行し、netstat の出力をほぼリアルタイムで変更を確認できるようにします。
まず、監視ウィンドウを設定しましょう。ターミナルで次のコマンドを実行します。これにより、2 秒ごとに
netstat -antpが実行され、結果が表示され、画面が継続的に更新されます。watch netstat -antpa: すべてのソケットを表示します。n: 数値アドレスを表示します。t: TCP 接続のみを表示します。p: PID/プログラム名を表示します。
ターミナルには
netstatの出力が表示され、自動的に更新されます。このターミナルを開いたまま表示しておいてください。次に、接続を作成するコマンドを発行するために、新しいターミナルタブを開く必要があります。ターミナルのタブバーにある「プラス」アイコンをクリックしてください。
新しいターミナルタブで、
curlを使用して LabEx ウェブサイトのホームページを取得します。>記号は、HTML 出力を/dev/nullにリダイレクトするため、画面が乱雑になるのを防ぎます。curl https://www.labex.io > /dev/nullEnterを押すとすぐに、最初のターミナルタブ(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 ...StateがESTABLISHEDになっていることに注意してください。これはアクティブな接続を示しています。Foreign Addressはlabex.ioサーバーの IP アドレスとポート443(HTTPS の標準ポート) を表示します。PID/Program name列は、この接続を開始したプログラムがcurlであることを明確に識別します。Local Addressは、高番台のランダムなポート(例では45678のような)を使用します。これはエフェメラルポートであり、次のステップで詳しく説明します。
curlコマンドのダウンロードが完了すると(非常に高速です)、接続状態がTIME_WAITまたはFIN_WAITに変化してから、リストから完全に消えるのがわかります。これで
watchコマンドを停止できます。最初のターミナルタブに移動してCtrl+Cを押してください。2 番目のターミナルタブを閉じることもできます。
ESTABLISHED セッションとエフェメラルポートを特定する
この最終ステップでは、永続的なアクティブな接続を調べることで、理解を統合します。これにより、ネットワークの「セッション」を明確に特定し、システムがクライアント側の通信に一時的な、または「エフェメラル」ポートをどのように使用するかを確認できます。
netstat の出力における ESTABLISHED 接続は、アクティブなセッション(OSI レイヤー 5)を表し、2 つのアプリケーションがデータを交換する準備ができている状態です。前のステップの curl セッションは非常に短時間でした。セッションをより簡単に調査するために、SSH を使用して開いたままの状態を作成します。
まず、重要な概念であるエフェメラルポートを定義しましょう。コンピューター(クライアント)が既知のポート(SSH のポート 22 や HTTPS のポート 443 など)でサーバーに接続する場合、オペレーティングシステムは会話の自機側のためにポートを割り当てる必要があります。これは、高番台の範囲(通常は 32768 以上)から一時的な未使用ポートを選択します。これはエフェメラルポートと呼ばれます。このメカニズムにより、単一のコンピューターが同じサーバーポートに対して多くの個別の接続を持つことができます。例えば、同じウェブサイトに対して複数のブラウザタブを開くことができます。
安定した観測可能なセッションを作成するために、ラボマシンから自身に 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を押して続行します。パスワードを入力するように求められます。パスワードを入力する必要はありません。そのまま待機してください。
「プラス」アイコンをクリックして、新しいターミナルタブを開きます。アクティブな SSH セッションを妨げずに
netstatを実行するために、この新しいターミナルが必要です。新しいターミナルで
netstatを再度実行しますが、今回はgrepコマンドを使用して出力をフィルタリングし、ESTABLISHEDを含む行のみを表示します。これにより、アクティブなセッションを見つけやすくなります。netstat -antp | grep ESTABLISHED出力には、現在アクティブなすべての 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:46280が127.0.0.1:22に接続しています。プログラムは5449/sshとして明確に識別されています。 - ポート
46280はエフェメラルポートです。システムはこの特定の SSH セッションのクライアント側のためにランダムに選択しました。別のssh localhost接続を開くと、異なるエフェメラルポートが使用されます。
- 接続のサーバー側は
最後に、セッションを閉じます。
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 状態の接続を特定し、ネットワーク通信のクライアント側に割り当てられる一時的なポートであるエフェメラルポートの役割を理解することができました。



