From 7a373a3b853ed77b1e8b3bf28f809928903d5b27 Mon Sep 17 00:00:00 2001 From: Jonathan Flueren <11487762+JonOfUs@users.noreply.github.com> Date: Thu, 17 Aug 2023 21:46:32 +0200 Subject: [PATCH] Move to scanner+uploader logic --- README.md | 18 ++--- scanner/scan.sh | 56 --------------- scanner/scanner.sh | 20 ++++++ scanner/{upload.py => uploader.py} | 45 +++++++----- scanner/wifi_map.yaml | 110 +---------------------------- 5 files changed, 59 insertions(+), 190 deletions(-) delete mode 100644 scanner/scan.sh create mode 100644 scanner/scanner.sh rename scanner/{upload.py => uploader.py} (66%) diff --git a/README.md b/README.md index a2bbcee..58294d1 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,29 @@ # CZI presence detector -Tool to detect the presence of defined devices by their WiFi MAC addresses. +Tool to detect and publish the presence of defined devices by their WiFi MAC addresses. ## How scanning works Sets the wifi adapter into monitor mode, then listens to surrounding packets listing all detected devices into `wifi_map.yaml`. Then, periodically filters the results by the mac addresses that opted in on the website from `identities.json` and sends all matched identities to the website via a signed webhook. This website stores the presence information locally and displays it with `website/index.php` with a timestamp of the last update. ## What the website is capable of -Shows the last update of the `upload.py` routine. It also allows to add identities by their name and mac and to delete identities by their mac. The mac addresses are hashed server-side and then stored into the world-accessible `identities.json`. +Shows the last update of the `uploader.py` routine. It also allows to add identities by their name and mac and to delete identities by their mac. The mac addresses are hashed server-side and then stored into the world-accessible `identities.json`. ## Set-up Dependencies: -- Scanner: Python3, trackerjacker (pip3) +- Scanner/Uploader: Python3, trackerjacker (pip3) - Website: php Configs to change: -- `scanner/live-scanner.sh`: +- `scanner/scanner.sh`: - WiFi adapter name - Possibly some more system-specific changes -- `scanner/upload.py`: - - URLs for webhook and identities +- `scanner/uploader.py`: + - base URL for webhook and identities - webhook secret - `public/update.php`: - webhook secret -Put `scanner` onto the scanning device (e.g. Raspberry Pi). Let `live-scanner.sh` and `live-uploader.sh` running in the background, e.g. by the Systemd services below. +Put `scanner` onto the scanning device (e.g. Raspberry Pi). Let `scanner.sh` and `uploader.pu` running in the background, e.g. by the Systemd services below. Put `website` onto a php-capable webserver and point your domain to it. ## Systemd services @@ -38,7 +38,7 @@ User=root Group=root Restart=always WorkingDirectory=/path/to/scanner -ExecStart=/path/to/scanner/live-scanner.sh +ExecStart=scanner.sh [Install] WantedBy=multi-user.target @@ -54,7 +54,7 @@ User=pi Group=pi Restart=always WorkingDirectory=/path/to/scanner -ExecStart=/path/to/scanner/live-uploader.sh +ExecStart=uploader.py [Install] WantedBy=multi-user.target diff --git a/scanner/scan.sh b/scanner/scan.sh deleted file mode 100644 index ce8d21a..0000000 --- a/scanner/scan.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -adapter=wlan0 -conn_test_url=http://www.google.com - -restart_network() { - systemctl restart wpa_supplicant -} - -# Check for root privileges -if [ "$(id -u)" != "0" ] -then - >&2 echo "Quitting, this script has to be run as root!" - exit 1 -fi - -# Activate Monitor mode -#trackerjacker --monitor-mode-on -i $adapter - -#ip link set $adapter down -#iw dev $adapter set monitor control -#ip link set $adapter up - -# Run scan -timeout 30 trackerjacker -i $adapter --map - -# Deactivate Monitor mode -#trackerjacker --monitor-mode-off -i $adapter - -#ip link set $adapter down -#iw dev $adapter set type managed -#ip link set $adapter up - -# Test network & try to restart if it fails -for i in 1 2 3 4 5 -do - sleep 10 - wget -q --spider $conn_test_url && break - - # no internet connection - echo "No internet - restarting network" - restart_network -done - -# Network restarted up to 5 times, last test for connectivity -wget -q --spider $conn_test_url - -if [ $? -eq 0 ]; then - # Filter & upload results - python upload.py -else - echo "ERROR: no network connection" -fi - -# Remove old scan results -rm wifi_map.yaml \ No newline at end of file diff --git a/scanner/scanner.sh b/scanner/scanner.sh new file mode 100644 index 0000000..830a1ac --- /dev/null +++ b/scanner/scanner.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +adapter=wlan1 + +# Check for root privileges +if [ "$(id -u)" != "0" ] +then + >&2 echo "Quitting, this script has to be run as root!" + exit 1 +fi + +# Activate Monitor mode +#trackerjacker --monitor-mode-on -i $adapter + +#ip link set $adapter down +#iw dev $adapter set monitor control +#ip link set $adapter up + +# Run scan +trackerjacker -i $adapter --remove-unseen-devices --map > /dev/null 2>&1 \ No newline at end of file diff --git a/scanner/upload.py b/scanner/uploader.py similarity index 66% rename from scanner/upload.py rename to scanner/uploader.py index c809fb4..72bf272 100644 --- a/scanner/upload.py +++ b/scanner/uploader.py @@ -1,22 +1,28 @@ -# credits: https://gist.github.com/calebmadrigal/fdb8855a6d05c87bbb0254a1424ee582 +#!/usr/bin/python + +# some credits: https://gist.github.com/calebmadrigal/fdb8855a6d05c87bbb0254a1424ee582 -import sys import yaml import requests import json import hmac import hashlib +import time BASE_URL = "http://localhost:8080/" WEBHOOK_SECRET = "CHANGE-THIS" WIFI_MAP_PATH = "wifi_map.yaml" +UPLOAD_INTERVAL = 30 def get_identities(): identities_url = BASE_URL.rstrip('/') + '/identities.json' resp = requests.get(identities_url) - return resp.json() - - + if resp.status_code == 200: + return resp.json() + else: + return [] + + def parse_wifi_map(map_path): # read scan results with open(map_path, 'r') as f: @@ -25,9 +31,9 @@ def parse_wifi_map(map_path): # read known identities identities = get_identities() - print("Known identities:") - for identity in identities: - print('mac hash = {}, name = {}'.format(identity['mac_hash'],identity['name'])) + #print("Known identities:") + #for identity in identities: + # print('mac hash = {}, name = {}'.format(identity['mac_hash'],identity['name'])) filtered_identities = set() @@ -43,16 +49,13 @@ def parse_wifi_map(map_path): if identity['mac_hash'] == mac_hash: filtered_identities |= {identity['name']} - print('\nFiltered identities:') - print(filtered_identities) + #print('\nFiltered identities:',filtered_identities) return filtered_identities -if __name__ == '__main__': - filtered_identities = parse_wifi_map(WIFI_MAP_PATH) - +def upload_identities(identities): # build request - json_payload = json.dumps(list(filtered_identities)).encode("utf-8") + json_payload = json.dumps(list(identities)).encode("utf-8") signature = hmac.new( key=bytes(WEBHOOK_SECRET, "utf-8"), @@ -69,6 +72,16 @@ if __name__ == '__main__': # send request r = requests.post(url=webhook_url, data=json_payload, headers=req_headers) + #print("Upload response:", r.status_code) + + +if __name__ == '__main__': + while(1): + filtered_identities = parse_wifi_map(WIFI_MAP_PATH) + upload_identities(filtered_identities) + + time.sleep(UPLOAD_INTERVAL) + + + - print("Upload response:") - print(r.status_code) diff --git a/scanner/wifi_map.yaml b/scanner/wifi_map.yaml index 468fb48..1dc1bc0 100644 --- a/scanner/wifi_map.yaml +++ b/scanner/wifi_map.yaml @@ -15,112 +15,4 @@ TEST_SSID: vendor: Apple, Inc. signal: -86 ssid: TEST_SSID - vendor: Broadcom - -eduroam: - 90:48:9a:e3:58:25: - bssid: 90:48:9a:e3:58:25 - bytes: 5073 - channels: - - 1 - devices: - 01:00:5e:96:e1:89: - bytes: 476 - signal: -62 - vendor: '' - 30:8c:fb:66:23:91: - bytes: 278 - signal: -46 - vendor: Dropcam - 34:23:ba:1c:ba:e7: - bytes: 548 - signal: 4 - vendor: SAMSUNG ELECTRO-MECHANICS(THAILAND) - signal: -80 - ssid: eduroam - vendor: TU Dortmundddd - -hacker_network: - 80:2a:a8:e5:de:92: - bssid: 80:2a:a8:e5:de:92 - bytes: 5895 - channels: - - 11 - devices: - 80:1f:02:e6:44:96: - bytes: 960 - signal: -46 - vendor: Edimax Technology Co. Ltd. - 80:2a:a8:8a:ec:c8: - bytes: 472 - signal: 4 - vendor: Ubiquiti Networks Inc. - 80:2a:a8:be:09:a9: - bytes: 5199 - signal: 4 - vendor: Ubiquiti Networks Inc. - d8:49:2f:7a:f0:8f: - bytes: 548 - signal: 4 - vendor: CANON INC. - signal: -46 - ssid: hacker - vendor: Ubiquiti Networks Inc. - 80:2a:a8:61:aa:2f: - bssid: 80:2a:a8:61:aa:2f - bytes: 5629 - channels: - - 44 - - 48 - devices: - 78:88:6d:4e:e2:c9: - bytes: 948 - signal: -52 - vendor: '' - e4:8b:7f:d4:cb:25: - bytes: 986 - signal: -48 - vendor: Apple, Inc. - signal: -48 - ssid: null - vendor: Ubiquiti Networks Inc. - 82:2a:a8:51:32:25: - bssid: 82:2a:a8:51:32:25 - bytes: 3902 - channels: - - 48 - devices: - b8:e8:56:f5:a0:70: - bytes: 1188 - signal: -34 - vendor: Apple, Inc. - signal: -14 - ssid: hacker - vendor: '' - 82:2a:a8:fc:33:b6: - bssid: 82:2a:a8:fc:33:b6 - bytes: 7805 - channels: - - 10 - - 11 - - 12 - devices: - 78:31:c1:7f:25:43: - bytes: 4632 - signal: -52 - vendor: Apple, Inc. - 7c:dd:90:fe:b4:87: - bytes: 423223 - signal: 4 - vendor: Shenzhen Ogemray Technology Co., Ltd. - ff:ff:ff:ff:ff:ff: - bytes: 2323 - signal: 2 - vendor: none - 80:2a:a8:be:09:a9: - bytes: 5199 - signal: 4 - vendor: Ubiquiti Networks Inc. - signal: -62 - ssid: null - vendor: '' \ No newline at end of file + vendor: Broadcom \ No newline at end of file