Post

Capturing Remote Wi-Fi Traffic on OpenWRT with Wireshark

Overview

I’ll explain how I transformed my OpenWrt access point into a remote Wi-Fi packet capture device. By leveraging SSH, tcpdump, and a custom channel hopping script, I can stream live Wi-Fi traffic directly into Wireshark on my Windows PC without needing physical access to the router.

I used a Netgear R7450 AC2600 to set this up.

I aimed to capture Wi-Fi packets remotely by putting my OpenWrt device into monitor mode and streaming the data over SSH. The main challenges I encountered were:

  • Device Mode Configuration: Initially, setting up monitor mode correctly on the device was tricky. Using the wrong interface parameters led to errors.
  • Channel Hopping: My device uses two radios—one for 2.4GHz and one for 5GHz. I needed a way to cycle through channels to capture a comprehensive range of traffic.

1. Configuring Monitor Mode

I used the following commands to push my radio cards into monitoring mode:

1
2
iw phy phy0 interface add mon0 type monitor
iw phy phy1 interface add mon1 type monitor

I ensured both wireless interfaces were set to monitor mode. Running the command:

1
OpenWrt:~# iw dev

yielded the following configuration:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
phy#1
        Interface mon1
                ifindex 16
                wdev 0x100000004
                addr c8:9e:43:e2:d0:66
                type monitor
                channel 48 (5240 MHz), width: 20 MHz (no HT), center1: 5240 MHz
                txpower 20.00 dBm
phy#0
        Interface mon0
                ifindex 15
                wdev 0x4
                addr c8:9e:43:e2:d0:65
                type monitor
                channel 7 (2442 MHz), width: 20 MHz (no HT), center1: 2442 MHz
                txpower 20.00 dBm

This confirmed that the interfaces were ready for packet capture.

2. Implementing Channel Hopping

To cover the entire Wi-Fi spectrum, I created a dual-band channel hopping script. This script cycles through the supported channels for both the 2.4GHz (mon0) and 5GHz (mon1) interfaces.

Here’s the final version of the script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/bin/sh
IFACE_24="mon0"
IFACE_5="mon1"
CHANNELS_24="1 2 3 4 5 6 7 8 9 10"
CHANNELS_5="36 40 44 48"
DWELLTIME_24=1
DWELLTIME_5=1
command -v iw >/dev/null 2>&1 || { echo "Error: iw not found. Please install it."; exit 1; }
command -v sleep >/dev/null 2>&1 || { echo "Error: sleep not found. Please install it."; exit 1; }
if [ "$(id -u)" -ne 0 ]; then
    echo "Error: This script must be run as root." >&2
    exit 1
fi
echo "Starting channel hopping..."
echo "  $IFACE_24 (2.4GHz) channels: $CHANNELS_24"
echo "  $IFACE_5  (5GHz) channels: $CHANNELS_5"
echo "Dwell times: ${DWELLTIME_24}s (2.4GHz), ${DWELLTIME_5}s (5GHz)"
channel_hop() {
    INTERFACE="$1"
    CHANNELS="$2"
    DWELL="$3"
    while true; do
        for CH in $CHANNELS; do
            echo "Setting $INTERFACE to channel $CH"
            iw dev "$INTERFACE" set channel "$CH" 2>/dev/null
            if [ $? -ne 0 ]; then
                echo "Warning: Failed to set $INTERFACE to channel $CH"
            fi
            sleep "$DWELL"
        done
    done
}
channel_hop "$IFACE_24" "$CHANNELS_24" "$DWELLTIME_24" &
PID_24=$!
channel_hop "$IFACE_5" "$CHANNELS_5" "$DWELLTIME_5" &
PID_5=$!
echo "Channel hopping started:"
echo "  $IFACE_24 (2.4GHz) - PID $PID_24"
echo "  $IFACE_5  (5GHz)  - PID $PID_5"
echo "Press Ctrl+C to stop."
wait

This script, adjusted for my device’s regulatory domain, excludes unsupported channels and those requiring DFS, which did take me a while to figure out.

Channel Hopping in Action

3. Running the Capture

With the channel hopper active, capturing the Wi-Fi traffic was straightforward. To capture 5 GHz, I used interface mon1.
Wireshark SSH

Once started, Wireshark begins displaying the live packet capture streamed from the router over SSH.

Wireshark Capture

This post is licensed under Apache License 2.0 by the author.