Best way to monitor when a device connects and disconnects to network?
-
I want to monitor when a device connects and disconnects to the network. Some of the devices won't reply to ping, and so the next best way I figured is to monitor the ARP table with something like
/usr/sbin/arp --libxo json -a
.I can see on the diagnostics screen that ARP entries last around 20 minutes, and that the DHCP status screen doesn't realise they are offline until the ARP timeout expires and that entry is removed.
I can also run
/usr/sbin/arp -d -a
to delete all entries.I have a feeling that it's not a good idea to be clearing the ARP table every minute or so. Is there a better way to achieve this? Perhaps a script that first attempts to ping the device, then deletes the ARP entry if there's less than X time on the entry, and that script runs once every 2ish minutes?
-
@Slyke you could reduce the time devices stay in the arp cache.
in shell you could reduce from 1200seconds to for example 120 seconds...
sysctl net.link.ether.inet.max_age=120
this will not survive a reboot, but should be good for testing.
-
@Slyke said in Best way to monitor when a device connects and disconnects to network?:
want to monitor when a device connects and disconnects to the network
Just because the arp cache has expired, doesn't mean the device is still not on the network. Just that pfsense has not seen any traffic from it.. I could be busy moving data between it and your nas for example..
if you want to know if something is on the network or not, you prob want to do an actual arp scan every X amount of time you are wanting resolution at, be that 1 minute, 1 hour, etc.
While something might not answer a ping, it would answer a arp.
-
@heper What's the best way to make it permanent? Also, are there any issues with doing this? ARP packets are small, and I can't find any valid reason that decreasing this timeout would cause any issues, except maybe slightly more LAN traffic, which isn't really a problem.
@johnpoz Yeah, not too worried about if some devices aren't detected, like my smart switches or whatever, it's mainly my phone and gf's phone for presence detection, possibly for guests (friends) too. For something like a NAS, I could always ping it, and for smart switches, they reply to http requests (Being Shellys) and pings.
-
@Slyke Maybe DHCP leases?
-
You'd need fairly short leases for that to work. A lease is valid until it expires and that has nothing to do with a device leaving the network.
-
@guile dhcp leases for what? While a device getting a lease for sure could tell you when something joins. There is nothing saying its going to release it when it leaves - especially with wifi devices. They just end up out of range and connect to either cell or another wifi network. Unlike a pc or laptop that might be shutdown and release the dhcp lease as it shutdown, etc..
The best way to monitor close to real time what is on the network and what not on the network is to do a arp scan, and send out notifications for what your interested in.
I use to do using https://www.domotz.com/ which is pretty slick, but the pricing got out of hand for home user - it use to be like 20$ a year or something for a home license - now its like 23 a month.. No thanks.. Fing is the non pro version.. But think its limited to network.
You might be able to do some arp monitoring with zabbix - hmm I think there was a thread around here somewhere were somebody did something with that. Or maybe that was over on reddit? But there is no reason to re-invent the wheel here, sure that is something already done for this.. Be it free as in beer or with some cost.
-
@johnpoz I use Zabbix, but he said some devices wont reply to ping.. and prob cant install zabbix agent.
-
@guile any device will answer arp - use arp scan..
Something like this maybe?
https://github.com/rggassner/gassnerZabbixScripts/tree/master/arpMonitoring
Or something like this maybe
https://github.com/pucherot/Pi.Alert
not a lot of reason to re-invent wheels, if you think of doing X, someone has prob already thought of it and created something ;)
-
@johnpoz I agree reinventing the wheel is not a good idea, but I don't need a fully fledged app installed. I really just need to execute a script (really a mqtt or http request) when these events happens.
I tried getting dhcpd to use its execute() function, but since it's chrooted, cURL or wget need to be statically compiled, or all the libraries cURL or wget need, need to be moved into the chrooted environment. Even after statically compiling them, there were errors that were above my paygrade to solve. So I checked pfsense's source code to see how it determined if a host was online or offline and found that it was executing
/usr/sbin/arp
in one of the files.I also found arpwatch, but it sends the alerts via email for some reason instead of allowing me to execute a shell script for it to run.
So far the best solution I've found is to setup a cronjob that runs every minute, create lockfile, execute
/usr/sbin/arp
use cURL to send the results somewhere, wait 5 seconds and do it again, until 55 seconds have passed then delete lockfile, then exit. I don't even need the host running pfsense to even diff the ARP changes, I just need to be able to see what's there and I can diff it elsewhere (Which will be NodeRed).Pi.Alert does look nice, and I might set it up on my K8s cluster for more advanced monitoring.
Here's the (untested - GPT4 helped write it) script:
#!/bin/bash LOCKFILE="/tmp/arpmonitor.lock" OUTPUT_FILE="/tmp/arpmonitor_output.json" URL="http://w.x.y.z/abc?123=456" MAX_LOOPS=15 MAX_TIME=55 WAIT_BETWEEN_LOOPS=5 if [ -e "${LOCKFILE}" ]; then echo "Lockfile exists, exiting..." exit 1 fi touch "${LOCKFILE}" START=$(date +%s) echo "${START}" > "${LOCKFILE}" LOOP_COUNT=0 while [ $LOOP_COUNT -lt $MAX_LOOPS ] && [ $LOOP_COUNT -ge 0 ]; do NOW=$(date +%s) DIFF=$(( $NOW - $START )) if [ $DIFF -ge $MAX_TIME ]; then echo "${MAX_TIME} seconds passed, exiting..." rm -f "${LOCKFILE}" exit 0 fi OUTPUT=$(/usr/sbin/arp --libxo json -a) echo "${OUTPUT}" > "${OUTPUT_FILE}" # for debugging curl -X POST -H "Content-Type: application/json" -d "${OUTPUT}" ${URL} --connect-timeout 3 LOOP_COUNT=$((LOOP_COUNT+1)) sleep $WAIT_BETWEEN_LOOPS done echo "Loop failed to correctly break (Loops: ${LOOP_COUNT}). Exiting..." exit 2
-
Final reply to this thread for anyone in the future who needs to setup something similar:
I've put the full solution, including the NodeRed flow here: https://gist.github.com/Slyke/7d5b290f1d5695fdd79f5e0a08837c93