Move to scanner+uploader logic
This commit is contained in:
parent
6d6d242346
commit
7a373a3b85
5 changed files with 59 additions and 190 deletions
18
README.md
18
README.md
|
@ -1,29 +1,29 @@
|
||||||
# CZI presence detector
|
# 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
|
## How scanning works
|
||||||
Sets the wifi adapter into monitor mode, then listens to surrounding packets listing all detected devices into `wifi_map.yaml`.
|
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.
|
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
|
## 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
|
## Set-up
|
||||||
Dependencies:
|
Dependencies:
|
||||||
- Scanner: Python3, trackerjacker (pip3)
|
- Scanner/Uploader: Python3, trackerjacker (pip3)
|
||||||
- Website: php
|
- Website: php
|
||||||
|
|
||||||
Configs to change:
|
Configs to change:
|
||||||
- `scanner/live-scanner.sh`:
|
- `scanner/scanner.sh`:
|
||||||
- WiFi adapter name
|
- WiFi adapter name
|
||||||
- Possibly some more system-specific changes
|
- Possibly some more system-specific changes
|
||||||
- `scanner/upload.py`:
|
- `scanner/uploader.py`:
|
||||||
- URLs for webhook and identities
|
- base URL for webhook and identities
|
||||||
- webhook secret
|
- webhook secret
|
||||||
- `public/update.php`:
|
- `public/update.php`:
|
||||||
- webhook secret
|
- 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.
|
Put `website` onto a php-capable webserver and point your domain to it.
|
||||||
|
|
||||||
## Systemd services
|
## Systemd services
|
||||||
|
@ -38,7 +38,7 @@ User=root
|
||||||
Group=root
|
Group=root
|
||||||
Restart=always
|
Restart=always
|
||||||
WorkingDirectory=/path/to/scanner
|
WorkingDirectory=/path/to/scanner
|
||||||
ExecStart=/path/to/scanner/live-scanner.sh
|
ExecStart=scanner.sh
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
@ -54,7 +54,7 @@ User=pi
|
||||||
Group=pi
|
Group=pi
|
||||||
Restart=always
|
Restart=always
|
||||||
WorkingDirectory=/path/to/scanner
|
WorkingDirectory=/path/to/scanner
|
||||||
ExecStart=/path/to/scanner/live-uploader.sh
|
ExecStart=uploader.py
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|
|
@ -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
|
|
20
scanner/scanner.sh
Normal file
20
scanner/scanner.sh
Normal file
|
@ -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
|
|
@ -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 yaml
|
||||||
import requests
|
import requests
|
||||||
import json
|
import json
|
||||||
import hmac
|
import hmac
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import time
|
||||||
|
|
||||||
BASE_URL = "http://localhost:8080/"
|
BASE_URL = "http://localhost:8080/"
|
||||||
WEBHOOK_SECRET = "CHANGE-THIS"
|
WEBHOOK_SECRET = "CHANGE-THIS"
|
||||||
WIFI_MAP_PATH = "wifi_map.yaml"
|
WIFI_MAP_PATH = "wifi_map.yaml"
|
||||||
|
UPLOAD_INTERVAL = 30
|
||||||
|
|
||||||
def get_identities():
|
def get_identities():
|
||||||
identities_url = BASE_URL.rstrip('/') + '/identities.json'
|
identities_url = BASE_URL.rstrip('/') + '/identities.json'
|
||||||
resp = requests.get(identities_url)
|
resp = requests.get(identities_url)
|
||||||
return resp.json()
|
if resp.status_code == 200:
|
||||||
|
return resp.json()
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
def parse_wifi_map(map_path):
|
def parse_wifi_map(map_path):
|
||||||
# read scan results
|
# read scan results
|
||||||
with open(map_path, 'r') as f:
|
with open(map_path, 'r') as f:
|
||||||
|
@ -25,9 +31,9 @@ def parse_wifi_map(map_path):
|
||||||
# read known identities
|
# read known identities
|
||||||
identities = get_identities()
|
identities = get_identities()
|
||||||
|
|
||||||
print("Known identities:")
|
#print("Known identities:")
|
||||||
for identity in identities:
|
#for identity in identities:
|
||||||
print('mac hash = {}, name = {}'.format(identity['mac_hash'],identity['name']))
|
# print('mac hash = {}, name = {}'.format(identity['mac_hash'],identity['name']))
|
||||||
|
|
||||||
filtered_identities = set()
|
filtered_identities = set()
|
||||||
|
|
||||||
|
@ -43,16 +49,13 @@ def parse_wifi_map(map_path):
|
||||||
if identity['mac_hash'] == mac_hash:
|
if identity['mac_hash'] == mac_hash:
|
||||||
filtered_identities |= {identity['name']}
|
filtered_identities |= {identity['name']}
|
||||||
|
|
||||||
print('\nFiltered identities:')
|
#print('\nFiltered identities:',filtered_identities)
|
||||||
print(filtered_identities)
|
|
||||||
|
|
||||||
return filtered_identities
|
return filtered_identities
|
||||||
|
|
||||||
if __name__ == '__main__':
|
def upload_identities(identities):
|
||||||
filtered_identities = parse_wifi_map(WIFI_MAP_PATH)
|
|
||||||
|
|
||||||
# build request
|
# build request
|
||||||
json_payload = json.dumps(list(filtered_identities)).encode("utf-8")
|
json_payload = json.dumps(list(identities)).encode("utf-8")
|
||||||
|
|
||||||
signature = hmac.new(
|
signature = hmac.new(
|
||||||
key=bytes(WEBHOOK_SECRET, "utf-8"),
|
key=bytes(WEBHOOK_SECRET, "utf-8"),
|
||||||
|
@ -69,6 +72,16 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
# send request
|
# send request
|
||||||
r = requests.post(url=webhook_url, data=json_payload, headers=req_headers)
|
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)
|
|
|
@ -15,112 +15,4 @@ TEST_SSID:
|
||||||
vendor: Apple, Inc.
|
vendor: Apple, Inc.
|
||||||
signal: -86
|
signal: -86
|
||||||
ssid: TEST_SSID
|
ssid: TEST_SSID
|
||||||
vendor: Broadcom
|
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: ''
|
|
Loading…
Reference in a new issue