Packet sniffing with Pyspinel

Overview

The Pyspinel sniffer tool connects to a Thread NCP device and converts it into a promiscuous packet sniffer, generating a pcap (packet capture) stream to be saved or piped directly into Wireshark.

Wireshark is an open-source tool that can decode network protocols in the Thread stack, such as IEEE 802.15.4, 6LoWPAN, IPv6, MLE (Mesh Link Establishment), UDP, and CoAP.

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

Requirements

Hardware

  • macOS or Ubuntu machine to serve as an NCP host processor, and to run Pyspinel and Wireshark
  • 1 OpenThread device flashed with the NCP radio build

Software:

Installation

Set up the sniffer environment

Clone and install Pyspinel and dependencies:

git clone https://github.com/openthread/pyspinel
cd pyspinel
pip install --user future pyserial ipaddress

Alternatively, set up the environment by installing the pyspinel package. Note that this package uses the Pyspinel v1.0.0a3 release and not the latest Pyspinel master.

pip install --user pyspinel

Install Wireshark

Ubuntu Linux

Open a terminal and run the following commands to download and install Wireshark:

sudo add-apt-repository ppa:wireshark-dev/stable
sudo apt-get update
sudo apt-get install wireshark

We recommend running Wireshark as a non-root user. To do so, reconfigure the package:

sudo dpkg-reconfigure wireshark-common

When you get the dialog asking "Should non-superusers be able to capture packets?", select Yes, then add the wireshark user and update file permissions:

sudo adduser $USER wireshark
sudo chmod +x /usr/bin/dumpcap

macOS

Download and install Wireshark for macOS.

Build the sniffer

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

For example, to set up the Nordic nRF52840 example for use as a sniffer:

  1. Build the OpenThread nRF52840 example:
    git clone https://github.com/openthread/openthread
    cd openthread
    ./bootstrap
    make -f examples/Makefile-nrf52840
    
  2. Convert the ot-ncp-radio binary output to hex:
    arm-none-eabi-objcopy -O ihex output/nrf52840/bin/ot-ncp-radio ot-ncp-radio.hex
    
  3. Flash the ot-ncp-radio.hex file to the nRF52840 board as detailed in Flash the nRF52840.
  4. 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.
    

Baud rate

For optimal sniffer capability on the Nordic nRF52840, we recommend updating the UART baud rate from 152000 (default) to 460800 prior to building. Search for the UART_BAUDRATE define in /examples/platforms/nrf52840/platform-config.h and update it to 460800:

#ifndef UART_BAUDRATE
#define UART_BAUDRATE NRF_UART_BAUDRATE_460800
#endif

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.

Master Key

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

  1. Using the OpenThread CLI:
    masterkey
    33334444333344443333444433334444
    
  2. Using wpanctl with an NCP:
    wpanctl getprop Network:Key
    Network:Key = [33334444333344443333444433334444]
    

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

Wireshark configuration - protocols

Wireshark must be configured to properly show Thread packets.

Select Preferences... in Wireshark and expand the Protocols section.

6LoWPAN

Select 6LoWPAN from the list of protocols and verify or change the following settings:

  1. Uncheck Derive ID according to RFC 4944.
  2. Update Context 0 with the Mesh Local Prefix for the target Thread network.

OT Sniffer Wireshark 6LoWPAN

Wireshark uses context configurations to parse the compressed IPv6 address and display the IPv6 source and destination addresses correctly.

To show the addresses for other on-mesh prefixes configured on the gateway, update other Context IDs with those prefixes.

To get the Context ID for a specific on-mesh prefix, view the Thread Network Data TLV in any MLE Data response message. For example:

Context 1: fd00:7d03:7d03:7d03::/64

CoAP

Select CoAP from the list of protocols and set CoAP UDP Port to 61631. This ensures TMF messages (like address solicit) are displayed.

IEEE 802.15.4

Select IEEE 802.15.4 from the list of protocols and verify or change the following settings:

  1. Set 802.15.4 Ethertype (in hex) to "0x809a".
  2. Set the Security Suite to "AES-128 Encryption, 32-bit Integrity Protection".
  3. Click the Edit... button next to Decryption Keys, which is where you add the Thread network Master Key for packet decryption.
    1. Click + to add a Decryption key.
    2. Enter the Thread network Master Key into the Decryption key column.
    3. Enter "1" as the Decryption key index.
    4. Select Thread hash from the Key hash column listbox. OT Sniffer Wireshark IEEE 802.15.4
    5. Click OK to save the decryption key.

Thread

Select Thread from the list of protocols and verify or change the following settings:

  1. Enter "00000000" for the Thread sequence counter.
  2. Uncheck Use PAN ID as first two octets of master key.
  3. Check Automatically acquire Thread sequence counter.

Click the OK button to save any protocol changes.

Some Thread traffic might be analyzed as the ZigBee protocol. To correctly display these two protocols, edit the enabled protocols in Wireshark:

  1. In Wireshark, go to Analyze > Enabled Protocols.
  2. Uncheck the following protocols:
    1. LwMesh
    2. ZigBee
    3. ZigBee Green Power

Wireshark configuration - RSSI

To display RSSI in Wireshark:

  1. Go to Preferences > Protocols > IEEE 802.15.4.
  2. Set the FCS Format to TI CC24xx metadata.
  3. Click OK to save and return to the Preferences menu.
  4. From Preferences, select Appearance > Columns.
  5. Add a new entry:
    • Title: RSSI
    • Type: Custom
    • Fields: wpan.rssi

OT Sniffer Wireshark RSSI

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. 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 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.

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 see the packets and related protocols for this configuration in Wireshark:

Wireshark Capture

See 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-ncp-radio binary to be built with the USB=1 flag:

make -f examples/Makefile-nrf52840 USB=1

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 -

Troubleshooting

If you run into Import errors when attempting to run the sniffer, it might be a compatibility issue with Python 2.7. Make sure the future package is installed and try again:

pip install --user future

Resources

For more information on how to use Pyspinel and Wireshark, see the following: