ポート調査

サーバーのセキュリティ管理では、「意図していないポートで、意図していないサービスが外部からの接続を待ち受けていないか」を定期的に確認することが重要です。使っていないサービスがポートを開けたままになっていると、それ自体が攻撃者にとっての足がかり(アタックサーフェス)になり得ます。

開いているポートを調べる手段は1つではなく、大きく2つの視点に分けて理解すると整理しやすくなります。

  • サーバー自身の視点(ローカル):netstat・ss・lsof・fuserは、いずれもLinuxカーネルが持っているソケット(通信の接続口)の情報や、どのプロセスがそのソケットを使っているかという情報を、サーバー上で直接確認するコマンドです。
  • ネットワーク越しの視点(外部からの到達性):nmapは、実際にネットワーク経由でパケットを送り、応答があるかどうかを調べるポートスキャナーです。ファイアウォールの設定次第では、カーネルが実際にはポートを開いて待ち受けているにもかかわらず、外部からは到達できない、ということが起こり得ます。この「カーネルの内部状態」と「外部から見た実際の到達性」の違いを区別できることが、この分野の理解の核心です。

netstat:ネットワーク接続・ソケット状態の一覧表示(従来からのツール)

netstatは、ネットワーク接続の状態やルーティングテーブル、待ち受け中のソケットなどを表示する、古くから使われてきたコマンドです。

主なオプション

オプション意味
-l待ち受け中のソケットだけを表示する(TCPではLISTEN状態)
-a待ち受け中・接続済みの両方を含む、すべてのソケットを表示する
-tTCPソケットに限定する
-uUDPソケットに限定する
-nホスト名・サービス名の名前解決をせず、IPアドレス・ポート番号を数値のまま表示する
-pソケットを使用しているプログラム名・PIDを表示する

netstatをオプション無しで実行すると、既定では確立済み(接続済み)のソケットが中心に表示され、待ち受け中のソケットは表示されません。待ち受け中のポートを確認したい場合は-l(または-a)を明示的に指定する必要があります。実務では、これらを組み合わせたnetstat -tulnp(TCP・UDPの待ち受けソケットを、名前解決せずプログラム名付きで表示)という書き方がよく使われます。

-pオプションで他のユーザーが所有するプロセスの名前・PIDまで表示するには、多くの環境でroot権限(sudo)が必要です。一般ユーザーの権限では、自分が所有していないプロセスの情報が空欄になります。

netstatはnet-toolsパッケージに含まれるコマンドですが、net-toolsをあらかじめインストールしていないディストリビューションも増えており、後述のssが事実上の後継として使われる場面が多くなっています「netstatはもう使われていない」という理解は誤りです。LPIC・LinuC双方の公式出題範囲に現在も明記されている、試験対策上は欠かせないコマンドです。[1]。

ss:iproute2に含まれる、より新しいソケット確認コマンド

ss(socket statistics)は、iproute2パッケージに含まれる、netstatと同様の目的(ソケットの状態確認)のために作られたコマンドです。多くの現行ディストリビューションで既定でインストールされています。

ssはnetstatからの移行をしやすくするため、多くのオプション文字が共通化されています。

ss -tulnp

上記は、netstat -tulnpとほぼ同じ意味(TCP・UDPの待ち受けソケットを、名前解決せずプログラム名付きで表示)になります。-pで他ユーザーのプロセス情報まで表示するにはroot権限が必要な点も、netstatと同様です。

nmap:ネットワーク越しにポートの到達性を調べるスキャナー

nmap(Network Mapper)は、対象ホストに実際にパケットを送信し、応答を観察することでポートの状態を調べるポートスキャナーです。netstat・ssのようにカーネルの内部情報を直接読み取るのではなく、ネットワークを介した実際の到達性を確認する点が本質的に異なります。

自分が管理していないホストに対して許可なくポートスキャンを行うことは、相手先の運用ポリシーや法令に抵触する可能性があります。nmapは自分が管理する、または明示的に許可を得たホストに対してのみ使用してください。

基本的な使い方

