エンジニアリング記事

クラウドMacの待受ポートを監査してネットワーク露出を減らす

クラウドMacの待受ポートを監査してネットワーク露出を減らす

リモートMacでビルドを何度か実行すると、開発ツール、デバッグサーバー、パッケージマネージャー、一時スクリプトなどが待受ポートを残すことがあります。本当に問題なのは「ポート数が多い」ことではなく、誰が待ち受けているのか、どのアドレスにバインドされているのか、マシンの再起動後にも再び現れるのかという3点を把握できないことです。ここではmacOS標準ツールを使って、再現可能な読み取り専用の監査手順を確立し、ネットワーク露出を段階的に減らしていきます。

待受ポートのベースラインを作成する

まず、ノードがアイドル状態にあり、一時的なデバッグタスクが動いていないときにTCPとUDPの状態を取得します。-nPを指定すると、名前解決とポート番号からサービス名への変換を回避できるため、出力を保存して比較しやすくなります。

mkdir -p "$HOME/audit/network"
stamp="$(date -u +%Y%m%dT%H%M%SZ)"

sudo lsof -nP -iTCP -sTCP:LISTEN \
  > "$HOME/audit/network/tcp-$stamp.txt"

sudo lsof -nP -iUDP \
  > "$HOME/audit/network/udp-$stamp.txt"

netstat -anv -p tcp \
  > "$HOME/audit/network/netstat-tcp-$stamp.txt"

ポート番号だけで判断してはいけません。COMMANDPIDUSERNAMEをまとめて確認する必要があります。同じ開発サーバーでも、一般ユーザーとして実行されている場合と、正体不明のプログラムがrootとして実行されている場合とでは、対応の優先度がまったく異なります。

待受形式 一般的な意味 次に確認すること
127.0.0.1:8080 IPv4のローカルホストからのみアクセス可能 想定した開発サービスか確認する
[::1]:8080 IPv6のローカルホストからのみアクセス可能 この設定を維持し、SSH転送をテストする
*:8080 利用可能なすべてのインターフェースで待ち受け プロセスを特定し、優先的にバインド範囲を狭める
10.x.x.x:8080 特定のインターフェースにバインド ノードのネットワークポリシーと照合する
固定された通信相手がないUDP 検出サービスまたは補助サービスの可能性 プロセスの用途と起動元を調べる

LISTENだからといって、必ず外部から到達できるわけではありません。最終的な到達可否は、待受アドレス、ホスト側のファイアウォール、ノードのネットワークポリシーによって決まります。ただし、ワイルドカードアドレスはプロセスが自ら受信範囲を広げていることを意味するため、優先して理由を確認する必要があります。

ポートからプロセスと起動項目を特定する

PIDを特定したら、psで完全なコマンド、親プロセス、実行時間を確認し、常駐する起動項目から実行されていないか調べます。

pid=1234
ps -p "$pid" -o pid,ppid,user,lstart,command
sudo lsof -nP -p "$pid"

launchctl print "gui/$(id -u)" > "$HOME/audit/network/launch-gui.txt"
sudo launchctl print system > "$HOME/audit/network/launch-system.txt"

find "$HOME/Library/LaunchAgents" \
  /Library/LaunchAgents \
  /Library/LaunchDaemons \
  -maxdepth 1 -name '*.plist' -print 2>/dev/null

疑わしいplistについては、plutil -p ファイルパスを使ってProgramProgramArgumentsRunAtLoadKeepAliveを確認します。ビルドスクリプトが一時的に起動したプロセスであれば、タスクの終了後に停止するはずです。KeepAliveによって繰り返し再起動される場合は、単にkillを実行するだけでは解決できません。

対応台帳を作成する

システム以外の待受項目については、少なくともサービスの用途、担当者、起動方法、バインド先アドレス、維持する理由を記録します。所有者や用途を特定できないプロセスは、まず関連タスクを停止し、コマンドライン、ログのパス、plistの内容を保存してください。すぐにファイルを削除すると、調査に必要な情報が失われます。

ポートを塞ぐ前にバインド先をループバックへ変更する

開発サービスを現在のユーザーだけが利用する場合、最も直接的な対策はループバックアドレスにバインドすることです。これにより、ファイアウォールルールが変わっても、プロセスがほかのインターフェースからの接続を受け付けることはありません。

python3 -m http.server 8080 --bind 127.0.0.1

HOST=127.0.0.1 PORT=8080 ./run-development-server

