WiFinder Is A Python Driven Roommate Warning System

WiFinder

We’ve all been there. Your roommate is finally out of the house and you have some time alone. Wait a minute… your roommate never said when they would be back. It would be nice to be warned ahead of time. What should you do? [Mattia] racked his brain for a solution to this problem when he realized it was so simple. His roommates have been warning him all along. He just wasn’t listening.

Most Hackaday readers probably have a WiFi network in their homes. Most people nowadays have mobile phones that are configured to automatically connect to these networks when they are in range. This is usually smart because it can save you money by not using your expensive 4G data plan. [Mattia] realized that he can just watch the wireless network to see when his roommates’ phones suddenly appear. If their devices appear on the network, it’s likely that they have just arrived and are on their way to the front door.

Enter wifinder. Wifinder is a simple Python script that Mattia wrote to constantly scan the network and alert him to new devices. Once his roommates are gone, Mattia can start the script. It will then run NMap to get a list of all devices on the network. It periodically runs NMap after this, comparing the new host list to the old one. If any new devices show up, it alerts with an audible beep and a rather hilarious output string. This type of scanning is nothing new to those in the network security field, but the use case is rather novel.

30 thoughts on “WiFinder Is A Python Driven Roommate Warning System

    1. Or if the phone doesn’t reliably autoconnect, or if the phone is left in airplane mode, etc. There are myriad ways for this system to fail, but many of them are corner cases. Working well enough for the common case is a classic hallmark of a hack.

  1. Continuously polling with an ARP scan seems a little… brutal.

    Why not put the card in monitor mode (or leave it in monitor mode — my laptop starts a monitor-mode interface at boot, and leaves it up all the time) and look for authentication/association packets? Assuming one doesn’t know the MAC address of interest, and just wants to notice any new device, as the python script does, something like this should do:
    tcpdump -i mon0 -elnq "(type mgt subtype assoc-req or type mgt subtype assoc-resp or type mgt subtype auth) and wlan host `iwconfig |sed -n 's/.*\(\([0-9A-Z]\{2\}:\)\{5\}[0-9A-Z]\{2\}\).*/\1/p'`"
    (If you know your AP’s BSSID, you can just drop that in instead of the backquoted “iwconfig |sed …” bit.)

    If you want it to beep…
    tcpdump -i mon0 -elnq "(type mgt subtype assoc-req or type mgt subtype assoc-resp or type mgt subtype auth) and wlan host `iwconfig |sed -n 's/.*\(\([0-9A-Z]\{2\}:\)\{5\}[0-9A-Z]\{2\}\).*/\1/p'`" |sed s/^/\a/
    I leave adding a “rather hilarious output string” as an exercise for the reader…

    But unless your roommate is running a MAC randomizer on his phone, there’s no reason you wouldn’t know his MAC; once you do, you can do a simple:
    tcpdump -i mon0 -elnq "type mgt and wlan host 00:11:22:33:44:55" |sed s/^/\a/
    (replacing 00:...:55 with his phone's WLAN MAC, of course...)
    Either way, it doesn't take 49 lines of code or constant polling.

    1. That’s quite good! You’re lucky your laptop card has a monitor mode, I basically had to install an alfa USB dongle.

      I don’t spose you would do a breakdown of that?

      1. OK, starting from the inside out, `iwconfig |sed -n 's/.*\(\([0-9A-Z]\{2\}:\)\{5\}[0-9A-Z]\{2\}\).*/\1/p'` finds the BSSID of any networks you’re connected to. Actually, it finds anything that looks like a MAC (the BSSID is just the MAC of the AP):
        [0-9A-Z] matches a single hex digit
        [0-9A-Z]\{2\}: matches a sequence of 2 hex digits, then a literal ‘:’
        \([0-9A-Z]\{2\}:\)\{5\}matches a sequence of 5 of the above (i.e. 10 hex digits, with interspersed ‘:’ and one ‘:’ at the end
        \(\([0-9A-Z]\{2\}:\)\{5\}[0-9A-Z]\{2\}\)matches that sequence plus an extra 2 hex digits at the end (i.e. 12 hex digits, with interspersed ‘:’ — a MAC/BSSID)

        then sed -n 's/.*\(~~~~~\).*/\1/p' just finds any line containing ~~~~~ and replaces the whole line with the ~~~~~ part (in our case, the BSSID), and prints the result. The -n option stops sed’s default behavior of printing every line automatically, so it _only_ prints the BSSID.
        Note that if you have multiple wireless cards connected at the same time, you’ll get multiple lines of output, which will cause problems. Simplest fix, if you know which interface is connected to the WLAN of interest, is to replace “iwconfig” with “iwconfig wlan0” (where wlan0 is that interface)

        Once that’s done, the backquotes tell the shell to substitute the output (i.e. the BSSID) into the command, leaving us with something like:
        tcpdump -i mon0 -elnq "(type mgt subtype assoc-req or type mgt subtype assoc-resp or type mgt subtype auth) and wlan host 01:23:45:67:89:AB" |sed 's/^/\a/'
        Taking that piece-by-piece:
        tcpdump — generic packet-sniffing program — despite the name, it’s not limited to TCP or IP, but can also handle other protocols including (as we need) ethernet or wifi link-level packets.
        -i mon0 — the network interface to read packets from. If your monitor-mode interface is different, replace “mon0” with whatever.
        -elnq — some miscellaneous options I normally use for this sort of thing, I’m not sure all of them apply in this case:
        -e prints link-level header (including MAC addresses) on each output line. (Good if you don’t yet know your roommate’s MAC, but not needed)
        -l makes the output line-buffered, ensuring that the next process (sed in our case) receives each line immediately, rather than waiting until a whole buffer-full is ready at once. (This is the only real important one)
        -n tells tcpdump to output addresses numerically, rather than attempting to look up the corresponding hostnames.
        -q reduces verbosity, making the output lines shorter

        "(type mgt subtype assoc-req or type mgt subtype assoc-resp or type mgt subtype auth) and wlan host 01:23:45:67:89:AB" — a filter expression determining which packets to dump. In these expressions, individual filters are connected by “and”, “or”, and parentheses exactly as you’d expect.
        (type mgt subtype assoc-req or type mgt subtype assoc-resp or type mgt subtype auth) — “type foo subtype bar” is a single filter which passees only packets of the specified subtype, so this passes packets of mgt/assoc-reg, mgt/assoc-resp, or mgt/auth — all types of packets you expect to see when a client associates.
        wlan host 01:23:45:67:89:AB — “host foo” passes only packets with foo as either the source or destination. The “wlan” modifier specifies that we’re looking for a link-level host, as opposed to, say an IP host. By specifying that the packets must be to or from our AP, we ignore any clients associating to the neighbors’ networks.

        tcpdump will then output one line for each packet matching those filters; each line might look like:
        00:15:14.718522 343829725486us tsft 1.0 Mb/s 2442 MHz 11b -65dB signal antenna 1 BSSID:00:24:xx:xx:xx:xx DA:00:24:xx:xx:xx:xx SA:00:19:xx:xx:xx:xx Assoc Request (xxxx_essid_here_xxxx) [1.0 2.0 5.5 11.0 Mbit]
        You’ll get several such lines each time a client associates, which is good — you’re not guaranteed to receive every packet, but there’s enough to make up for it.

        (The packet filter in the other example, for the case where you know the MAC address, is similar, but watching for packets to/from the client’s address. Additionally, we can use a simpler filter on packet type; if you show all mgt/* packets from an AP, you’ll see a lot of beacons when nobody’s associating, so we must select specific subtypes of interest. But clients don’t send beacons, so pretty much any “type mgt” is interesting. You could actually leave the type filter out altogether, but then once he associates, you’ll probably see a bunch of data packets as well, which may give you more beeps than you care for.)

        Finally, we pipe that through sed 's/^/\a/' — “^” matches the beginning of a line, and “\a” is the escape sequence for the “alert” or “bell” character, aka control-G, aka ASCII 07. So this just inserts the bell character at the beginning of each line; your terminal will ordinarily respond to this by beeping.

        1. Thanks for the breakdown! In case anyone’s interested, I’ve adapted it to work on OS X. (You may need to change en0 to en1 or en2, depending on how many network interfaces you’ve got.)

          #!/bin/zsh
          bssid=`/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -I en0 |sed -n ‘s/.*\(\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}\).*/\1/p’`
          tcpdump -I -i en0 -elq “(type mgt subtype assoc-req or type mgt subtype assoc-resp or type mgt subtype auth) and wlan host $bssid” | sed s/^//

          The bell character \\a wouldn’t work for me, so I used ^G. This won’t show up here since it’s a control character, but copying it into a suitable text editor (such as Textmate) should work, unless the commenting system filters it out.

          1. Turns out the ^G character is left intact, but the commenting system replaced the double and single quotes with stylised ones. Fix those after copying and the script should work.

    1. Now in english :) I did not expect any interest for this, its a raw piece of code that i wrote to exercise while learning Python. I’ll have to fix a lot of stuff.

        1. Which logic ?
          That’s BS.
          If your brain isn’t flexible enough to cope with another language, whether human or artificial, well, then poor you.
          Arrivederci !

  2. I wrote a script, thats using beacon frames. This way its possible not only to detect the roomates, but also the neighbours… ;)
    Using it, to know if the cute girl next door is back home, so i can knock the door incidentally :)

  3. I suppose that would work fine provided that the roommate is question never wonders, “Why the hell am I running the WiFi if I’m using Mobile Data?”

    The solution breaks down if the roommate decides it makes more sense not to eat up the battery by running that extra radio.

    1. mobile data hammers the battery compared to wifi, my battery lasts a lot longer if i have wifi enabled than if i dont as most of the loacations where i need internet access have wifi.

Leave a Reply to wisdomseekerCancel reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.