WiresharkでUSBフィルタ:USBPcap、usbmon、Bus Scopeで対象デバイスを特定する
USBPcapやusbmonのキャプチャ量が膨大になったとき、デバイス・エンドポイント・転送種別・Setupパケット・インターフェース・タイミングでUSBキャプチャを絞り込む方法を解説します。
USBキャプチャはすぐに肥大化します。1台のマシンに、キーボード/マウス/Webカメラ/Bluetoothアダプタ/ストレージ/シリアルアダプタ/セキュリティキー/内部ハブが同時に動いていることも珍しくありません。「Wireshark USB filter」「USBPcap filter device」「usbmon filter endpoint」「how to find my USB device in capture」で検索する人たちの問題はほぼ同じ。キャプチャには多すぎるトラフィックと少なすぎる構造が入っています。
Bus ScopeはUSB検査をより直接にするために作られていますが、フィルタリング問題自体を理解しておくのは依然として有用です。キャプチャ元がUSBPcap(Windows)であれusbmon(Linux)であれ、あるいは別のUSBキャプチャ元であれ、鍵は「デバイスを特定してから、転送種別・エンドポイント・コントロールリクエストで絞り込む」ことです。
列挙から始める
USBデバイスを識別する最も簡単な方法は、接続時からキャプチャすることです。列挙にはデバイスを名指しするディスクリプタが入っています。VID、PID、コンフィギュレーション、インターフェース、エンドポイント、クラス固有詳細など。
確認ポイント:
- Vendor ID
- Product ID
- デバイスディスクリプタ
- コンフィギュレーションディスクリプタ
- インターフェースディスクリプタ
- エンドポイントディスクリプタ
- 文字列ディスクリプタ
SET_ADDRESSSET_CONFIGURATION
デバイスの動作開始後にキャプチャを始めると、ディスクリプタの文脈なしにエンドポイントトラフィックしか見えないことがあります。エンドポイント番号だけでは絞り込みが難しくなります。
デバイスアドレスは変わり得る
USBデバイスアドレスは列挙中にホストが割り当てます。切断・再接続するとアドレスは変わるかもしれません。1回目の接続で動いたフィルタが2回目を見落とすことがあります。
リセットループのデバッグでこれは重要です。デバイスが繰り返し再列挙するなら、1つのキャプチャ内で複数アドレスを追う必要があります。Product/Vendorディスクリプタを見れば、それらが同じ物理デバイスだと分かります。
Bus Scopeは、この関係を見える形で保つ助けをします。アドレス変更を頭の中で縫い合わせる必要はありません。
エンドポイントでフィルタする
コンフィギュレーション後、ほとんどのデータトラフィックはエンドポイントを使います。エンドポイントゼロはコントロール用。ほかのエンドポイントはバルク/インタラプト/アイソクロナスになり得ます。
よくあるエンドポイントの読み方:
0x00:エンドポイントゼロのコントロールOUT0x80:エンドポイントゼロのコントロールIN0x81:エンドポイント1 IN0x01:エンドポイント1 OUT0x82:エンドポイント2 IN0x02:エンドポイント2 OUT
方向ビットが大事です。0x81 と 0x01 は方向が違う別物です。たとえばシリアルアダプタは、ホスト→デバイス用にバルクOUTを、デバイス→ホスト用にバルクINを使うことがあります。
エンドポイントフィルタは、対象トラフィックがどのエンドポイントを運ぶかを既に知っているときに有用です。
転送種別でフィルタする
USB問題は転送種別ごとに棲み分けます。
- コントロール転送:ディスクリプタ、コンフィギュレーション、クラスリクエスト、ベンダーコマンド
- バルク転送:ストレージ、シリアルデータ、ベンダーデータ、多くのキャプチャデバイス
- インタラプト転送:HID入力、ステータス通知、低遅延レポート
- アイソクロナス転送:オーディオ、ビデオ、時間に敏感なストリーミング
USBシリアルデバイスがポートを開いてもデータを送らないなら、ラインコーディング/コントロールライン状態向けにコントロール転送を、その後バルクエンドポイントのペイロードを観察。Webcamの映像が壊れるなら、アイソクロナス転送とAlternate Settingを観察。HIDデバイスが変なら、インタラプト転送とレポートディスクリプタを観察。
転送種別でフィルタすれば、ノイズを減らしながら必要なクラスの証拠を保てます。
Setupパケットでフィルタする
コントロール転送にはSetupパケットが含まれます。Setupパケットはリクエスト方向、種別、受信者、リクエストコード、Value、Index、Lengthを識別するので極めて有用です。
重要な例:
GET_DESCRIPTORSET_ADDRESSSET_CONFIGURATIONSET_INTERFACECLEAR_FEATURE- HID
GET_REPORT - HID
SET_REPORT - CDC
SET_LINE_CODING - CDC
SET_CONTROL_LINE_STATE - ベンダー固有コマンド
セットアップ中にデバイスが落ちるなら、Setupパケットを見ればどのリクエストが問題を起こしたかが正確に分かります。
WindowsのUSBPcapキャプチャ選択
Windowsでは、USBPcapはUSBホストコントローラからキャプチャします。マシンに複数のコントローラがある場合、誤ったものを選ぶと、対象デバイスのトラフィックが含まれない空のキャプチャになります。
実用的なワークフロー:
- 対象デバイスを抜く
- 想定されるコントローラでキャプチャ開始
- デバイスを挿す
- 列挙ディスクリプタを探す
- 何も出ない場合、別コントローラのキャプチャを試す
- デバイスが見つかったら、そのキャプチャを参照用に残す
Bus Scopeの価値は、このワークフローを不透明でなくする点にあります。ターゲットは「巨大なパケットリスト」ではなく「USBデバイスとの会話」です。
Linuxのusbmonキャプチャ
Linuxでは usbmon がUSBバストラフィックを露出します。バス番号が大事です。Bus 003 Device 012 としてリストされるデバイスは、その瞬間バス3に属します。再接続後はデバイス番号が変わるかもしれません。
最も有用なキャプチャは接続前から始まるもので、列挙がデバイス識別子を明らかにします。権限でキャプチャがブロックされるなら、まずそれを解決してください。そうでないと、アプリ層の失敗しか見えず、USBの証拠にはたどり着けません。
よくあるフィルタリングミス
次のミスを避けてください。
- 失敗後だけフィルタして列挙を取り逃す
- デバイスアドレスが再接続をまたいで一定だと思い込む
- エンドポイント方向を取り違える
- エンドポイントゼロのコントロールトラフィックを無視する
- ペイロードパケットだけ見てクラスリクエストを取り逃す
- ベンダー固有リクエストをすべてノイズ扱いする
- リセットやエラーを早期にフィルタアウトする
- ハブ/ポートのコンテキストを無視する
クリーンなフィルタは、失敗を保全してこそ意味があります。
調査用キャプチャに残すべきもの
ファームウェア/ドライバ/QAチームと共有するレポートには、次を残してください。
- 初期列挙
- 対象デバイスのディスクリプタ
- ホストが選択したコンフィギュレーションとインターフェース
- 失敗前のクラス/ベンダー固有リクエスト
- 失敗が起きたエンドポイントトラフィック
- リセット/ストール/タイムアウト/切断イベント
- 失敗が即時か、アイドル起因か、負荷起因かを示すタイミングコンテキスト
この証拠は「デバイス認識されません」のスクリーンショットよりずっと強力です。
最終的な診断
USBフィルタリングはノイズを隠す作業ではなく、「失敗を説明するパケットシーケンスを保全する」作業です。列挙から始めて、デバイスを識別し、アドレス変化を追跡し、エンドポイントと転送種別で絞り込み、コントロールリクエストを見えるまま保つ。
Bus Scopeはそのワークフローを支えるためにあります。実際のUSBの会話を素早く見つけ、なぜデバイスが動く/ストールする/リセットする/消えるのかをバスレベルの証拠で説明する。