Introduction
I recently published a Python based plugin for Icinga and Nagios monitoring platforms that monitors the presence of wireless devices in the vicinity.
I really like the stability and reliability Icinga provides when it comes to monitoring the state of hosts or services. There are so many software applications that let you do this, including one I talked about a while back called trackerjacker: https://github.com/calebmadrigal/trackerjacker
Why this way?
At first trackerjacker seemed like what I needed to do this sort of thing, but after several months of testing one issue persisted. The performance hit whenever I started the process was huge. The server, would frequently slow down, as packet capturing and monitoring of WiFi devices took place. So I decided to ditch this tool, and write my own plugin.
I am already using icinga on the server, so I figured, rather than write another app for polling, why not use the existing and well performing icinga2 monitoring software. After all, I had done this with bluetooth devices earlier and presence detection was working so well.
Pre-requisites
You are running a Linux based server with Icinga2 monitoring software installed, configured and working properly. There are several articles about how to install and configure icinga2 including the official documentation at:
https://icinga.com/docs/icinga-2/latest/doc/01-about/
The heavy lifting i.e. scanning is done by the Wireshark based CLI tool ‘tshark’. Therefore, ensure that Wireshark is installed on your system. Also, a separate wireless interface that supports monitor mode is required
To capture packets as a non-root user, run the following command in your terminal: sudo setcap cap_net_raw,cap_net_admin+eip $(which dumpcap)
If you’re still having trouble capturing packets as a non-root user, check out the following Wireshark wiki page:
https://wiki.wireshark.org/CaptureSetup/CapturePrivileges#Most_UNIXes
You will need to identify the MAC address of each wireless device you plan on monitoring. For phones for example, this information is in the Settings >> General >> About >> WiFi Address for iOS. For Android, go to Settings >> About >> Status >> Wi-Fi MAC address
NOTE: Some phones like the iPhone may have MAC randomization enabled, which makes it difficult to reliably monitor their presence status
Setup Icinga2 plugin
Download icinga2 monitoring plugin named ‘check_tshark’ from my Github page at:
https://github.com/zikusooka/icinga-nagios-plugins
Alternatively, you can clone the entire repository and check out my other plugins too:
git clone https://github.com/zikusooka/icinga-nagios-plugins
Copy the icinga2 plugin i.e. check_tshark to your icinga2 monitoring plugins directory e.g. /usr/lib64/nagios/plugins/
cp -v check_tshark /usr/lib64/nagios/plugins/
Configure Icinga2
Add new check and event command objects to icinga2 i.e. Add and save the following snippets to the file:
/etc/icinga2/conf.d/commands.conf
object CheckCommand "tshark" {
import "plugin-check-command",
command = [ PluginDir + "/check_tshark" ]
arguments = {
"-i"="$tshark_interface$"
"-t"="$tshark_timeout$"
"-a"="$tshark_address$"
}
}
object EventCommand "wifi-tshark-status-event" {
import "plugin-event-command"
command = [ SysconfDir + "/icinga2/scripts/wifi-tshark-status-event.sh" ]
env = {
"HOSTALIAS" = "$host.display_name$",
"HOSTADDRESS" = "$address$",
"HOSTSTATE" = "$host.state$",
"HOSTSTATEID" = "$host.state_id$",
"HOSTSTATETYPE" = "$host.state_type$",
"HOSTOUTPUT" = "$host.output$",
"HOSTDISPLAYNAME" = "$host.display_name$",
"LASTHOSTSTATE" = "$host.last_state$",
"LASTEHOSTSTATEID" = "$host.last_state_id$",
"LASTHOSTSTATETYPE" = "$host.last_state_type$",
"LASTHOSTSTATECHANGE" = "$host.last_state_change$",
"LASTHOSTCHECK" = "$host.last_check$",
"LONGDATETIME" = "$icinga.long_date_time$",
}
}
Add new host templates to icinga2 i.e. Add and save the following snippets to the file:
/etc/icinga2/conf.d/templates.conf
template Host "event-tshark-status" {
max_check_attempts = 6
check_interval = 30s
retry_interval = 5s
check_command = "tshark"
enable_event_handler = 1
event_command = "wifi-tshark-status-event"
enable_flapping = 1
flapping_ignore_states = ["Critical"]
}
Finally add the wireless devices you want to monitor to the hosts in icinga2 i.e. Add and save the following snippets to the file:
/etc/icinga2/conf.d/hosts.conf
NOTE: In addition to the MAC address, make sure you specify the WiFi interface used for monitoring
object Host "Phone_Zik" {
import "event-tshark-status"
vars.tshark_interface = "wlan1"
vars.tshark_timeout = 10
vars.tshark_address = "xx:xx:xx:xx:xx:xx"
}
object Host "Phone_Shushu" {
import "event-tshark-status"
vars.tshark_interface = "wlan1"
vars.tshark_timeout = 10
vars.tshark_address = "xx:xx:xx:xx:xx:xx"
}
Optional: Add Alert notification using MQTT
In order to send alerts whenever a WiFi device appears or disappears, you will need to set up a MQTT broker server. I personally use mosquitto on Fedora Linux. For detailed instructions on how to setup mosquitto on Fedora Linux, check out this how to: https://nullr0ute.com/2016/05/getting-started-with-mqtt-using-the-mosquitto-broker-on-fedora/
Since, we have already enabled event handling for our monitored devices in icinga2, all that is left is to add an event script that will be triggered by the HOST state of either UP or DOWN. Here’s an example:
Create the following script and make it executable:
cat > /etc/icinga2/scripts/wifi-tshark-status-event.sh <<ET
#!/bin/sh
# Variables
TSHARK_MAC_ADDRESS=$(echo "$HOSTOUTPUT" | grep -oP "(?<=\[).+?(?=\])")
MQTT_TOPIC_PRESENCE_TSHARK=Home/presence/$TSHARK_MAC_ADDRESS
MQTT_PUBLISH_CMD=/usr/bin/mosquitto_pub
MQTT_PUBLISH_OPTS="--quiet -h 127.0.0.1 -p 8883"
# Quit if type of state alert is 'SOFT'
[[ "$HOSTSTATETYPE" = "SOFT" ]] && exit 0
# Publish status via MQTT
if [[ "$HOSTSTATE" = "UP" ]];
then
$MQTT_PUBLISH_CMD $MQTT_PUBLISH_OPTS -t "$MQTT_TOPIC_PRESENCE_TSHARK" -m "Home"
else
$MQTT_PUBLISH_CMD $MQTT_PUBLISH_OPTS -t "$MQTT_TOPIC_PRESENCE_TSHARK" -m "Away"
fi
ET
chmod 755 /etc/icinga2/scripts/wifi-tshark-status-event.sh
To check your configuration and that all syntax is correct; run the following command:
icinga2 daemon -C
If all’s OK, restart icinga2 as follows:
systemctl restart icinga2
Conclusion
Next, log into your icinga2 web interface (if you have this setup) and ensure your devices are reporting correctly.
In order to monitor alerting via MQTT run the following command in a terminal:
mosquitto_sub -v -h JambulaTV -p 8883 -t "JambulaTV/#" --insecure | grep presence
That’s all for now. Until next time!