pfarpwatch - Watch for new clients on your pfSense managed LAN
I use pfSense as my home network router and find that over time that I've accumulated many clients on my network that I cannot readily identify. pfarpwatch watches the pfSense ARP table and tracks changes in a sqlite3 database. Any new client found on the network results in a text message notification.
- The history of known clients is tracked by MAC address. No changes are ever made on the pfSense device.
- Clients come and go over time, as family members come and visit.
- Clients may be manually deleted from the database (i.e., That laptop went in the tub with kids! (long gone)).
- Some hostnames are ambiguous, such as '*' and 'android-2ab8700dff69dbfd', and some devices issue random MAC addresses. Notes may be manually added for each client.
- The Organization Unique ID for for each clients' MAC address is looked up and added to the database, often providing enough info to identify strange clients.
- The clients database may easily be queried, with sort order and search/filter options.
Definition of terms:
- client is used in this documentation to refer to a host/client on your network.
- device refers to a pfSense(+) router on your network.
Supports
- Linux and Windows
- Python 3.9+
- pfSense+ 25.07.1 and above, and corresponding pfSense CE versions (2.8.0+?)
- Tested on 25.07.1, 25.11 and 26.03, 26.07
- pfSense+ MIM API and UnofficialV2 API modes
But why this tool, versus other solutions?
The key benefits of pfarpwatch over others are that
- Through the pfSense router, pfarpwatch has visibility over all subnets/vlans (and across multiple pfSense+ devices in a MIM configuration), and
- The collected client data can be annotated (and searched and sorted).
Compared to arpwatch on pfSense
Do use the arpwatch package on pfSense as your best alternative. The downsides of this solution is that 1) You most log into the pfSense router to view the data (but you'll have a nice GUI), and 2) logged client info cannot be annotated, so you'll have a collection of unidentifiable clients in the log.
arpwatch on a network client machine
Running the standard arpwatch tool (published by LBNL and available in many Linux distro repos) on a client on your network will log/track clients only on your client's subnet, not the whole LAN network. Also no annotation capability.
Notable changes since prior release (routermonitor V4.0.1)
- Changed from tracking the DHCP server to tracking the ARP table.
- Dropped the expiry field, and now last_seen is tracked for all clients **.
- Dropped page scrape mode.
- Customizable reporting with user settable field widths and order.
- With the CLI
--sort-byswitch the desired field may be specified by just the first unique characters; e.g.,--sort-by hspecifies to sort by hostname. - Both email and notification options, with selectable client field changes
- Local database of IEEE macoui's is maintained, with user-scheduled update frequency.
- Renamed to pfarpwatch 1.0.
** Note: ARP Table records show time to expiry of each arp record (e.g., "Expires in 1138 seconds"), and clients must re-announce themselves (or produce other traffic) before this timeout. pfarpwatch calculates when a client was last seen using the net.link.ether.inet.max_age (typically/default 1200 seconds / 20 minutes). The ARP_timeout param in the config file must match the pfSense value (you may check it in the GUI: Enter sysctl net.link.ether.inet.max_age on Diagnostics > Command Prompt > Execute Shell Command).
Usage
$ pfarpwatch --help
usage: pfarpwatch [-h] [--update] [--list-db] [--list-arp-table] [--sort-by SORT_BY] [--create-db] [--MAC MAC] [--note NOTE] [--delete] [--config-file CONFIG_FILE] [--print-log] [--service]
[--verbose] [--setup-user] [--setup-site] [--create-macoui-db] [--log-console] [--dev] [--version]
[SearchTerm]
Monitor clients on the network
Track pfSense's Diagnostics > ARP Table for recently seen network clients.
Any new clients are added to the tracking database, and a notification or email may be sent.
The database is easily searched, with customizable report formatting.
$ pfarpwatch
Prints the tracked clients list (defaults to --list-db)
$ pfarpwatch --sort-by mac
Prints the tracked clients list sorted by MAC address
$ pfarpwatch amazon
Prints the tracked clients list filtered for the search term in any field
$ pfarpwatch --list-arp-table
Prints the current pfSense ARP Table contents
1.0
positional arguments:
SearchTerm Print database records containing this text
options:
-h, --help show this help message and exit
--update, -u Check the pfSense router for new network clients and update the database
--list-db, -l Print known clients on the network from the database (default mode)
--list-arp-table, -r Print known clients on the network from the pfSense router ARP table
--sort-by SORT_BY, -s SORT_BY
Sort --list-db and --list-arp-table output. Overrides config SortBy (default <hostname> if neither specified).
--create-db Create a fresh database and populate it with the current network clients
--MAC MAC, -m MAC MAC address for --note or --delete
--note NOTE, -n NOTE Add a note to the database for the specified --MAC
--delete Delete from the database the specified --MAC
--config-file CONFIG_FILE, -c CONFIG_FILE
Path to the config file (Default <pfarpwatch.cfg)> in user/site config directory
--print-log, -p Print the tail end of the log file (default last 40 lines)
--service Run updates in an endless loop for use as a systemd service
--verbose, -v Print status and activity messages in non-service mode (-vv for debug logging)
--setup-user Install starter files in user space
--setup-site Install starter files in system-wide space - run with root prev
--create-macoui-db Build a fresh macoui database
--log-console, -z Force logging to the console, overriding the config LogFile param
--dev Run development code
--version, -V Print version number and exit
Example output
$ pfarpwatch
WARNING: ========== pfarpwatch (1.0) ==========
WARNING: Config file </path/to/pfarpwatch.cfg>
hostname first_seen last_seen ** ip device mac mac_oui notes
Denon-AVR-X1600H 2020-05-22 18:23:30 2025-11-29 21:29:18 192.168.1.112 pfsense.mylan 00:05:cd:8a:ab:8d Denon, Ltd. -
Galaxy-S10-jen 2020-05-22 18:23:33 2025-11-30 11:01:02 192.168.1.114 pfsense.mylan 10:98:c3:80:cd:b2 Murata Manufacturing Co., Ltd. -
amazon-b6f1c2033 2020-05-23 06:45:05 2025-11-30 11:06:36 192.168.1.118 pfsense.mylan 38:f7:3d:16:ef:40 Amazon Technologies Inc. Wife's Kindle Fire
espressif 2020-05-22 18:23:35 2025-11-30 11:23:37 192.168.2.121 pfsense.mylan 44:67:55:02:01:7f Orbit Irrigation -
Flex5 2020-05-22 18:23:36 2025-11-30 11:25:41 192.168.1.123 pfsense.mylan 50:5b:c2:e1:23:ef Liteon Technology Corporation -
* 2020-05-22 18:23:37 2025-11-30 11:31:48 192.168.1.144 pfsense.mylan 64:52:99:90:45:aa The Chamberlain Group, Inc Liftmaster gateway 828LM in office
MyQ-F8C 2020-05-22 18:23:38 2025-11-30 11:32:15 192.168.1.143 pfsense.mylan 64:52:99:91:67:51 The Chamberlain Group, Inc Garage door opener
ESP_48CEBF 2020-05-22 18:23:40 2025-11-30 11:33:19 192.168.2.146 pfsense.mylan 80:7d:3a:48:89:bf Espressif Inc. Basement lights smartswitch
* 2020-05-22 18:23:41 2025-11-30 11:34:23 192.168.2.133 pfsense.mylan 8c:85:80:1d:ab:69 Smart Innovation LLC Eufy doorbell
RPi1 2020-05-22 18:23:42 2025-11-30 11:36:13 192.168.1.31 pfsense.mylan b8:27:eb:25:cd:f7 Raspberry Pi Foundation -
FireStick4k 2020-05-22 18:23:44 2025-11-30 11:37:04 192.168.1.40 pfsense.mylan cc:9e:a2:56:ef:c9 Amazon Technologies Inc. -
...
<73> known clients.
Setup and Usage notes
- Install and configure/enable the pfSense arpwatch package. (Tested on arpwatch version 0.2.5.)
- Track all interfaces/subnets of interest on your LAN.
- Disable bogons and 0.0.0.0 changes
- Install pfarpwatch from PyPI (
pip install pfarpwatch) - Install the initial configuration files (
pfarpwatch --setup-userplaces files at~/.config/pfarpwatch). - Decide on which DHCP clients list lookup method you wish to use (see more details below). Both modes result in the same content in pfarpwatch:
Mode = MIM_APIis the best choice if you are using a Netgate pfSense+ device or have a Plus license - reasonably fast. If using the MIM API you will need to manually install the Netgate pfsense-api (see below).Mode = Unofficial_APIV2is a solid choice - fastest.
- Edit/configure
pfarpwatch.cfg,creds_SMTP, andcreds_pfarpwatchas needed. The suppliedpfarpwatch.cfgexplains each setting and the defaults. - Run
pfarpwatchonce manually to build the clients database and the MAC Organizationally Unique Identifier database. - Do
pfarpwatch --noteruns to annotate client info, as desired. Example:pfarpwatch --MAC 80:7d:3a:48:ce:bf --note "Basement lights smartswitch". pfarpwatch --list-db(equivalent to justpfarpwatch) provides a list of all known clients over time.pfarpwatch --sort-by hostnamemay be useful. The report may be sorted by mac, hostname, ip, device, first_seen, last_seen, notes, or mac_oui. The defaultSortBymay be set in the config file. Sort terms may be shortened to the first unique characters, e.g.,-s mto sort by MAC address.pfarpwatch amazfilters for all clients in the database that have the string 'amaz' (case insensitive) in any field (two in the above example output) whilepfarpwatch .2.lists all clients on my Guest WiFi (192.168.2.*, three in the above example output). Filtering is supported with--list-arp-tablealso.
pfarpwatch --list-arp-tableprovides a list of the currently known network clients.--sort-byis supported with fields mac, hostname, ip, device, and last_seen. Filtering is also supported.pfarpwatch --updatefinds any new clients on the network, adds them to the database, and optionally sends a text and/or email message notification (see pfarpwatch.cfg). Changes to hostname, ip address, device, last_seen, and mac_oui may also be logged and have text/email notifications sent.- Optionally set up the pfarpwatch systemd service. A template .service file is provided in the config directory.
- When running in service mode (continuously looping) the config file may be edited and is reloaded when changed. This allows for changing settings without having to restart the service.
Using the Netgate Nexus MIM API (pfSense+ devices/appliances only) (Mode = MIM_API)
Setup
-
Clone the Python interface github distribution to your local filesystem
cd <my-temp-space> git clone https://github.com/Netgate/pfsense-api.git # creates ./pfsense-api pip install ./pfsense-api/py # Once installed the cloned directory <my-temp-space>/pfsense-api may be deleted. -
In the pfsense+ GUI set the device to HTTPS access mode
- The API will not work in HTTP mode
- System > Advance > Admin Access > Protocol = HTTPS (SSL/TLS)
- This uses a self-signed certificate, so your browser may want your approval to connect.
- For more secure access, see below for setting up a certificate authority. Do this step before enabling Netgate Nexus Controller so that port 8443 is properly set up with the internally signed 'Server Certificate'. If you set up the CA after enabling Netgate Nexus then simply disable and re-enable Netgate Nexus Controller again.
-
Enable Netgate Nexus
- System > Advanced > Netgate Nexus > Enable Netgate Nexus Controller
- This enables the official Nexus MIM API. Without paying for a license you can access only the
localhostdevice. - See https://docs.netgate.com/pfsense/en/latest/nexus/setup.html
- The user must have full admin privileges (be a member of the admins group), as of 25.07.1 RELEASE.
- This enables the official Nexus MIM API. Without paying for a license you can access only the
- System > Advanced > Netgate Nexus > Enable Netgate Nexus Controller
-
See the pfarpwatch.cfg starter file for configuring access to the MIM API.
Notes and considerations
- This API returns the same information as on the Diagnostics > ARP Table page. Note that this table only has a 20 minute retention window by default, so set the
UpdateIntervalparam to less than 20 minutes. - Netgate Nexus and the MIM API were first released on pfSense+ version 25.07. For older pfSense+ versions and the CE version see the Unofficial V2 API.
- Hostnames come from any DHCP server assigned hostnames, with fallback to whatever the client provides. Windows clients may have a '.' appended to the hostname.
- Netgate Nexus on pfSense+ devices provides the multi-instance management (MIM) API, with specific support for accessing/controlling multiple pfSense+ devices on a network from a single "controller" (the master pfSense+ device). MIM API accesses have a
device_idfield, which specifies which pfSense+ instance the API request targets.pfarpwatchsupports specifying a series ofDevicesin the config file. The devices will be accessed in the order listed with all found clients merged into one clients list (unique by MAC address). The default Devices lists is['localhost']. 'Devices = All' causes the MIM controller to be queried for the list of managed devices. If you have a multi-instance network you will need a paid subscription to use Nexus across devices, and then the MIM API can also be used across devices. Without a paid subscription the MIM API may be used for reading the ARP table from only the main 'localhost' MIM controller.
Using the Unofficial V2 API (Mode = Unofficial_APIV2)
Setup
-
Install the Unofficial V2 API on your pfSense device. This API works on both Netgate pfSense+ devices (24.11+) and on CE devices (2.8.0+). See https://pfrest.org/INSTALL_AND_CONFIG/. The install can be done via an SSH login, using the device console, or using the GUI Diagnostics > Command Prompt > Execute Shell Command. Example for pfSense+ 26.03 (do install the correct version):
pkg-static -C /dev/null add https://github.com/jaredhendrickson13/pfsense-api/releases/latest/download/pfSense-26.03-pkg-RESTAPI.pkg -
To enable the API, briefly, you will need to, at System > REST API > Settings, Enable the API, set Allowed Interfaces, and set up the Authentication Method to
Key. On the Keys tab, create a key and save the key value to thecreds_pfarpwatchconfig fileAPI_keyparam.
Notes and considerations
- This API returns the same information as on the Diagnostics > ARP Table page. Note that this table only has a 20 minute retention window by default, so set the
UpdateIntervalparam to less than 20 minutes. - This API runs faster that the MIM API.
- Hostnames come from any DHCP server assigned hostnames, with fallback to whatever the client provides. Windows clients may have a '.' appended to the hostname.
- The reported device field will always be the URL to the pfSense device since there is no multi-device support.
- After a pfSense upgrade you will need to install the new/correct version of the Unofficial V2 API. Note that the previously issued key still seems to be in-place and active, so after installing the updated API all should be well.
Using a Certificate Authority
Each access mode supports verified SSL access by configuring a certificate authority within pfSense. In short, to set up certificates for use with pfarpwatch:
- Create a self-signed 'CA certificate' (System > Certificates > Authorities), then 'Export CA' to a file. This is the CA public key. Set the path to this file in the pfarpwatch config file
CA_pathparam. Note that the directory path to the CA file defaults to~/.config/pfarpwatch- an absolute path or a path relative to ~/.config/pfarpwatch may be specified. - Create a internally signed 'Server Certificate' (System > Certificates > Certificates) that refers to the new CA certificate (thus not a self-signed server certificate), with a Common Name (CN) or SAN entry set to the URL being used to access the device by pfarpwatch.
- Change the webGUI (webConfigurator) to use the new internally signed server certificate (System > Advanced > Admin Access > SSL/TLS Certificate). Once set, the new server certificate will show as in use by the 'webConfigurator'. Delete the original server cert. Your browser may need some nudging at this point.
- If applicable, change the MIM API to use the new internally signed server certificate (System > Advanced > Netgate Nexus > TLS Certificate). You may need to disable/re-enable Netgate Nexus to propagate the new certificate setup to port 8443.
Notes
- Use of a CA is optional.
CA_pathdefaults to False if not defined, which disables SSL verification. - When upgrading pfSense to a new version, these certificates seem to work correctly without needing any attention after the upgrade.
Version history
- 1.0 260828
- Ported from routermonitor
- Changed from tracking the DHCP server to tracking the ARP table
- Dropped the expiry field, and now last_seen is tracked for all clients
- Dropped page scrape mode
- Customizable reporting with user settable field widths and order
- With the CLI
--sort-byswitch the desired field may be specified by just the first unique characters - Text and email notifications supported for user selectable client field changes
- Local database of IEEE macoui's is maintained, with user-scheduled update frequency.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pfarpwatch-1.0.tar.gz.
File metadata
- Download URL: pfarpwatch-1.0.tar.gz
- Upload date:
- Size: 29.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8cdfc96f19bc63472e544b43e293dad82b581aeae5fc383b672ac0978d27556
|
|
| MD5 |
a7991d0f5894a9806656afc4e5097d1d
|
|
| BLAKE2b-256 |
579fde1bb9883173379da6c65efeafaed5619074293c2f76b2cbf778e7d4a4e0
|
File details
Details for the file pfarpwatch-1.0-py3-none-any.whl.
File metadata
- Download URL: pfarpwatch-1.0-py3-none-any.whl
- Upload date:
- Size: 24.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
caead9634f20a997e98772f6bbf341d2a822b2c2a4ed0b1c8b763189fdacc2f0
|
|
| MD5 |
88d2cf9bacc4733d8b800db18f2dc0fb
|
|
| BLAKE2b-256 |
949c0aa0a0927b20999bf6a95c6e03b7b9b4cc66e5eb8083c3dab1062098e455
|