Tom's Homepage

2026-05-11: Notifying of new network devices in pfSense


(This article is also available via the short link tomrei.ch/pfsense-newdevices)

For years, I've been looking for a simple way to get notified when a new device connects to my network. I've tried various pfSense plugins over the years, but they've all had drawbacks of one kind or another. The most recent one I was using stopped working properly when I switched to the Kea DHCP server.

I finally sat down with Claude Opus 4.6 and together we wrote a simple script that does exactly what I want: the first time it sees a MAC address it has never seen before, it sends a Pushover notification. That's it. Super simple, works great, nothing overkill.

Here's the script:


#!/bin/sh
# detect_new_devices.sh
# Monitors the ARP table on pfSense for new (never-before-seen) devices.
# Sends a Pushover notification when a new MAC address appears.
#
# SETUP:
#   1. Copy this script to /usr/local/etc/detect_new_devices.sh on your pfSense box.
#   2. chmod +x /usr/local/etc/detect_new_devices.shsr
#   3. Edit the PUSHOVER_USER_KEY and PUSHOVER_API_TOKEN below.
#   4. Add a cron job (via pfSense GUI or crontab):
#        */1 * * * * /usr/local/etc/detect_new_devices.sh
#      (runs every 1 minute; adjust as desired)
#
# FILES:
#   /usr/local/etc/known_devices.txt  - persistent list of seen MAC addresses + when
#   /usr/local/etc/new_device.log     - log of all new-device detections

# ---- Configuration ----
PUSHOVER_USER_KEY="ENTER USER KEY HERE"
PUSHOVER_API_TOKEN="ENTER API TOKEN HERE"
KNOWN_DEVICES_FILE="/usr/local/etc/known_devices.txt"
LOG_FILE="/usr/local/etc/new_device.log"
# ------------------------

# Create files if they don't exist
touch "$KNOWN_DEVICES_FILE"
touch "$LOG_FILE"

# Parse ARP table: extract IP and MAC pairs for entries that are valid (not incomplete)
arp -an | grep -v incomplete | awk -F'[() ]' '{
    for (i=1; i<=NF; i++) {
        if ($i ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) { ip=$i }
        if ($i ~ /^([0-9a-f]{2}:){5}[0-9a-f]{2}$/) { mac=$i }
    }
    if (ip != "" && mac != "") { print mac, ip; ip=""; mac="" }
}' | while read mac ip; do
    # Normalize MAC to lowercase
    mac=$(echo "$mac" | tr 'A-F' 'a-f')

    # Check if MAC is already known
    if ! grep -qi "^$mac " "$KNOWN_DEVICES_FILE"; then
        timestamp=$(date "+%Y-%m-%d %H:%M:%S")

        # Try to get hostname via DNS reverse lookup
        hostname=$(host "$ip" 2>/dev/null | awk '/domain name pointer/ {print $NF}' | sed 's/\.$//')
        if [ -z "$hostname" ]; then
            hostname="(unknown)"
        fi

        # Record device
        echo "$mac $ip $timestamp $hostname" >> "$KNOWN_DEVICES_FILE"
        echo "$timestamp NEW DEVICE: MAC=$mac IP=$ip HOST=$hostname" >> "$LOG_FILE"

        # Send Pushover notification
        /usr/local/bin/curl -s \
            --form-string "token=$PUSHOVER_API_TOKEN" \
            --form-string "user=$PUSHOVER_USER_KEY" \
            --form-string "title=New Device on Network" \
            --form-string "message=MAC: $mac
IP: $ip
Hostname: $hostname
First seen: $timestamp" \
            --form-string "priority=0" \
            https://api.pushover.net/1/messages.json > /dev/null 2>&1
    fi
done

And the crontab entry to run it on a schedule:


    */1 * * * * /usr/local/etc/detect_new_devices.sh

© 2026 Tom Reich

Home