Capturing Wireless LAN Packets in Monitor Mode with iw

I previously showed two ways to capture wireless LAN packets in Ubuntu Linux: using the command line tool iwconfig and using Kismet. Both involve putting the wireless LAN card into "monitor mode", allowing you to view and record all packets sent by other WiFi devices nearby. This includes data packets send between other devices, something which is not possible unless your device is in monitor mode.

Here I present a third option: again using the command line in Ubuntu Linux but with the command iw. The command iw is meant to replace iwconfig. I still like and use the old interface of iwconfig, but iw seems to be much more powerful for viewing/configuring wireless information.

Getting Started with iw

First be aware that iw distinguishes between wireless LAN hardware devices (the physical layer, referred to as phy) and the network interface configured to use that hardware (e.g. wlan0, similar to an Ethernet eth0 interface). To see the list of devices, and interfaces for each device:

$ iw dev
phy#0
	Interface wlan0
		ifindex 3
		type managed

In my case (and most likely for most typical computers) the hardware is phy0 and my network interface is wlan0. You can see detailed information about the hardware using:

$ iw phy phy0 info
Wiphy phy0
	Band 1:
		Capabilities: 0x172
			HT20/HT40
...
	Supported interface modes:
		 * IBSS
		 * managed
		 * AP
		 * AP/VLAN
		 * WDS
		 * monitor
		 * mesh point
	software interface modes (can always be added):
		 * AP/VLAN
		 * monitor
...

Of importance for the next step is the supported/software interface modes should include entry for "monitor", meaning your hardware supports monitor mode. If there is no "monitor" entry, then you will not be able to capture other peoples data using the next steps.

Capturing in Monitor Mode

If your hardware device supports monitor mode then you must add a monitor interface called mon0.

$ sudo iw phy phy0 interface add mon0 type monitor

You can check that it is added:

$ iw dev
phy#0
	Interface mon0
		ifindex 4
		type monitor
	Interface wlan0
		ifindex 3
		type managed

We will capture with the mon0 interface, so you can delete the normal wlan0 interface:

$ sudo iw dev wlan0 del

Now enable the mon0 interface using ifconfig:

$ sudo ifconfig mon0 up

Before capturing, specify the wireless LAN frequency you want to capture on. You should choose the frequency based on the channels used by neighbouring access points. The frequency is given in MHz, e.g.\ channel 6 is 2437.

2.4 GHz Wi-Fi channels (802.11b,g WLAN), Michael Gauthier / Wikimedia Commons / CC-BY-SA-3.0 /
$ sudo iw dev mon0 set freq 2437

To check that your interface is in monitor mode and using the correct frequency you can use iwconfig:

$ iwconfig mon0
mon0      IEEE 802.11bgn  Mode:Monitor  Frequency:2.437 GHz  Tx-Power=20 dBm   
          Retry  long limit:7   RTS thr:off   Fragment thr:off
          Power Management:on      

Now you can capture, e.g. using tcpdump:

$ sudo tcpdump -i mon0 -n -w wireless.cap

Ctrl-C to stop the capture, then view with Wireshark. To display select wireless LAN frames in Wireshark use the wlan and wlan_mgt filters. (My brief summary of Wireshark and WLAN filters)

Returning to Managed Mode

If after monitoring you want to revert the changes and continue using the wlan0 interface in managed mode (e.g. connect to an AP), then delete the mon0 interface and add the wlan0 interface:

$ sudo iw dev mon0 del
$ sudo iw phy phy0 interface add wlan0 type managed
$ iw dev
phy#0
	Interface wlan0
		ifindex 5
		type managed
$ iwconfig wlan0
wlan0     IEEE 802.11bgn  ESSID:off/any  
          Mode:Managed  Access Point: Not-Associated   Tx-Power=20 dBm   
          Retry  long limit:7   RTS thr:off   Fragment thr:off
          Power Management:on

What Can Go Wrong?

If you get errors with some of the above iw commands, then:

  1. Check that the wireless device is not soft/hard blocked by rfkill and unblock it if it is:
    $ rfkill list
    0: phy0: Wireless LAN
    	Soft blocked: yes
    	Hard blocked: no
    $ rfkill unblock 0
    
  2. Make sure you are using the correct interface/device. In my examples I use phy0, wlan0 and mon0. Yours may be different.

If the commands work, but in Wireshark you can only see packets either to your computer or broadcast/multicast (i.e. you cannot see any packets from one computer to another computer, such as HTTP or SSH), then:

  1. Make sure the frequency you selected is being used by others.
  2. Check that your device supports monitor mode (look in the output of iw phy phy0 info). Some wireless cards do not support monitor mode, and even if they do, some drivers do not support it.

Selecting a Wireless Adapter that Supports Monitor Mode

On the last point above, finding a wireless adapter that supports monitor mode to allow capturing of data packets in Linux can be troublesome. It depends on both the hardware and driver support. The Linux wireless drivers page provides a quick summary of monitor mode support in different drivers. To find out which devices use which drivers you can search on WikiDevi. As of March 2015, devices that use Atheros, Intel, RaLink or Broadcom chipsets seem to have good monitor mode support.

When looking to buy a wireless USB (or PCI) adapter that will support monitor mode, find some devices that are available, look them up on WikiDevi to see the drivers, and then check the driver support for monitor mode. Be especially careful with hardware versions: many branded devices are updated over time and although they have the same model number, the internal wireless chipset may change. Some devices I have successfully used include:

I recently ordered a batch of TP-Link TL-WN821N after checking that it supported monitor mode, but when delivered it was hardware version 4 which used a Realtek chipset (rtl8192cu) that did NOT fully support monitor mode (version 1 to 3 used Atheros chips, which did support monitor mode). Be carefully in checking the specific hardware versions when purchasing wireless devices.