Packet Sniffing with Pyspinel

View source on GitHub

This guide covers how to configure Wireshark and run Pyspinel to sniff packets from a Thread network.

To use the Wireshark extcap plugin for packet sniffing, refer to Packet Sniffing using extcap.

Set up the sniffer environment

Before you begin, complete the following steps:

Build the sniffer

Build and flash an NCP device to serve as the sniffer, using the ot-rcp binary output.

Nordic nRF52840

To set up the Nordic nRF52840 example for use as a sniffer, clone openthread/ot-nrf528xx and set up the build environment:

git clone https://github.com/openthread/ot-nrf528xx --recursive
./script/bootstrap

Set baud rate as 460800. Find the line #define UART_BAUDRATE NRF_UARTE_BAUDRATE_115200 in src/nrf52840/transport-config.h, and replace it with #define UART_BAUDRATE NRF_UARTE_BAUDRATE_460800.

Build the binary:

./script/build nrf52840 UART_trans

Convert the ot-rcp binary output to hex:

arm-none-eabi-objcopy -O ihex build/bin/ot-rcp ot-rcp.hex

Flash the ot-rcp.hex file to the nRF52840 board as detailed in Flash the nRF52840.

Disable Mass Storage Device (MSD) on the nRF52840 to avoid issues with data corruption or drops when using the debug port:

expect <<EOF
spawn JLinkExe
expect "J-Link>"
send "msddisable\n"
expect "Probe configured successfully."
exit
EOF
spawn JLinkExe
SEGGER J-Link Commander V6.42b (Compiled Feb  5 2019 17:35:31)
DLL version V6.42b, compiled Feb  5 2019 17:35:20
 
Connecting to J-Link via USB...O.K.
Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled Jan  7 2019 14:07:15
Hardware version: V1.00
S/N: 683411111
VTref=3.300V
 
Type "connect" to establish a target connection, '?' for help
J-Link>msddisable
Probe configured successfully.

Thread network properties

Before continuing, get the following properties for the Thread network you wish to sniff. You'll need them for Wireshark configuration and running the Pyspinel sniffer.

Mesh Local Prefix

To get the Mesh Local Prefix from a device in the target Thread network:

  1. Using the OpenThread CLI:

    dataset active
    Mesh Local Prefix: fd33:3333:3344:0/64
    

  2. Using wpanctl with an NCP:

    wpanctl getprop IPv6:MeshLocalPrefix
    IPv6:MeshLocalPrefix = "fd33:3333:3344:0::/64"
    

  3. Using the OTBR Web GUI, select Status. The Mesh Local Prefix is listed as IPv6:MeshLocalPrefix similar to wpanctl.

Channel

To get the Channel from a device in the target Thread network:

  1. Using the OpenThread CLI:

    channel
    15
    

  2. Using wpanctl with an NCP:

    wpanctl getprop NCP:Channel
    NCP:Channel = 15
    

  3. Using the OTBR Web GUI, select Status. The Channel is listed as NCP:Channel similar to wpanctl.

Network Key

The Thread Network Key is used by Wireshark to decrypt packets after capture. To get the Network Key from a device in the target Thread network:

  1. Using the OpenThread CLI:

    networkkey
    33334444333344443333444433334444
    

  2. Using wpanctl with an NCP:

    wpanctl getprop Network:Key
    Network:Key = [33334444333344443333444433334444]
    

The Thread Network Key is not available in the OTBR Web GUI.

Sniffer options

Options
-u or --uart
Default value
None - must be provided if you are using a device with a serial connection and not a socket connection.
Description
The -u or --uart flag followed by a device path such as /dev/ttyUSB0.
-c or --channel
Default value
11
Description
The -c or --channel flag followed by the channel configured on your Thread Network, upon which to sniff packets.
--no-reset
Default value
This flag overrides the default behavior.
Description
The --no-reset flag is needed if your NCP device is connected to the host with the native USB connection.
--crc
Default value
This flag overrides the default behavior.
Description
The --crc flag is needed for platforms such as TI and Nordic Semiconductor Thread boards. The flag recalculates the CRC to avoid a ‘Bad FCS' (frame check sequence) warning in Wireshark.
-b or --baudrate
Default value
115200
Description
The -b or --baudrate flag is used to override the default baud rate. Set this value to the same baud rate used with your NCP build (we recommend 460800).
--rssi
Default value
This flag overrides the default behavior.
Description
The --rssi flag is used to ensure the RSSI is included in the pcap output. You must use this flag if the TI CC24xx FCS format option is enabled in Wireshark.
--tap
Default value
This flag overrides the default behavior.
Description
The --tap flag specifies DLT_IEEE802_15_4_TAP(283) for the frame format, with a pseudo-header containing TLVs with metadata (such as FCS, RSSI, LQI, Channel). If not specified, DLT_IEEE802_15_4_WITHFCS(195) would be used by default with the additional RSSI and LQI following the PHY frame directly, as in TI CC24xx FCS format. You must use this flag if the ITU-T CRC-16 option is enabled in Wireshark. If that option is not enabled in Wireshark, do not use this flag.

Run the sniffer

Make sure to use the specific device path for your NCP and the channel for the Thread network you are attempting to sniff.

If following this guide, the nRF52840 DK should be attached to the host machine by the debug port, as described in Flash the nRF52840. To run the Pyspinel sniffer, use the -b flag to specify the baud rate (if it was changed from the default) and omit the --no-reset flag.

If you Configure Wireshark to display RSSI, you must also include the --rssi flag when you run the sniffer tool. For example, to sniff on Channel 15 using a device mounted at /dev/ttyACM0 with RSSI included in the Wireshark output:

cd path-to-pyspinel
python sniffer.py -c 15 -u /dev/ttyACM0 --crc --rssi -b 460800 | wireshark -k -i -

You should now be able to view the packets and related protocols for this configuration in Wireshark:

Wireshark Capture

Refer to the Spinel sniffer reference for more information on running the Pyspinel sniffer.

Native USB connection

Using the nRF52840 DK USB port requires the OpenThread ot-rcp binary to be built with USB_trans:

./script/build nrf52840 USB_trans
Flash the nRF52840 DK, connect it to the host machine by the USB port, then use the --no-reset flag but omit the -b flag when running the sniffer:

python sniffer.py -c 15 -u /dev/ttyACM0 --crc --no-reset --rssi | wireshark -k -i -

Resources

For additional Nordic tools, refer to Nordic Semiconductor — Thread Sniffer based on nRF52840 with Wireshark.