Skip to main content

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

  1. Through the pfSense router, pfarpwatch has visibility over all subnets/vlans (and across multiple pfSense+ devices in a MIM configuration), and
  2. 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-by switch the desired field may be specified by just the first unique characters; e.g., --sort-by h specifies 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-user places 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_API is 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_APIV2 is a solid choice - fastest.
  • Edit/configure pfarpwatch.cfg, creds_SMTP, and creds_pfarpwatch as needed. The supplied pfarpwatch.cfg explains each setting and the defaults.
  • Run pfarpwatch once manually to build the clients database and the MAC Organizationally Unique Identifier database.
  • Do pfarpwatch --note runs to annotate client info, as desired. Example: pfarpwatch --MAC 80:7d:3a:48:ce:bf --note "Basement lights smartswitch".
  • pfarpwatch --list-db (equivalent to just pfarpwatch) provides a list of all known clients over time.
    • pfarpwatch --sort-by hostname may be useful. The report may be sorted by mac, hostname, ip, device, first_seen, last_seen, notes, or mac_oui. The default SortBy may be set in the config file. Sort terms may be shortened to the first unique characters, e.g., -s m to sort by MAC address.
    • pfarpwatch amaz filters for all clients in the database that have the string 'amaz' (case insensitive) in any field (two in the above example output) while pfarpwatch .2. lists all clients on my Guest WiFi (192.168.2.*, three in the above example output). Filtering is supported with --list-arp-table also.
  • pfarpwatch --list-arp-table provides a list of the currently known network clients. --sort-by is supported with fields mac, hostname, ip, device, and last_seen. Filtering is also supported.
  • pfarpwatch --update finds 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
  • 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 UpdateInterval param 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_id field, which specifies which pfSense+ instance the API request targets. pfarpwatch supports specifying a series of Devices in 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 the creds_pfarpwatch config file API_key param.

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 UpdateInterval param 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_path param. 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_path defaults 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-by switch 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

pfarpwatch-1.0.tar.gz (29.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pfarpwatch-1.0-py3-none-any.whl (24.6 kB view details)

Uploaded Python 3

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

Hashes for pfarpwatch-1.0.tar.gz
Algorithm Hash digest
SHA256 a8cdfc96f19bc63472e544b43e293dad82b581aeae5fc383b672ac0978d27556
MD5 a7991d0f5894a9806656afc4e5097d1d
BLAKE2b-256 579fde1bb9883173379da6c65efeafaed5619074293c2f76b2cbf778e7d4a4e0

See more details on using hashes here.

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

Hashes for pfarpwatch-1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 caead9634f20a997e98772f6bbf341d2a822b2c2a4ed0b1c8b763189fdacc2f0
MD5 88d2cf9bacc4733d8b800db18f2dc0fb
BLAKE2b-256 949c0aa0a0927b20999bf6a95c6e03b7b9b4cc66e5eb8083c3dab1062098e455

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page