第28回で 「サーバとクライアントは TCP/UDP ポートを持つプロセスにすぎない」 ことを確認し、第29回で HTTP を実際に書く 側を体験しました。本講ではさらに一段下、「ワイヤ(ネットワーク媒体)を実際に流れているバイト列そのものを観る」 視点に降ります。自分で書いた HTTP リクエスト がパケットとしてどう見えるかを、Wireshark で直接観察できるようになる回です。代表的なツールは Wireshark(GUI) と、その兄弟分の tshark / tcpdump / dumpcap(CLI)。Ethernet フレームから IP・TCP・HTTP・TLS まで、層を一枚ずつ剥がして読みます。取得フィルタ(BPF) と 表示フィルタ の違い、TCP の 3 ウェイ・再送・ウィンドウ の見え方、そして SSLKEYLOGFILE を使って TLS 通信を復号するところまで踏み込みます。
本講を終えると、以下を達成できるようになります。
図の見方:キャプチャは OS のパケットフックから生バイトを取る重い処理、解析はそれを TCP/HTTP/TLS など各層に分解する処理。GUI で全部やるのが Wireshark、サーバ上で tcpdump -w xxx.pcap して手元の Wireshark で開く運用も多い。
つながる知識: パケットキャプチャは OS から見ると ネットワークインタフェースのフックポイント に常駐する作業。Linux は AF_PACKET、macOS / BSD は BPF デバイス、Windows は Npcap(WinPcap の後継) が経路。この層は通常のユーザ権限では触れず、管理者権限 やキャプチャ専用グループ(Linux なら wireshark グループ)が必要。
確認: 本番サーバ(SSH 経由)で短時間だけパケットを取得してから、自分の PC の Wireshark で解析したい。最も適切な手段は?
正解:B。本番運用では「取得は CLI で軽量・解析は手元 GUI で快適」が定石。dumpcap や tcpdump はメモリフットプリントが小さくサーバへの負荷が少ない。生成された .pcap ファイルは Wireshark / tshark どちらでも開けるので、現場(取得)と分析(可視化)を分離できる。これが Wireshark のアーキテクチャが dumpcap・tshark・GUI に分割されている理由。
| OS | 導入 | 注意点 |
|---|---|---|
| Windows | Wireshark 公式インストーラ → Npcap も一緒にインストール(チェック必須) | Npcap を入れないとインタフェース一覧が空になる |
| macOS | brew install --cask wireshark + ChmodBPF を許可 | 初回起動時に「BPF デバイスへのアクセス許可」 ダイアログを承認 |
| Linux | apt install wireshark 等。インストール時に「非 root ユーザに dumpcap 実行を許可するか」 と聞かれる | 許可した場合、自分のユーザを wireshark グループに追加し再ログイン |
http://example.com/ を開く(HTTPS でなく HTTP の方が観察しやすい)http と入れて Enter → HTTP メッセージだけが残る図の見方:Wireshark の操作の 9 割は 「① で気になる行を選ぶ → ② で層を展開して読む → ③ でバイト位置を確認」 の往復。パケットを「読む」 とは、② の階層展開を上から下へたどる作業のこと。
Q. 「Wireshark で職場の Wi-Fi に流れている全パケットを覗ける」と思いきや、実際には自分宛のフレームしか見えない。なぜ? また、どんな環境なら他人のパケットが見えるのか?
有線 LAN(スイッチング・ハブ環境): スイッチは MAC アドレステーブルで宛先ポートを学習しており、他人宛のフレームを自分のポートに流さない。だから普通に Wireshark を起動しても自分宛しか見えない。古い「ダムハブ」(全ポートにブロードキャスト)時代の名残で、現代では覗けないのが標準。
Wi-Fi: 電波は誰でも受信できるが、Wi-Fi NIC は通常「自分宛フレームだけ取得」する管理モード。モニターモード(monitor mode) に切り替えると、空中を飛んでいる全フレームをキャプチャできる(macOS は airport sniff、Linux は iw)。ただし WPA2/3 の暗号化は健在で、鍵を持たないと中身は読めない。
覗けるケース: ① ダムハブ環境(教育用ラボ等)、② SPAN ポート / TAP(管理者の許可で全フローをミラー)、③ 自分の PC で完結する通信(VPN/ローカル等)。プライバシー保護は ネットワーク機器の設計 に依存しているという見方で、暗号化と二重で守られている。
図の見方:外側のヘッダから内側へ、Frame(物理 + 取得情報) → Ethernet → IP → TCP → HTTP と入れ子になっている。Wireshark の詳細ペインは、これをそのまま展開可能なツリーで見せる。第11回(階層化とカプセル化) の図が 実バイトとして可視化 される瞬間。
| 層 | 必ず見る項目 | 意味 |
|---|---|---|
| Frame | Time, Length, Interface | 取得時刻と長さ。前後パケットとの時間差(Δt) は性能解析の基本 |
| Ethernet | Src / Dst MAC, EtherType | 同一セグメント上の物理経路。EtherType=0x0800 が IPv4、0x86DD が IPv6 |
| IPv4 | Src / Dst IP, TTL, Identification | TTL の減り方で経由ルータ数。Identification は断片化の追跡用 |
| TCP | Src / Dst Port, Flags, Seq, Ack, Window | 後述の TCP セクションで深掘り |
| HTTP / TLS | Method, Host, Status, ALPN | アプリ層の意味。TLS は暗号化されているとここで止まる(後の節で復号) |
考えてみよう: 同じ Web ページを取得しても、HTTP/1.1 と HTTP/2、HTTP/3 でパケットの見え方は大きく違う。HTTP/1.1 は平文 ASCII でそのまま読めるが、HTTP/2 は バイナリフレーム で多重化、HTTP/3 は QUIC over UDP で TCP すら見えない。Wireshark は ALPN(Application-Layer Protocol Negotiation) を見て自動判別してくれる。次回 第33回 QUIC / HTTP/3 で、その差を再度見ます。
確認: HTTPS(TLS 1.3)で暗号化された通信を Wireshark でキャプチャしたとき、復号鍵を持たなくても観察できる情報はどれか。
正解:C。TLS は ペイロード(HTTP メソッド・URL・ヘッダ・本文) を暗号化するが、IP/TCP ヘッダや TLS のクライアントヘロー内 SNI は平文で見える。だから「どこに接続しているか」「どれくらいの量を流しているか」は復号なしで分かる(これがメタデータの限界)。Encrypted Client Hello(ECH)が普及すると SNI も隠れるが、IP・タイミングは依然見える。これが「TLS は中身を守るがメタデータは守らない」と言われる本質。
| 意図 | 取得フィルタ(BPF / tcpdump) | 表示フィルタ(Wireshark) |
|---|---|---|
| HTTP / HTTPS だけ | tcp port 80 or tcp port 443 | tcp.port == 80 || tcp.port == 443 |
| 特定 IP との通信 | host 93.184.216.34 | ip.addr == 93.184.216.34 |
| DNS だけ | udp port 53 | dns(プロトコル名でも書ける) |
| SYN パケットだけ | tcp[tcpflags] & tcp-syn != 0 | tcp.flags.syn == 1 && tcp.flags.ack == 0 |
| HTTP の GET | (BPF では難しい) | http.request.method == "GET" |
| TLS ハンドシェイクの ClientHello | (BPF では難しい) | tls.handshake.type == 1 |
ペイロード中身に基づく絞り込みは BPF では困難。BPF は ヘッダのバイト位置で素早く判定する低レベル機構なので、HTTP のテキスト中身や TLS のハンドシェイク種別のような 解析後でないと意味が分からない条件 は表示フィルタの仕事になります。
# TCP の再送だけ
tcp.analysis.retransmission
# 1500 バイト超の IP パケット(MTU超えの調査)
ip.len > 1500
# RST が立った TCP (異常切断)
tcp.flags.reset == 1
# DNS 応答で NXDOMAIN
dns.flags.rcode == 3
# HTTP/2 の SETTINGS フレーム
http2.type == 4
# 特定の TCP ストリーム全体(右クリック → Follow → TCP Stream で取得した番号)
tcp.stream eq 7
確認: 取得フィルタ(BPF)と表示フィルタの違いとして、最も適切なものはどれか。
正解:B。取得フィルタ(BPF)は カーネルレベルで動き、ディスクへの書き出し前にパケットを捨てる ─ ハイトラフィック環境で必須。一方、表示フィルタは 記録済みデータの可視化制御 で、解析中に何度でも条件を変えられる。実務では「取得は広めに保存、表示で詳しく絞る」が定石。文法も BPF と Wireshark フィルタは別系統(tcp port 80 vs tcp.port == 80 など)で、慣れが要る。
図の見方:Info 列の [SYN] / [SYN, ACK] / [ACK] の 3 行が 3 ウェイ。直後にデータ送信(GET) が続く。Time 列を見れば、SYN→SYN/ACK 間の往復時間 ≒ RTT(ここでは約 18ms)。これだけで「サーバまでの距離感」 が分かる。
Wireshark は TCP ストリームの状態を内部で追跡しており、同じ Seq の再送 や 失った Seq に対する Duplicate ACK を Info 列に [TCP Retransmission] や [TCP Dup ACK ...] と表示してくれます。表示フィルタで tcp.analysis.retransmission や tcp.analysis.duplicate_ack を入れれば、再送だけを抽出可能。
(1) RTT の急変(Time 列の差分でジッタを観察) → 経路の混雑、(2) ウィンドウの縮小(tcp.window_size が頭打ち) → 受信側のバッファ不足、(3) MTU の壁(tcp.len > 1400 のあたりで再送集中) → PMTUD 失敗、(4) ICMP Frag Needed(icmp.type == 3 && icmp.code == 4) → 経路 MTU 不一致。Wireshark の Statistics → TCP Stream Graph(時系列での Seq/Ack を可視化) を併用すると、どこで詰まっているかが視覚的に見える。
パケット一覧で気になる行を右クリック → Follow → TCP Stream。これだけで、その TCP セッションの送受信バイトをアプリ層の塊として整形表示してくれます。HTTP/1.1 の通信なら 「リクエストヘッダとレスポンスヘッダ・本文」 がそのまま 1 画面に 並びます。HTTPS だと暗号文が並ぶので意味不明 ─ 次節の TLS 復号と組み合わせると一気に有用になります。
# Chrome を SSLKEYLOGFILE つきで起動(macOS)
export SSLKEYLOGFILE="$HOME/sslkeys.log"
open -a "Google Chrome"
# curl の場合
curl --tlsv1.3 --keylog-file ~/sslkeys.log https://example.com/
# Linux で Firefox
SSLKEYLOGFILE=/tmp/sslkeys.log firefox &
sslkeys.log の中身は次のようなテキスト:
CLIENT_HANDSHAKE_TRAFFIC_SECRET 52d7e2bc... 4a91c0ab8f...
SERVER_HANDSHAKE_TRAFFIC_SECRET 52d7e2bc... 8d3f7e21a4...
CLIENT_TRAFFIC_SECRET_0 52d7e2bc... 1b22b7f0c9...
SERVER_TRAFFIC_SECRET_0 52d7e2bc... 6e0d8c4915...
Wireshark はこれらの secrets を使って TLS 1.3 のキーを再構成し、暗号文を復号して上の階層(HTTP/2) を表示できるようになります。
つながる知識: SSLKEYLOGFILE は RFC 文書ではなく業界事実上の標準(NSS Keylog format)。OpenSSL は SSL_CTX_set_keylog_callback() で出力できる。本機構があるからこそ、自社の HTTPS バックエンドとの通信不具合を Wireshark で追える。一方で 本番環境で常に有効化してはいけない(鍵が平文ファイルとして残る) ─ デバッグ時のみ、安全な手元環境で。
Q. 「SSLKEYLOGFILE を設定すれば、自分の PC で動くブラウザの HTTPS 通信を Wireshark で復号できる」と言うが、では 他人(別ホスト)の TLS 通信を盗聴して同じ手順で復号 できるか? できないなら、なぜ?
できない。 SSLKEYLOGFILE は「そのプロセスが自分で作った鍵を、自分のディスクに書き出す」機構。クライアントとして TLS を喋っているプロセスが 自発的に協力 しているから出力されるだけで、第三者は鍵を入手できない。
つまりこれは「自分の通信のデバッグ手段」であって、「他人の HTTPS を解読する手段」ではない。TLS の安全性は損なわれない:他人の鍵は他人のメモリにしか存在せず、ネットを流れるのは ECDHE で交換された鍵で暗号化されたバイト列だけ。
これが TLS 1.3 で「中間者が事後に鍵を入手しても過去のセッションを復号できない」Forward Secrecy が成立している理由でもある。RSA 鍵交換時代(古い TLS 1.2 サーバ)はサーバ秘密鍵が漏れると過去の全通信が事後復号できたが、ECDHE 限定の現代 TLS 1.3 ではセッション鍵がメモリから消えれば永久に復号不可能。
# 1) ライブで HTTP リクエストの URI だけ表示
tshark -i en0 -Y 'http.request' -T fields -e ip.dst -e http.host -e http.request.uri
# 2) pcap から DNS クエリ名を集計
tshark -r capture.pcapng -Y 'dns.qry.name' \
-T fields -e dns.qry.name | sort | uniq -c | sort -rn | head
# 3) TLS の SNI(Server Name Indication) 一覧
tshark -r capture.pcapng -Y 'tls.handshake.extensions_server_name' \
-T fields -e tls.handshake.extensions_server_name | sort -u
# 4) TCP ストリームの統計(再送・損失・ACK重複)
tshark -r capture.pcapng -q -z conv,tcp
# 5) JSON 出力(jq などへ流す)
tshark -r capture.pcapng -Y 'http.request' -T json | jq '.[] | ._source.layers.http'
# 6) リングバッファでの長時間キャプチャ(100MB × 5 ファイルでローテート)
dumpcap -i en0 -b filesize:100000 -b files:5 -w rotating.pcap
覚えるべき主要オプション:-i インタフェース、-r 入力 pcap、-w 出力 pcap、-Y 表示フィルタ、-f 取得フィルタ、-T fields -e ... 指定フィールド抽出、-q -z 統計表示。
つながる知識: サーバ上で問題を再現するときは、SSH 越しに root で tcpdump して pcap を持ち帰る のが定石。tcpdump -i any -w /tmp/x.pcap host 10.0.0.5 and port 443 のような形で取り、scp で手元へ。tshark は GUI 不要なので CI / 自動テスト・回帰検査に組み込みやすい。
| 症状 | Wireshark の見え方 | 一次仮説 |
|---|---|---|
| サーバに繋がらない | SYN は出るが SYN/ACK が一切返らない | 到達経路で FW がドロップ、または相手プロセスが listen していない(第28回参照) |
| すぐ切られる | 3 ウェイ完了直後に RST(Reset) | サーバ側アプリのエラー、ALPN 不一致、IP/ポートの誤り |
| 遅い・止まる | 大量の [TCP Retransmission] と Dup ACK | 経路の損失、Wi-Fi の電波品質、輻輳制御の介入 |
| 大きいデータだけ失敗 | ~1500B 周辺で再送集中、ICMP Frag Needed あり | PMTUD 失敗 ─ ICMP がブロックされ MTU 通知が届かない |
| HTTPS が落ちる | ClientHello → Alert: "handshake_failure" | ALPN / 暗号スイート / SNI / 証明書ミスマッチ |
| DNS が遅い | クエリ送信から応答まで >1s、または NXDOMAIN の連発 | リゾルバ到達不能、上流障害、DNSSEC の検証失敗 |
| 同じ IP から大量の SYN | 1 つのソース IP からの SYN だけで埋まる | SYN フラッド(攻撃) または NAT 配下の多数クライアント |
つながる知識: ここで挙げた症状の多くは、過去のレッスンで原理を学んだもの ─ TCP(第18回)、IP/ICMP/MTU(第20回)、TLS(第25回)、DNS(第13・39回)、ファイアウォール(第27回)。Wireshark は「学んだことを目で確認する装置」。逆に、原理を知らないと表示が読めない。教科書とパケット観察は両輪で動かすのが効きます。
| 用語 | 1行説明 |
|---|---|
| pcap / pcapng | パケットキャプチャの保存形式。pcapng は注釈・複数インタフェース対応の新版 |
| libpcap / Npcap | キャプチャドライバ。Unix 系は libpcap、Windows は Npcap(WinPcap 後継) |
| 取得フィルタ(BPF) | 取り込み段階で絞る低レベル構文。tcpdump と互換 |
| 表示フィルタ | 取った中から見せる範囲を絞る Wireshark 独自構文(tcp.port == 443) |
| パケット詳細(Packet Details) | 1 つのパケットを層ごとに展開表示するペイン |
| Follow Stream | 選択した会話の全パケットを抽出してアプリ層で整形表示する機能 |
| tcp.analysis.retransmission | Wireshark が自動検出した再送を表す表示フィルタ |
| SSLKEYLOGFILE | ブラウザ等が TLS 鍵情報を出力する環境変数。Wireshark が読み込んで復号 |
| tshark | Wireshark の CLI 版。フィールド抽出・統計・JSON 出力が可能 |
| dumpcap | 取得専用の軽量バックエンド。Wireshark / tshark が内部で使用 |
| プロミスキャスモード | NIC が自分宛以外のフレームも受信するモード(L2 観察用) |