From 6e0a293075986337d18c2f60748d2e4fd80a958e Mon Sep 17 00:00:00 2001 From: Cobra Date: Fri, 10 Apr 2026 14:55:13 -0400 Subject: [PATCH] Add presence daemon user documentation and architecture guide --- presence/README.md | 202 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 presence/README.md diff --git a/presence/README.md b/presence/README.md new file mode 100644 index 0000000..b80a7d4 --- /dev/null +++ b/presence/README.md @@ -0,0 +1,202 @@ +# Presence Daemon — Person Presence Intelligence + +Passive multi-signal WiFi/ARP/DHCP/BLE person presence tracking daemon for BigBrother drop implant. + +## Quick Start + +```bash +cd /home/n0mad1k/tools/bigbrother/presence +sudo bash install.sh +``` + +This creates `/opt/sensor/sensor.py`, initializes the database, and starts the systemd service. + +## Configuration + +Environment variables: +- `PRESENCE_MONITOR_IFACE` — WiFi monitor mode interface (default: wlan1) +- `PRESENCE_DATA_IFACE` — Connected network interface for ARP/DHCP (default: wlan0) +- `PRESENCE_DB_PATH` — SQLite database location (default: /opt/presence/presence.db) +- `PRESENCE_MATRIX_WEBHOOK` — Matrix webhook URL for alerts (default: empty, no alerts) + +Example systemd override: +```bash +sudo systemctl edit sensor +# Add to [Service] section: +# Environment=PRESENCE_MONITOR_IFACE=wlan2 +# Environment=PRESENCE_MATRIX_WEBHOOK=https://matrix.example.com/hook/... +``` + +## Architecture + +### Sensor Threads (4 concurrent) + +1. **Probe Sniffer** — WiFi probe request capture on monitor interface + - Passive 802.11 frame parsing (type 0, subtype 4) + - Extracts source MAC → +0.60 certainty bump + - Runs on PRESENCE_MONITOR_IFACE + +2. **ARP Listener** — netlink RTM_NEWNEIGH/RTM_DELNEIGH events + - Kernel neighbor discovery events + - Filters infrastructure IPs + - Extracts MAC → +0.50 certainty bump + +3. **DHCP Sniffer** — AF_PACKET raw socket on data interface + - Captures DHCP DISCOVER/REQUEST packets + - Extracts client MAC (chaddr field) + - Extracts hostname (option 12) + - MAC → +0.80 certainty bump + +4. **BLE Scanner** — Passive BLE device discovery + - Uses `bleak` library if available + - Gracefully disables if ImportError + - Device address → +0.40 certainty bump + +### Core Logic + +**Signal Fusion** (per person): +- Collect all device certainties +- Apply exponential decay: `certainty × e^(-0.08 × age_minutes)` +- Aggregate: `max + 0.08 × second_max` +- Check state machine + +**Presence Anchor** (critical): +- Once PRESENT (certainty ≥ 0.40), hold PRESENT for 45 minutes from last signal +- Prevents false ABSENT from temporary signal loss (iOS suppression, WiFi roam, power save) +- After 45 minutes without signal ≥ 0.40 → ABSENT + +**State Machine**: +``` +UNKNOWN → PRESENT → ABSENT → PRESENT + ↓ agg_cert ↓ + └─────────≥ 0.40 45 min no signal +``` + +**Alerting**: +- UNKNOWN → PRESENT: "ARRIVED" alert +- PRESENT → ABSENT: "DEPARTED" alert +- Via Matrix webhook if configured + +### Database Schema + +**persons** — Named people +- id (PK) +- name — Person name +- notes — Optional metadata + +**devices** — MAC-to-person mapping +- mac (PK) +- person_id (FK) +- label — Device name (iPhone, Laptop, etc.) +- added_at — Timestamp + +**signals** — Raw signal observations +- id (PK) +- mac — Device MAC +- signal_type — "probe", "arp", "dhcp", or "ble" +- certainty — Aggregated certainty after this signal +- ts — Observation timestamp + +**occupancy_log** — State transitions +- id (PK) +- person_id (FK) +- old_status — Previous state +- new_status — New state +- ts — Transition timestamp + +## HTTP Status Endpoint + +GET http://127.0.0.1:9191/ + +Returns JSON: +```json +{ + "persons": [ + { + "id": 1, + "name": "Alice", + "status": "PRESENT", + "last_change": 1712761234.5 + } + ] +} +``` + +## Limitations (Phase 1) + +- **No auto-enrollment**: Device-to-person mapping must be set up manually in database +- **No mDNS parsing**: Hostnames are not extracted or used for identity +- **BLE optional**: Requires `bleak` library; gracefully disabled if missing +- **Monitor mode required**: Probe sniffer needs separate WiFi adapter in monitor mode +- **Root access needed**: Raw sockets require CAP_NET_ADMIN or root +- **Single location**: No multi-room support + +## Files + +- `presence_daemon.py` — Main daemon (1000+ lines) +- `presence_schema.sql` — SQLite schema +- `install.sh` — Deployment script +- `AUDIT_impl.md` — Implementation notes and audit checklist +- `README.md` — This file + +## Logging + +Logs to `/var/log/sensor.log` and stdout. Log level: INFO (debug messages only on errors). + +Example log output: +``` +2026-04-10 14:54:32,123 [INFO] Database initialized at /opt/sensor/sensor.db +2026-04-10 14:54:32,124 [INFO] Loaded 2 persons from database +2026-04-10 14:54:32,125 [INFO] Probe sniffer started on wlan1 +2026-04-10 14:54:32,126 [INFO] ARP listener started +2026-04-10 14:54:32,127 [INFO] DHCP sniffer started on wlan0 +2026-04-10 14:54:32,128 [INFO] BLE scanner started +2026-04-10 14:54:32,129 [INFO] Status server started on http://127.0.0.1:9191 +2026-04-10 14:54:32,130 [INFO] Sensor daemon started +``` + +## Testing + +1. Verify systemd service is running: + ```bash + sudo systemctl status sensor + ``` + +2. Check database initialization: + ```bash + sqlite3 /opt/sensor/sensor.db ".tables" + ``` + +3. Query persons: + ```bash + sqlite3 /opt/sensor/sensor.db "SELECT * FROM persons;" + ``` + +4. Query recent signals: + ```bash + sqlite3 /opt/sensor/sensor.db "SELECT * FROM signals ORDER BY ts DESC LIMIT 10;" + ``` + +5. Check status endpoint: + ```bash + curl http://127.0.0.1:9191/ + ``` + +6. Check logs: + ```bash + tail -f /var/log/sensor.log + ``` + +## Phase 2 Roadmap + +- Auto-enrollment from mDNS hostnames +- BLE MAC signature recognition (Apple Watch, AirPods) +- Device quorum (multi-device presence confirmation) +- Tentative device linking via co-occurrence windows + +## Phase 3 Roadmap + +- Pattern of life analytics +- Arrival/departure time learning +- Occupancy forecasting +- Multi-location aggregation