Sniffing for WiFi SSIDs with the Raspberry Pi 3

As you all probably know, the Raspberry Pi turned 4 on February 29th, and this was celebrated with the release of the Raspberry Pi 3.  What’s new?  Well the big things are:

  • Built in wireless access (no more using 25% of your available USB ports for WiFi).
  • Built in Bluetooth
  • 64 Bit Cortex A-53 processor
  • 1GB of memory
  • Still just $35  (not really new)

I decided I would try to play with one of the new features and make a simple WiFi detector.  I am a big fan of the Best American Non-Required Reading series, which used to have a front section that included some of the most creative WiFi names around.  I was certain that there would be some fun names in my neighborhood, so I thought I would use my Pi3 as an SSID ‘sniffer’.

Since the WiFi is built in to the Pi3, I can strip this project down to just the Pi and a 5V cell phone charger.

WiFi_5

There are quite a few examples of these out there, and they vary in complexity.  The one I worked on uses the built in WiFi to scan all available networks every 10 seconds and record them in a .csv file.  My thought was that I would put this in my backpack and walk around the neighborhood.

The first thing to do is try this command:

sudo iwlist wlan0 scan

You should see a long list of things come back.  The command asked the Pi to scan the wireless signals and report back on everything it finds.  I am most interested in the SSIDs (shown below as ESSID:”coyote”).

WiFi_2

Once that works, I found and modified a python program that will output all of the SSIDs.

I created a folder called ‘wifi’ and a file called ‘test.py’.

mkdir wifi
nano test.py

The code below gets copied into test.py.

from subprocess import check_output

scanoutput = check_output([“iwlist”, “wlan0”, “scan”])

for line in scanoutput.split():

    if line.startswith(“ESSID”):
      line=line[7:-1]
      print line

The program is really simple.  First it imports the subprocess library.  Then it uses the check_output command and stores the results in a variable called scanoutput.  There are lots of lines in scanoutput, so we split them out individually and look for ones that startswith “ESSID”.  We strip those lines to get rid of the first 7 characters (ESSID:”) and the last character (“), and then print it.

If you see a short list of networks, then its working.

WiFi_3

That is the simple version of the program.  What I would like to do know is have that run as a loop every ten seconds and spit the values out into a .csv file.  This complicates the program a little bit, but the main parts are still there, and we can figure everything else out.

from subprocess import check_output
import csv
import time

#get the current time to name a file later on
timestamp = time.strftime("%m-%d-%Y-%I:%M:%S")

#define a function for doing a wifi scan
def wifiscan():
  ssid = []
  scanoutput = check_output(["iwlist", "wlan0", "scan"])
  curtime = time.strftime("%I:%M:%S")
  ssid.append(curtime)

  for line in scanoutput.split():
    line=str(line)
      if line.startswith("ESSID"):
      line=line[7:-1]
      ssid.append(line)
  with open('/home/pi/wifi/'+timestamp+'.csv','a') as csvfile:
      csvwriter = csv.writer(csvfile,delimiter=',')
      csvwriter.writerow(ssid)
  print ssid

while True: #repeat the program in an infinite loop
  ssid=[] #clear the list
  wifiscan()
  time.sleep(10)

This program works just like the previous one but it has some enhancements.  My python skills are still pretty weak, and I was having a tough time getting all of the networks to show up instead of just the first one, so I started saving everything in a list called ssid.  It starts empty, and then gets populated with the current time (curtime) and SSIDs.  The program then uses csvwriter to open a file that is named with another date stamp that is captured just once when the program starts.  When the SSIDs are captured, it becomes a row in the CSV file, and the first cell in each row is the date stamp.  The infinite loop runs the wifiscan, clears ssid, waits for 10 seconds, and starts over again.

How does it look?

WiFi_4

It works pretty well.  I am really only interested in the names, and the number of names for each scan.  The iwlist command gives a lot more information like signal strength, frequency, and MAC Address.  I live in a pretty densely populated place, so I am curious about how many of these things I can detect as I walk to the coffee shop, or drive to work.

I can visualize it like this by doing a little work in Excel.

WiFi_5

 

An obvious next step would be to GeoCode this information through the use of a GPS HAT.  As I go through various neighborhoods it would be interesting to see how connectivity changes.

Enjoy!