A response I typically see on the internet when someone asks about blocking certain websites, tracking behavior, or throttling network access is that they’re in the middle of an XY Problem that has a personal solution rather than a technical one. It could be employees slacking off at work or a family member hogging all the bandwidth, and the solution is usually to work it out in real life rather than passive-aggressively implement a technical ‘solution’.

So what do you do when you’re stuck in an XY problem, you’re powerless to do X and all you can really do is Y — but it’s not a solution, not even a partial solution, but will provide a brief reprieve from the problem that necessitates X?

Holed up one evening I needed a distraction so I decided to give Y a shot, I didn’t exactly have much to lose.

Proxies For Location

How can you figure out where someone is? Not an easy problem even when the person in question is trying to make their location known. Even harder when you’re trying to determine it passively. But is determining where they are what I want? I found myself in another Y problem, I really want to know where they aren’t which turns out to be much easier.

The metric that seemed to fit the bill was network access. It wouldn’t be perfect, their device could be off or disconnected, but it’s the best I could do on short notice. It wouldn’t quite get me what I wanted but it might be good enough. If I could detect that their device was connected to the network I could be reasonably confident in their location but outside of that it was a mystery.

Black Box Monitoring

I have an old appliance router, it meets my needs but it’s not exactly full of features. After playing around with it for a while and getting the authentication to work I wasn’t reasonably confident that I would be able to scrape the data from the page. It was just a soup of server rendered HTML tags, tables within tables within tables, none of which were labeled. I would have to try something else.

One method of discovering devices on a network is to ping the broadcast address.

ping 192.168.1.255

My devices responded but that’s only because they were configured to respond. I got nothing from their device. I searched for a while and found out that most devices, including phones, typically don’t respond for security reasons. No problem I thought, their device would certainly respond to a direct ping and there’s only 256 addresses. I can just scan the whole subnet and find their device.

nmap -sP 192.168.1.1-254

It worked – kinda. I was able to ping their device but it would only work sometimes. It would stop responding when it was inactive. I thought maybe going one layer lower by scanning the ARP cache would produce better results.

arp-scan --interface=eth0 --localnet

No luck again, it would only intermittently appear on the scan. I would have to try something more than scanning.

Using DHCP

The solution that worked well enough was to disable my routers DHCP server and replace it with my own. There I could set the DHCP lease time on their devices to something short, say five minutes, and get periodic updates. I ended up using an old laptop but for this guide I’ll pretend that I used my Raspberry Pi instead.

I had used dnsmasq in the past for a local DNS server and noticed that it had a DHCP server built in that I always had to ignore when configuring it. There might be better Free DHCP servers out there but I’m a sucker for familiarity.

Start with the basics, get it installed and running. I’m more familiar with RPM based distributions, I use RHEL at work, CentOS on my server, and Arch on my personal laptop so the Debian commands are a bit exotic to me. I had used apt-get in the past but apparently I’m supposed to use apt now.

apt install dnsmaq
systemctl enable --now dnsmasq

Configuring it for my purposes was really as simple as reading down through the manual and picking out the options that seemed relevant.

man dnsmasq

This host might as well act as a DNS caching server as well as the DHCP server. To that end I need to set the upstream DNS servers.

# /etc/resolv.conf

nameserver 8.8.8.8
nameserver 8.8.4.4

Then we need to configure dnsmasq itself. Here are the options I changed from the default.

# /etc/dnsmasq.conf

bogus-priv
dhcp-authoritative
dhcp-range=192.168.1.100,192.168.0.254,12h
dhcp-script=/usr/local/bin/dhcp-hook.sh
dhcp-option=option:router,192.168.0.1
dhcp-option=option:ntp-server,192.168.0.1
dhcp-option=option:ip-forward-enable,0
dhcp-host=$MAC1,5m
dhcp-host=$MAC1,5m

The last part is to write the dhcp-hook.sh script which will be called when a new lease is added or removed.

#! /usr/bin/env bash

if [[ $2 = "$MAC1" || $2 = "$MAC2"]]; then
  if [[ $1 = "add" ]]; then
    sendmail -t <<-EOF
    To: Me <me@inspiredby.es>
    From: Home <home@inspiredby.es>
    Subject: Home
    Content-Type: text/plain; charset="UTF-8"

    DHCP Lease Added
    EOF
  elif [[ $1 = "del" ]]; then
    sendmail -t <<-EOF
    To: Me <me@inspiredby.es>
    From: Home <home@inspiredby.es>
    Subject: Away
    Content-Type: text/plain; charset="UTF-8"

    DHCP Lease Removed
    EOF
  fi
fi

Sending Email

The last part was making sure I could send email. Since the email would be originating from a residential IP address not only would it be blacklisted by just about every email provider but port 25 is blocked as well. So I had to make due relaying to Gmail’s SMTP server.

apt install postfix

Configuring postfix to be send-only is really easy once you know that they call this configuration a null client.

# /etc/postfix/main.cf

# Settings needed for outgoing mail.
mydomain = estheruary.me
myhostname = home.estheruary.me
myorigin = $mydomain

# Relay to Gmail.
relayhost = [smtp.gmail.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_security_options =
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd

# Settings to disable incoming mail.
inet_interfaces = loopback-only
mydestination =

# Mandatory TLS encryption.
smtp_tls_security_level = encrypt
smtp_tls_mandatory_ciphers = high

And in the file /etc/postfix/sasl_passwd we have the following.

[smtp.gmail.com]:587    username@gmail.com:password

Finally we can restart everything, disable my router’s DHCP server, and see if I can connect.

systemctl restart dnsmasq
systemctl restart postfix

Wrapping Up

A few hours later I got a notification for my first email. And a short while later I got another. It was working! The relief of accomplishing something I desperately needed.