Monitor login attempts on your home WiFi

Private Reception

Article from Issue 186/2016
Author(s):

Push notifications to your cell keep you up to date with the details of any clients that log in or out of your home WiFi.

Whenever the lights on my router start to flash like crazy when I'm not actually doing anything on the network, I always suspect that one of my neighbors might have cracked my WPA2 password and is making mischief on my Internet account. I live in a large city on the second floor of a house half way up a steep hill. My guess is that a couple of hundred people can receive my WiFi router's signal – and that potentially includes a couple of good for nothings who would love to mess around with it.

The scripts I look at this month regularly pick up a list of wireless devices logged in to my WiFi router and text my cell phone when a new client logs onto or off of my home WiFi network.

Instead of programming a new cell app for this, Prowl for the iPhone or Notify my Android for Android devices has a web interface that lets scripts send messages. The Prowl servers then ensure that the events are forwarded to all the endpoints, with the Prowl app running under the same user account. This will even work with a locked phone; in this case, the messages just briefly flash up on the lock screen (Figures 1 and 2).

Figure 1: One glance at the cell phone reveals who has just logged on to the home WiFi network.
Figure 2: The router pushes active DHCP data to a hosting service, where a cron job notifies the Prowl server of events via its web API. Prowl then sends a push notification to phones with the Prowl app installed.

Unusable Toolchain

How did I get the Asus RT-66U router, on which I immediately installed the free DD-WRT software after my purchase, to monitor active WiFi users and call the web service on the Prowl server in case of changes? The process that handles the dynamic DHCP IP addresses on the router goes by the name of dnsmasq; it stores the DHCP leases currently in use in the /tmp/dnsmasq.leases file. The column format used here (Listing 1) lists the expiration time in seconds for each lease, the MAC address of the device, the IP address assigned to it, and a name the device uses to describe itself [1].

Listing 1

dnsmasq.leases

1 86400 74:da:42:1b:44:a7 192.168.20.148 raspberrypi *
2 86400 e8:80:2e:e9:11:a9 192.168.20.130 MikesiPhone e8:80:2e:e9:11:a9
3 86400 10:68:3a:17:4a:ba 192.168.20.131 android-oba143110ae5ee34 10:68:3a:17:4a:ba
4 86400 00:51:b6:76:a1:b6 192.168.20.134 Mikes-Macbook 00:51:b6:76:a1:b6

On a Linux distribution, it would be relatively simple to use an infinite loop to detect incoming or outgoing clients and send an HTTP request to the Prowl API in the case of changes. However, the DD-WRT distro on the router has a very limited selection of Unix tools, and solving the normally trivial problem of searching through the lease file with Perl and firing off HTTP requests, if needed, becomes a genuine brain teaser.

Although I could install Perl on the router, along with a couple of CPAN modules, the more the configuration were to deviate from a plain vanilla DD-WRT distribution, the more error prone the upgrade results would be. A simple shell script that uses the BusyBox tools on the router will hopefully still run in a couple of years without manual changes, and it's fairly easy to install via the DD-WRT GUI. The GUI stores the script in the router's NVRAM, pushes it into the filesystem on reboot, and has it fire up its infinite loop.

Tongues of Angels

The shell script in Listing 2 thus makes do with ssh to upload the file with the issued IP addresses to an account on my hosting provider's server, where a cron job regularly checks them for changes and contacts the Prowl server using Perl and an API key obtained from Prowl's website.

Listing 2

lease-push.sh

01 #!/bin/sh
02 file=/tmp/dnsmasq.leases
03 var=lease-file
04
05 HOME=/tmp/root
06
07 cd /tmp
08 uudecode <<'EOT'
09 begin 664 keyfile
10 M5V%S(&EC:"!N:6-H="!W96G#GRP@;6%C:'0@;6EC:"!N:6-H="!H96G#GRX@
11 [...]
12 51\.V=&4N($]D97(@4V-H:6QL97(N
13 `
14 end
15 EOT
16
17 cd /tmp/root/.ssh
18 uudecode <<'EOT'
19 begin 664 known_hosts
20 M3&ER=6T@3&%R=6T@3,.V9F9E;'-T:65L+B!797(@;FEC:'1S(&AA="P@9&5R
21 [...]
22 >(&AA="!N:6-H="!V:65L+B!$;VYA;&0@5')U;7`N
23 `
24 end
25 EOT
26
27 cd /tmp
28 while [ "forever" ]
29 do
30     sum=`/usr/bin/sha1sum $file | cut -d " " -f1`
31     stored="$(/usr/sbin/nvram get $var)"
32
33     if [ "$stored" != "$sum" ]
34     then
35      /usr/bin/scp -i keyfile $file perlsnapshot@<somehoster.com>:
36      /usr/sbin/nvram set $var=$sum
37     fi
38
39     sleep 30
40 done

Even this task isn't totally simple; after all, the scp client on the BusyBox-based distribution is not fully functional. It takes the tongues of angels to get it to authenticate against the hosting provider's server using a private key and to send the file to the server.

After installing a private key generated using ssh-genkey for the SSH process on the DD-WRT distribution, the started process just disappears after reporting that some internal string somewhere in the depths of its implementation is too long. Thanks a lot, BusyBox! If you google this message, you will discover that the pared down SSH version uses a special format for private keys. Instead, a tool named dropbearkey on the DD-WRT router generates a compatible key. For this, log into the router via ssh as root after enabling the SSH daemon in the GUI below Services. The call

dropbearkey -t rsa -f keyfile

generates the private key in the keyfile file.

The dropbearkey tool displays the matching public key on its standard output. If you copy this text string into the .ssh/authorized_keys file on the server, and open the connection on the router by typing

ssh -i keyfile <servername>

at the command line, you do not need to enter a password and can thus automate the process.

Hard Wiring

Unfortunately, the filesystem on the router does not survive a reboot because it resides in volatile memory, and all the information is rebuilt from NVRAM after the reboot. This is why programmers embed all required information in the scripts that need to run on the router. Listing 2 relies on the slightly ancient uudecode to handle the binary data from the special private key file; its unreadable mess of data, with a width of precisely 61 characters, fits perfectly into a source code listing. The following call created the data:

cat keyfile | uuencode -f keyfile

I manually copied the output into Listing 2. The same procedure as for the private key applies to the known_hosts file, which lists the SSH host keys for known hosts. The first call to ssh to open the connection to a new server interactively prompts you on the terminal to decide whether the server seems to be trustworthy. If you say y, SSH stores the host key in ~/.ssh/known_hosts file. The uuencode data in lines 20-22 were created by running uuencode against the known_hosts file and cutting and pasting its output into Listing 2.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More

News