Create usbmon capture

From postmarketOS
Note Captured traffic usually contains sensitive data like phone numbers - don't just upload it to public bug reports without reviewing what's in there!

This article explains how to create usbmon captures with postmarketOS. One use case is capturing traffic between a USB attached modem inside the device (like the eg25-g in the PinePhone) to figure out modem related problems.

Preparation

Kernel module

Load the usbmon kernel module:

$ sudo modprobe usbmon

If it is not available for the kernel that your device uses, adjust your kernel config to enable CONFIG_USB_MON, build the kernel on your PC and install it. Make a merge request to pmaports so it will be enabled for others in the future.

Find the USB bus

Use lsusb to figure out the relevant USB Bus ID. In this example, it is the bus 2.

$ sudo apk add usbutils
$ lsusb
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 2c7c:0125 Quectel Wireless Solutions Co., Ltd. EC25 LTE modem
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Find the interface

This guide uses tcpdump to capture the traffic. Find the relevant interface first, in the example usbmon2.

$ sudo apk add tcpdump
$ sudo tcpdump --list-interfaces
1.wlan0 [Up, Running, Wireless, Associated]
2.any (Pseudo-device that captures on all interfaces) [Up, Running]
3.lo [Up, Running, Loopback]
4.usb0 [Up, Disconnected]
5.usbmon5 (Raw USB traffic, bus number 5)
6.usbmon4 (Raw USB traffic, bus number 4)
7.usbmon3 (Raw USB traffic, bus number 3)
8.usbmon2 (Raw USB traffic, bus number 2)
9.usbmon1 (Raw USB traffic, bus number 1)
10.usbmon0 (Raw USB traffic, all USB buses) [none]
11.nflog (Linux netfilter log (NFLOG) interface) [none]
12.nfqueue (Linux netfilter queue (NFQUEUE) interface) [none]
13.wwan0 [none, Disconnected]

Capture

Over SSH

A convenient setup is running wireshark on your PC and have it analyze the traffic in real time. Enable SSH and configure it so you can login with your PC's SSH key as root on your phone. Then run the following script on your PC to launch tcpdump over ssh, and pipe its output into wireshark. Once you run the command, you need to login via SSH first (e.g. type in the password of your SSH key). Afterwards the connection should be established, and whenever something happens on the USB, you should see related packages in wireshark.

#!/bin/sh -ex

interface="usbmon2"
host="192.168.1.82"

ssh root@"$host" \
        tcpdump -i "$interface" -s0 -w - -U \
        | wireshark -k -S -i -

Locally

Depending on what you want to test, you might need to do a local capture instead. For example, when debugging problems related to suspending (where the application processor goes to sleep and the SSH connection would be lost).

Run this on your phone to do a local capture:

$ sudo tcpdump -i usbmon2 -s0 -w capture.pcap

Analyzing

To analyze the captured packages, view them in Wireshark.

Using WiresharkQMIDissector

If you have captured traffic of a modem speaking the Qualcomm MSM Interface (QMI) protocol (e.g. the eg25-g in the PinePhone), a dissector based on libqmi can be generated and used as follows:

$ git clone https://github.com/dnlplm/WiresharkQMIDissector
$ git clone https://gitlab.freedesktop.org/mobile-broadband/libqmi.git
$ cd WiresharkQMIDissector
$ python3 generate_lua.py ../libqmi/data/
$ wireshark -X lua_script:qmi_dissector_gen.lua

QMI packets should show up as USB/QMI protocol now, and you can filter for "qmi" (e.g. with the display filter input).

See also