障害対応の現場から:ssコマンドを極めて「見えないパケット」を可視化せよ
ネットワーク運用、あるいはWeb APIのバックエンド開発をしていると、必ずと言っていいほど「なぜか繋がらない」「通信が詰まっている」という事態に直面します。そんな時、あなたはまず何を叩きますか? netstatですか? それともlsof?
もし、まだss(Socket Statistics)コマンドを使いこなせていないのであれば、あなたのトラブルシューティングはまだ「原始時代」にあるかもしれません。netstatが非推奨(deprecated)となりつつある今、高速かつ高機能なssこそ、我々インフラエンジニアの最強の武器です。
今回は、数々の修羅場をくぐり抜けてきた私が、現場で本当に使えるssのフィルタリング術を伝授します。
なぜ ss なのか?
netstatはカーネルの /proc/net/tcp を直接読み込みますが、高負荷なサーバーでは接続数が膨大すぎて、結果が返ってくるまでに数秒かかることがあります。一方、ssはカーネル内部の netlink ソケットを直接叩くため、圧倒的に高速です。
何より、ssの真骨頂は「強力なフィルタリング機能」にあります。膨大なノイズの中から、真に原因となっているソケットをピンポイントで射抜く。これこそが、障害時の冷静さを保つ秘訣です。
基本的な構文とフィルタリングの鉄則
ssのフィルタリングは、コマンドの末尾に filter 式を記述することで行います。
# 基本形:ss [オプション] [フィルタ式]
ss -nt state established '( dport = :80 or dport = :443 )'
この構文を覚えておくだけで、監視の解像度が劇的に変わります。
1. state で特定の通信状態を絞り込む
APIサーバーが「TIME_WAIT」で溢れかえっている時、まず見るべきはこれです。
# TIME_WAIT状態のソケットだけを抽出して数える
ss -tn state time-wait | wc -l
# 接続確立済みのものに絞る
ss -tn state established
TIME_WAITが異常に多い場合は、クライアント側(あるいはバックエンドへのコネクション)の再利用ができていない証拠です。Web API設計において、Keep-Aliveの挙動を疑うべきサインですね。
2. sport と dport でポートを特定する
特定のサービスポートに絞り込むのは基本中の基本です。
# 宛先ポートが 8080 の通信だけを詳細表示
ss -nt dst :8080
# 送信元ポートが範囲指定(1024〜65535)の場合
ss -nt sport gt :1023
ここで重要なのは、dst(宛先)と src(送信元)の使い分けです。外部からのリクエストを追いかけるなら dst、自サーバーからバックエンド(DBやRedisなど)へ向かう通信なら src で絞り込むのが現場の定石です。
実践:Pythonで叩いたAPIの「残り香」を追跡する
例えば、Pythonの requests ライブラリで外部APIを叩いた直後のコネクション状態を確認したいとします。
import requests
# 意図的にコネクションを張る
url = "https://api.example.com"
response = requests.get(url)
print(response.status_code)
# ここでスクリプトを一時停止させて、別ターミナルから ss を叩く
input("Press Enter to finish...")
このスクリプトを実行中に、サーバー上でこう打ち込みます。
# 該当ドメインへの通信を特定する
ss -ntp dst 93.184.216.34
ここで -p オプションを付けるのがポイントです。どのプロセスがそのソケットを握っているのか(PID)が分かれば、ゾンビ化しているプロセスを特定し、kill ではなく SIGTERM で正しく終了させるという、エンジニアとしての「作法」を守ることができます。
現場で使う「一歩先」のフィルタリング例
最後に、私が障害対応の現場でよく使う「合わせ技」を紹介します。
例1:特定のIPアドレスからの攻撃や異常な通信を炙り出す
# 特定の送信元IPからの確立済み通信のみを表示
ss -nt state established src 192.168.1.100
例2:ソケットの情報を詳細に表示し、バッファ詰まりを確認する
# -o でタイマー情報(再送回数など)、-m でメモリ使用量を表示
ss -ntom 'sport = :443'
※ Recv-Q や Send-Q に値が溜まり続けている場合、TCPウィンドウサイズ制御がうまくいっていないか、アプリケーション層での処理がボトルネックになっています。
最後に:ツールに振り回されるな
どんなに優れたツールも、それを使う人間の「仮説」がなければただの文字列の羅列です。
ssでフィルタリングを行いながら、「なぜこのソケットは FIN_WAIT_2 のままなのか?」「なぜ Send-Q が減らないのか?」と自問自答してください。ネットワークエンジニアにとって一番大切なのは、CLIコマンドそのものではなく、その出力結果からパケットの行く末を脳内でシミュレーションする力です。
さあ、次はあなたのターミナルで ss を叩いてみてください。ノイズの中から、解決の糸口が見えるはずです。
コメント