{"id":2067,"date":"2021-11-15T13:53:15","date_gmt":"2021-11-15T10:53:15","guid":{"rendered":"https:\/\/joseph.zikusooka.com\/?p=2067"},"modified":"2021-11-15T14:44:17","modified_gmt":"2021-11-15T11:44:17","slug":"how-to-monitor-the-presence-of-nearby-wifi-devices-using-icinga2","status":"publish","type":"post","link":"https:\/\/joseph.zikusooka.com\/?p=2067","title":{"rendered":"How to monitor the presence of nearby WiFi devices using Icinga2"},"content":{"rendered":"\n<h4 class=\"wp-block-heading\">Introduction<\/h4>\n\n\n\n<p>I recently published a Python based plugin for Icinga and Nagios monitoring platforms that monitors the presence of wireless devices in the vicinity.<\/p>\n\n\n\n<p>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: <a href=\"https:\/\/github.com\/calebmadrigal\/trackerjacker\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/calebmadrigal\/trackerjacker<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Why this way?<\/h4>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Pre-requisites<\/h4>\n\n\n\n<p>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:<br><a href=\"https:\/\/icinga.com\/docs\/icinga-2\/latest\/doc\/01-about\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/icinga.com\/docs\/icinga-2\/latest\/doc\/01-about\/<\/a><\/p>\n\n\n\n<p>The heavy lifting i.e. scanning is done by the Wireshark based CLI tool &#8216;tshark&#8217;. Therefore, ensure that Wireshark is installed on your system. Also, a separate wireless interface that supports monitor mode is required<\/p>\n\n\n\n<p>To capture packets as a non-root user, run the following command in your terminal: <br><code>sudo setcap cap_net_raw,cap_net_admin+eip $(which dumpcap)<\/code><\/p>\n\n\n\n<p>If you&#8217;re still having trouble capturing packets as a non-root user, check out the following Wireshark wiki page:<br><a href=\"https:\/\/wiki.wireshark.org\/CaptureSetup\/CapturePrivileges#Most_UNIXes\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/wiki.wireshark.org\/CaptureSetup\/CapturePrivileges#Most_UNIXes<\/a><\/p>\n\n\n\n<p>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 &gt;&gt; General &gt;&gt; About &gt;&gt; WiFi Address for iOS. For Android, go to Settings &gt;&gt; About &gt;&gt; Status &gt;&gt; Wi-Fi MAC address<\/p>\n\n\n\n<p>N<strong>OTE:<\/strong> Some phones like the iPhone may have MAC randomization enabled, which makes it difficult to reliably monitor their presence status<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Setup Icinga2 plugin<\/h4>\n\n\n\n<p>Download icinga2 monitoring plugin named &#8216;check_tshark&#8217; from my Github page at:<br><a href=\"https:\/\/github.com\/zikusooka\/icinga-nagios-plugins\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/zikusooka\/icinga-nagios-plugins<\/a><\/p>\n\n\n\n<p>Alternatively, you can clone the entire repository and check out my other plugins too:<\/p>\n\n\n\n<p><code>git clone https:\/\/github.com\/zikusooka\/icinga-nagios-plugins<\/code><\/p>\n\n\n\n<p>Copy the icinga2 plugin i.e. check_tshark to your icinga2 monitoring plugins directory e.g. \/usr\/lib64\/nagios\/plugins\/<\/p>\n\n\n\n<p><code>cp -v check_tshark \/usr\/lib64\/nagios\/plugins\/<\/code><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Configure Icinga2<\/h4>\n\n\n\n<p>Add new check and event command objects to icinga2 i.e. Add and save the following snippets to the file:<br>\/etc\/icinga2\/conf.d\/commands.conf<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>object CheckCommand \"tshark\" {\n        import \"plugin-check-command\",\n\n        command = &#91; PluginDir + \"\/check_tshark\" ]\n\n        arguments = {\n                \"-i\"=\"$tshark_interface$\"\n                \"-t\"=\"$tshark_timeout$\"\n                \"-a\"=\"$tshark_address$\"\n        }\n}<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>object EventCommand \"wifi-tshark-status-event\" {\n  import \"plugin-event-command\"\n\n  command = &#91; SysconfDir + \"\/icinga2\/scripts\/wifi-tshark-status-event.sh\" ]\n\n  env = {\n    \"HOSTALIAS\" = \"$host.display_name$\",\n    \"HOSTADDRESS\" = \"$address$\",\n    \"HOSTSTATE\" = \"$host.state$\",\n    \"HOSTSTATEID\" = \"$host.state_id$\",\n    \"HOSTSTATETYPE\" = \"$host.state_type$\",\n    \"HOSTOUTPUT\" = \"$host.output$\",\n    \"HOSTDISPLAYNAME\" = \"$host.display_name$\",\n    \"LASTHOSTSTATE\" = \"$host.last_state$\",\n    \"LASTEHOSTSTATEID\" = \"$host.last_state_id$\",\n    \"LASTHOSTSTATETYPE\" = \"$host.last_state_type$\",\n    \"LASTHOSTSTATECHANGE\" = \"$host.last_state_change$\",\n    \"LASTHOSTCHECK\" = \"$host.last_check$\",\n    \"LONGDATETIME\" = \"$icinga.long_date_time$\",\n  }\n\n}<\/code><\/pre>\n\n\n\n<p>Add new host templates to icinga2 i.e. Add and save the following snippets to the file:<br>\/etc\/icinga2\/conf.d\/templates.conf<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>template Host \"event-tshark-status\" {\n  max_check_attempts = 6\n  check_interval = 30s\n  retry_interval = 5s\n\n  check_command = \"tshark\"\n\n  enable_event_handler = 1\n  event_command = \"wifi-tshark-status-event\"\n\n  enable_flapping = 1\n  flapping_ignore_states = &#91;\"Critical\"]\n}<\/code><\/pre>\n\n\n\n<p>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:<br>\/etc\/icinga2\/conf.d\/hosts.conf<\/p>\n\n\n\n<p><strong>NOTE:<\/strong> In addition to the MAC address, make sure you specify the WiFi interface used for monitoring<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>object Host \"Phone_Zik\" {\n  import \"event-tshark-status\"\n  vars.tshark_interface = \"wlan1\"\n  vars.tshark_timeout = 10\n  vars.tshark_address = \"xx:xx:xx:xx:xx:xx\"\n}\n\nobject Host \"Phone_Shushu\" {\n  import \"event-tshark-status\"\n  vars.tshark_interface = \"wlan1\"\n  vars.tshark_timeout = 10\n  vars.tshark_address = \"xx:xx:xx:xx:xx:xx\"\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Optional: Add Alert notification using MQTT<\/h4>\n\n\n\n<p>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: <a href=\"https:\/\/nullr0ute.com\/2016\/05\/getting-started-with-mqtt-using-the-mosquitto-broker-on-fedora\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/nullr0ute.com\/2016\/05\/getting-started-with-mqtt-using-the-mosquitto-broker-on-fedora\/<\/a><\/p>\n\n\n\n<p>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&#8217;s an example:<\/p>\n\n\n\n<p>Create the following script and make it executable:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; \/etc\/icinga2\/scripts\/wifi-tshark-status-event.sh &lt;&lt;ET\n#!\/bin\/sh\n# Variables\nTSHARK_MAC_ADDRESS=$(echo \"$HOSTOUTPUT\" | grep -oP \"(?&lt;=\\&#91;).+?(?=\\])\")\nMQTT_TOPIC_PRESENCE_TSHARK=Home\/presence\/$TSHARK_MAC_ADDRESS\nMQTT_PUBLISH_CMD=\/usr\/bin\/mosquitto_pub\nMQTT_PUBLISH_OPTS=\"--quiet -h 127.0.0.1 -p 8883\"\n# Quit if type of state alert is 'SOFT'\n&#91;&#91; \"$HOSTSTATETYPE\" = \"SOFT\" ]] &amp;&amp; exit 0\n\n# Publish status via MQTT\nif &#91;&#91; \"$HOSTSTATE\" = \"UP\" ]];\nthen\n$MQTT_PUBLISH_CMD $MQTT_PUBLISH_OPTS -t \"$MQTT_TOPIC_PRESENCE_TSHARK\" -m \"Home\"\n\nelse\n$MQTT_PUBLISH_CMD $MQTT_PUBLISH_OPTS -t \"$MQTT_TOPIC_PRESENCE_TSHARK\" -m \"Away\"\nfi\nET\n \nchmod 755 \/etc\/icinga2\/scripts\/wifi-tshark-status-event.sh<\/code><\/pre>\n\n\n\n<p>To check your configuration and that all syntax is correct; run the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>icinga2 daemon -C<\/code><\/pre>\n\n\n\n<p>If all&#8217;s OK, restart icinga2 as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>systemctl restart icinga2<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Conclusion<\/h4>\n\n\n\n<p>Next, log into your icinga2 web interface (if you have this setup) and ensure your devices are reporting correctly.<\/p>\n\n\n\n<p>In order to monitor alerting via MQTT run the following command in a terminal:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mosquitto_sub -v -h JambulaTV -p 8883 -t \"JambulaTV\/#\" --insecure  | grep presence<\/code><\/pre>\n\n\n\n<p>That&#8217;s all for now. Until next time!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":2069,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":3,"footnotes":""},"categories":[8,19],"tags":[],"class_list":["post-2067","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tools","category-tutorial"],"_links":{"self":[{"href":"https:\/\/joseph.zikusooka.com\/index.php?rest_route=\/wp\/v2\/posts\/2067","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/joseph.zikusooka.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/joseph.zikusooka.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/joseph.zikusooka.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/joseph.zikusooka.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2067"}],"version-history":[{"count":8,"href":"https:\/\/joseph.zikusooka.com\/index.php?rest_route=\/wp\/v2\/posts\/2067\/revisions"}],"predecessor-version":[{"id":2081,"href":"https:\/\/joseph.zikusooka.com\/index.php?rest_route=\/wp\/v2\/posts\/2067\/revisions\/2081"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/joseph.zikusooka.com\/index.php?rest_route=\/wp\/v2\/media\/2069"}],"wp:attachment":[{"href":"https:\/\/joseph.zikusooka.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2067"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/joseph.zikusooka.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2067"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/joseph.zikusooka.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2067"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}