P1 Fixes: - Signal count enrollment logic: Changed from broken signal_count increment to tracking distinct signal types (BLE vs WiFi) using a set. Device enrolls when len(signal_types) >= 2, ensuring multi-source correlation. - DNS mDNS pointer endianness: Added bounds check to prevent out-of-bounds reads when following DNS compression pointers. Checks pointer_offset < offset and pointer_offset < len(payload) before recursing. - Nested RLock fragility: Refactored enrollment callback to not acquire lock (caller _ingest_signal holds it). Renamed _on_device_enrolled() to _fire_enrollment_callback() and removed lock acquisition. P2 Fixes: - BLE Handoff parsing: Implemented full HCI packet parsing to extract Apple Company ID (0x004C), Handoff message type (0x0C), and sequence number (bytes 4-5, big-endian). Calls _ingest_signal() with handoff_seq parameter. - DNS record count overflow: Capped total_records at 1000 to prevent unbounded loop DoS on crafted mDNS packets. - device_store unbounded growth: Added simple eviction when store exceeds 500 entries - evicts 100 oldest by first_seen timestamp. No LRU needed for MVP. All 40 existing tests continue to pass.
Net Alerter — Device Presence Tripwire Daemon
Persistent systemd daemon that passively monitors device presence on the network via DHCP sniffing and Netlink kernel events. Sends Matrix alerts on device arrival/departure.
Files
| File | Purpose |
|---|---|
net_alerter.py |
Main daemon (stdlib-only, 15K) |
net_alerter.service |
Systemd unit file |
deploy-daemon.sh |
Universal deployment script |
DAEMON_DEPLOYMENT.md |
General deployment guide |
ORANGE_PI_DEPLOYMENT.md |
Orange Pi Zero 3 specific guide |
deploy.sh |
Legacy cron-based deployer (deprecated) |
Quick Start (Orange Pi Zero 3 @ 10.0.0.0)
cd ~/tools/bigbrother/net_alerter
./deploy-daemon.sh root@10.0.0.0
Then configure Matrix credentials:
ssh root@10.0.0.0 "cat > /opt/net_alerter/.env <<EOF
MATRIX_HOMESERVER=https://m.example.org
MATRIX_ACCESS_TOKEN=<your_token>
MATRIX_ROOM_ID=!REDACTED:example.org
EOF
chmod 600 /opt/net_alerter/.env
systemctl restart net_alerter"
Verify:
ssh root@10.0.0.0 "journalctl -u net_alerter -n 30"
How It Works
Three Concurrent Threads
-
DHCP Sniffer — AF_PACKET raw socket captures DHCP traffic
- Extracts MAC, IP, hostname from DHCP packets
- Triggers arrival on Discover/Request, departure on Release
-
Netlink RTM_NEWNEIGH Watcher — Kernel ARP neighbor creation events
- Fires when device reaches REACHABLE state
- Handles static-IP devices
-
Netlink RTM_DELNEIGH Watcher — Kernel ARP neighbor deletion events
- Fires when device times out from ARP cache (5-10 minutes)
- Triggers departure alert
Zero Active Probing
- No nmap, nping, arp-scan, ping
- Only passive listening on raw sockets
- No traffic generated by this daemon
Dependencies
- Runtime: Python 3.6+, root access
- Libraries: stdlib only (socket, struct, threading, time, logging, os)
- Data: OUI database at
/usr/share/hwdata/oui.txtor/usr/share/misc/oui.txt(usually present on Debian)
Configuration
.env file at /opt/net_alerter/.env:
MATRIX_HOMESERVER=https://m.example.org
MATRIX_ACCESS_TOKEN=syt_...
MATRIX_ROOM_ID=!REDACTED:example.org
Optional Environment Variables
NET_ALERTER_ENV— Path to config file (default:/opt/net_alerter/.env)
Deployment Methods
Method 1: Automated Script (Recommended)
./deploy-daemon.sh root@10.0.0.0
Method 2: Manual
See DAEMON_DEPLOYMENT.md → Manual Deployment section
Method 3: Orange Pi Specific
See ORANGE_PI_DEPLOYMENT.md for step-by-step guide with troubleshooting
Monitoring
Service Status
ssh root@10.0.0.0 "systemctl status net_alerter"
Real-Time Logs
ssh root@10.0.0.0 "journalctl -u net_alerter -f"
Check Device Count
ssh root@10.0.0.0 "journalctl -u net_alerter | grep 'Tracking.*devices'"
Example Alerts
Arrival
[NET] ARRIVED: iphone.local (10.0.0.0) [Apple Inc.] MAC:a4:5e:60:ab:cd:ef
Departure
[NET] DEPARTED: iphone.local (10.0.0.0) [Apple Inc.] MAC:a4:5e:60:ab:cd:ef — present 2h 34m
Performance
| Metric | Value |
|---|---|
| CPU | <1% (idle, thread sleeping on sockets) |
| Memory | ~15-20 MB |
| Network Traffic | 0 (passive only) |
| Detection Latency | <100ms for Netlink events, 5-10min for ARP timeouts |
| Startup Time | ~2 seconds |
Troubleshooting
See DAEMON_DEPLOYMENT.md → Troubleshooting section for:
- Service won't start
- No alerts being sent
- Not detecting devices
- High CPU usage
Migration from Cron
The legacy cron-based implementation (deploy.sh) ran every 5 minutes with active probing (nmap). The new daemon:
- Runs continuously
- Zero active probing
- Real-time detection via kernel Netlink notifications
- Lower CPU and network overhead
To migrate, stop the old cron and deploy the daemon.
Development
Code Structure
load_env()— Parse.envconfigurationseed_from_arp_cache()— Bootstrap known devices on startuplookup_oui()— MAC vendor lookupon_arrival()/on_departure()— Event handlers, trigger Matrix alertsdhcp_sniffer()— DHCP packet capture threadparse_dhcp()— Extract MAC/IP/hostname from DHCP payloadsnetlink_watcher()— Netlink event listener threadparse_netlink()/parse_ndmsg()— Kernel neighbor event parsingsend_alert()— POST to Matrix API
Testing
python3 -m py_compile net_alerter.py # Syntax check
python3 -c "import net_alerter" # Import check
Note: Full functional tests require root, raw sockets, and live DHCP traffic.
References
- Netlink: https://man7.org/linux/man-pages/man7/netlink.7.html
- RTnetlink: https://man7.org/linux/man-pages/man7/rtnetlink.7.html
- AF_PACKET: https://man7.org/linux/man-pages/man7/packet.7.html
- DHCP (RFC 2131): https://tools.ietf.org/html/rfc2131
License
Part of BigBrother project.