tcpdumpの深淵:パケットドロップを許さない、高負荷環境の「真実」を切り取る技術
ネットワークエンジニアにとって、tcpdumpは最後の砦だ。しかし、真夜中のデータセンターで、10Gbpsを超えるトラフィックが流れるリンクを前にしたとき、あなたは「なんとなく」コマンドを打っていないだろうか?
「パケットが消えた」と騒ぐ現場で、実はキャプチャツール自体が悲鳴を上げてパケットを捨てている。そんな恥ずべき事態を避けるために、今日はtcpdumpにおけるスナップショット長(snaplen)の最適化と、カーネルレベルのバッファリングについて、現場の泥臭い知見を共有する。
なぜ「デフォルト」ではいけないのか
tcpdumpのデフォルトのsnaplenは、多くの環境で 68 または 96 バイト程度だ。これはEthernetフレームのヘッダーとIP、TCPヘッダーを拾うには十分だが、昨今のモダンなアプリケーション解析にはあまりに心許ない。
もし君が、TLSのClient Helloに含まれるSNI(Server Name Indication)を確認したり、HTTP/2のヘッダー圧縮(HPACK)の挙動を追うのであれば、この設定は致命的だ。パケットのペイロードまで含めてキャプチャしようとしてsnaplenを0(無制限)にするエンジニアもいるが、高トラフィック環境ではそれが「自爆スイッチ」になる。
スナップショット長とパフォーマンスのトレードオフ
snaplenを広げれば、それだけカーネルからユーザースペースへのコピーコストが増大する。特にパケットレートが高い環境では、CPUの割り込み処理が飽和し、キャプチャそのものがボトルネックとなって、本来追うべき障害の痕跡すら消し去ってしまう。
現場では、「必要な情報を、最小限のコストで抜く」のがプロの流儀だ。
# ヘッダー解析に特化する場合(80-128バイト程度で十分なケースが多い)
# -s 128: Ethernet(14) + IP(20) + TCP(20) + オプション + ペイロードの先頭部分
tcpdump -i eth0 -s 128 -w capture.pcap 'tcp port 443'
TLSハンドシェイクのログを取りたい場合は、128バイトでは足りない。SNIまで見たいなら、最低でも256バイト程度は確保しておくと安心だ。
高トラフィック環境の敵:バッファあふれを制する
高負荷なリンクでtcpdumpを動かすと、dropped by kernelという冷徹なメッセージが画面を流れることがある。これは、カーネルがパケットをtcpdumpのリングバッファにコピーする速度よりも、NICがパケットを受信する速度が上回ったときに発生する。
これを防ぐための最大の武器が -B(バッファサイズ)オプションだ。
Linuxカーネルのリングバッファを拡張せよ
デフォルトのバッファサイズでは、数ミリ秒のバーストトラフィックに耐えられない。現場では、最低でも128MB、高負荷なら256MB以上を割り当てるのが定石だ。
# バッファを256MBに拡張し、スナップショット長をTLS解析用に適正化
# -B 262144: 256MBのバッファを確保
# -n: 名前解決を無効化(DNS遅延によるキャプチャ漏れを防ぐ)
tcpdump -i eth0 -n -s 256 -B 262144 -w investigation.pcap 'host 10.0.1.5 and tcp port 443'
もしこれでもパケットが落ちるなら、tcpdumpの実行プロセスがCPUコアを占有できていない可能性がある。tasksetを使って、当該NICの割り込み処理が行われているCPUコアと、tcpdumpプロセスを同じNUMAノード上に固定してやるだけで、劇的にドロップ率は改善する。
なぜ「ヘッダーだけ」にこだわるのか
インフラアーキテクトとして、我々が真に注目すべきは「パケットの中身」ではない。パケットが刻む「時間」と「順序」だ。
- RTT(Round Trip Time)の計測:
SYNを送ってからSYN-ACKが返るまでの時間。ここをtcpdumpで正確に追いかける際、snaplenが大きすぎると、カーネルがパケットを処理するまでの「ジッター(揺らぎ)」が計測結果に混入する。 - TLSハンドシェイクの最適化: セッション再開(Session Resumption)のパケットを解析する際、余計なペイロードはノイズでしかない。
ヘッダー情報さえあれば、Wireshark(tshark)の統計機能を使って、TCPのウィンドウサイズ推移や、再送発生のトリガーを論理的に特定できる。
現場の知恵:運用監視への落とし込み
最後に、本番環境で運用中のエンジニアへアドバイスを一つ。tcpdumpを長時間回し続けるのはNGだ。ディスクのI/O負荷がシステム全体を巻き込む。
もし継続的な監視が必要なら、tcpdumpではなくeBPFベースのツール(tcptopやbiolatencyなど)への移行を検討すべきだ。しかし、障害が起きた「その瞬間」を切り取るためのtcpdumpの作法は、今後も変わらない。
1. -n を忘れるな: 現場で名前解決待ちが発生すると、キャプチャの整合性が崩れる。
2. フィルタを極限まで絞れ: host、port、tcp-synなどのフラグを組み合わせ、不要なトラフィックをカーネル側で捨てさせる。
3. -B でゆとりを持て: メモリをケチるな。パケットが落ちて原因が特定できないコストに比べれば、数百MBのメモリなど安いものだ。
ネットワークは生き物だ。その挙動をパケットレベルで正確に観測できるエンジニアだけが、複雑怪奇な分散システムのトラブルを沈静化できる。さあ、次は君の番だ。ターミナルを開き、コマンドに魂を込めろ。
コメント