nmap 192.168.1.10

ポート番号を-pで指定しない場合、nmapは既定でよく使われる代表的な1,000個のポート(TCP)を対象にスキャンします。すべてのポートを対象にしたい場合は-p-(1〜65535番をすべて指定)を使います。

スキャン方式とroot権限の関係

nmapは、実行するユーザーの権限によってスキャン方式が変わります。

  • root権限で実行した場合、既定ではSYNスキャン(TCPの3ウェイハンドシェイクを最後まで完了させない、いわゆる「半開放」スキャン)が使われます。
  • root権限が無い環境では、生パケットを直接送信できないため、既定ではTCP接続スキャン(connect()システムコールを使い、実際に接続を完了させるスキャン)にフォールバックします。

両者は挙動が異なりますが、いずれもポートが「開いている(open)」「閉じている(closed)」「フィルタされている(filtered、応答が無くファイアウォール等で遮断されていると考えられる)」のいずれかを判定するという目的は共通しています。

netstat・ssとの結果の違いに注意

netstat・ssは「サーバー自身のカーネルが、そのポートで待ち受けているかどうか」を答えます。一方nmapは「ネットワーク経由で、実際にそのポートへ到達できるかどうか」を答えます。ファイアウォールで特定のポートへのアクセスを遮断している場合、netstat -lではそのポートが待ち受け状態として表示される一方で、外部からnmapでスキャンするとfiltered(またはポリシーによってはclosed)と判定されることがあります。TCPでは待ち受け状態はLISTEN状態として表示されます。「サーバー内部での待ち受け状況」と「外部からの実際の到達性」は必ずしも一致しない、という点を区別して理解しておくことが重要です。

lsof:開いているファイルとしてのソケットを確認する

Linuxでは、通常のファイルだけでなくネットワークソケットも「ファイルディスクリプタ」として扱われます。lsof(list open files)は、その名のとおりプロセスが開いているファイル(ソケットを含む)の一覧を表示するコマンドで、-iオプションを付けるとネットワーク関連の項目に絞り込めます。

lsof -i :80

上記は、TCP・UDPを問わずポート80番を使用しているプロセスを表示します。プロトコルを限定したい場合はlsof -i tcp:80のように指定します。netstat・ssの-pと同様、自分以外のユーザーが所有するプロセスの詳細まで確認するには、多くの環境でroot権限が必要です。

fuser:特定のポートを使っているプロセスを直接特定する

fuserは、指定したファイル(またはポートのようなリソース)を現在使用しているプロセスのPIDを表示するコマンドです。ネットワークポートを指定する場合は、ポート番号/プロトコルという省略形で指定できます。

fuser 80/tcp

上記は、TCPポート80番を使用しているプロセスのPIDを表示します(fuser -n tcp 80という書き方でも同じ意味になります)。

fuserには-kオプションがあり、指定したリソースを使用しているプロセスをその場で終了(既定ではSIGKILLを送信)できます。稼働中のサービスを誤って終了させてしまう恐れがあるため、-kの使用は原因調査で対象プロセスを確実に特定できた後に限るなど、慎重な取り扱いが必要です。
また、マウントしたファイルシステムを指定する-mオプションと詳細表示する'-v'オプションを組み合わせることで、当該マウントポイントを使用しているプロセスを特定することが可能です。

まとめ:5つのコマンドの立ち位置

コマンド情報の出どころ視点
netstatカーネルのソケット情報(net-tools)サーバー自身(ローカル)
ssカーネルのソケット情報(iproute2、より新しい実装)サーバー自身(ローカル)
nmapネットワーク経由の実測外部(ネットワークの向こう側)
lsofプロセスが開いているファイルディスクリプタ(ソケット含む)サーバー自身(ローカル)
fuser指定したポート・ファイルを使用しているプロセスの特定サーバー自身(ローカル)

補足

  1. 「netstatはもう使われていない」という理解は誤りです。LPIC・LinuC双方の公式出題範囲に現在も明記されている、試験対策上は欠かせないコマンドです。 ↩