自分のコンピューターからアクセスする場合は、SSHローカル転送を入口として使用します。

ssh -N \
  -L 127.0.0.1:9000:127.0.0.1:8080 \
  "$REMOTE_USER@$REMOTE_HOST"

その後、ローカルの127.0.0.1:9000へアクセスします。同時に、起動パラメーターが反映されず*:8080へ戻っていないこと、リモートサービスが引き続き127.0.0.1:8080だけで待ち受けていることも確認してください。

バインド先を限定する方法は、遮断ルールを追加するよりも一般に検証しやすく、リモート管理接続を誤って切断する危険も抑えられます。ファイアウォールは第2の制御層であり、サービスの正しい待受設定の代わりにはなりません。

2層のファイアウォールを読み取り専用で確認する

macOSのアプリケーションファイアウォールとpfでは、対象とする領域が異なります。監査時はまず状態を読み取り、リモートセッション中にルールを直接上書きしないでください。

sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --listapps

sudo pfctl -s info
sudo pfctl -sr
sudo pfctl -sn

アプリケーションファイアウォールの一覧では、受信接続を許可されているプログラムを確認できます。pfの出力では、フィルタリングルールとアドレス変換ルールを確認します。異常が見つかった場合は、まず完全な出力を保存し、そのルールがシステム設定、運用手順、一時的な実験のどこから追加されたものかを確認してください。

pfをリモートから変更する際の最大のリスクは、構文エラーではなく、現在使用している管理接続まで遮断してしまうことです。検証済みの第2の接続経路がない場合は、読み取り専用の確認にとどめてください。変更がどうしても必要であれば、事前にルールをバックアップし、ロールバック用のコマンドを明確にしたうえで、別のセッションからコンソールへ継続的に到達できることを確認します。

差分確認でポートの再発を防ぐ

一度のクリーンアップだけでは、その後のツール更新、ビルドスクリプトの変更、新しい起動項目の追加には対応できません。環境の初期化が完了した時点で承認済みのベースラインを保存し、大きな変更を加えるたびに状態を取得し直すことを推奨します。

latest_tcp="$(ls -t "$HOME"/audit/network/tcp-*.txt | head -n 1)"
diff -u "$HOME/audit/network/tcp-approved.txt" "$latest_tcp"

latest_udp="$(ls -t "$HOME"/audit/network/udp-*.txt | head -n 1)"
diff -u "$HOME/audit/network/udp-approved.txt" "$latest_udp"

差分に新しい項目が現れた場合は、決められた順序で確認します。まずプロセスの所有者や用途を特定し、次に待受アドレスと起動元を確認します。その後、リモートアクセスが必要か判断し、最後に維持するか、ローカルバインドへ変更するか、無効化するかを決定します。ポート番号を静的な許可リストへ追加しただけで追跡を終えてはいけません。同じポートを別のプログラムが使用する可能性があるためです。

OwnAMacの専有物理ノードでも、この手順はビルドエージェント、プレビューサーバー、テスト用コールバックプロセス、一時ファイルサービスにそのまま適用できます。完了後は、元のスナップショット、対応記録、再確認の結果を保存してください。次に環境を変更するときは、現在の状態を一から推測するのではなく、差分の確認から始められます。

よくある質問

LISTENと表示されたポートはインターネットから接続できますか?

必ずしも接続できるとは限りません。待受アドレス、ネットワークポリシー、ファイアウォール規則を確認します。127.0.0.1や::1は通常ローカル限定ですが、*やインターフェースのアドレスは外部から検証が必要です。

リモート監査中にpfの規則を変更してもよいですか?

復旧経路を確認できる場合に限ります。現在の規則と待受一覧を保存し、管理接続をもう一つ確保してから小さな変更を試します。復旧手段がなければ読み取り専用の監査に留めます。

localhostだけで待受するサービスへ手元のPCから接続する方法は?

SSHのローカルポート転送を使います。手元のポートをリモート側の127.0.0.1に転送すれば、サービスを全インターフェースへ公開せずに利用できます。

OwnAMac クラウドMac

次のビルドを専有Apple Silicon物理ノードで実行

タスクの規模に合わせて3つの構成と5つのノードから選択できます。計算リソースとストレージは他のテナントと共有されません。すべてのノードは365日、年間を通じて安定稼働しています。実際の利用可能状況はコンソールのリアルタイム表示をご確認ください。

構成を選んで注文する