# Net Alerter Daemon Deployment ## Overview The new `net_alerter.py` is a persistent systemd daemon that monitors device presence via passive network observation. It replaces the previous 5-minute cron-based implementation with three concurrent threads running indefinitely. ## Architecture ### Three Concurrent Threads 1. **DHCP Sniffer** (AF_PACKET raw socket) - Captures DHCP packets passively on the network interface - Extracts MAC, IP, and hostname from DHCP Discover/Request/Release messages - Triggers `on_arrival()` for Discover/Request, `on_departure()` for Release 2. **RTM_NEWNEIGH Watcher** (Netlink socket) - Kernel pushes RTM_NEWNEIGH events when ARP neighbors reach REACHABLE/STALE/DELAY/PROBE states - Supplements DHCP sniffer for devices that don't use DHCP - Triggers `on_arrival()` immediately 3. **RTM_DELNEIGH Watcher** (Netlink socket) - Kernel pushes RTM_DELNEIGH events when ARP neighbors are deleted (5-10 minutes after last seen) - Triggers `on_departure()` when neighbor is removed from kernel table ### Key Features - **Zero Active Probing** — no nmap, no arp-scan, no ping. Only passively listens. - **Stdlib Only** — no external dependencies (socket, struct, threading, time, logging, os) - **Thread-Safe** — `known_devices` dict protected by `threading.Lock` - **Persistent Daemon** — systemd service with auto-restart - **Logging to File + Stdout** — `/opt/net_alerter/net_alerter.log` - **Matrix Alerting** — sends alerts to configured Matrix room on arrival/departure ## Prerequisites ### Device Requirements - Debian-based OS (Debian, Raspbian, Orange Pi OS) - Python 3.6+ - Root access (AF_PACKET and Netlink require CAP_NET_RAW) - Primary network interface (auto-detected from /proc/net/route) ### Configuration Files The daemon reads `/opt/net_alerter/.env` at startup: ```bash MATRIX_HOMESERVER=https://m.example.org MATRIX_ACCESS_TOKEN= MATRIX_ROOM_ID=!REDACTED:example.org ``` If `.env` doesn't exist, it will log a warning and try environment variables instead. ## Deployment ### Quick Deployment Script ```bash cd ~/tools/bigbrother/net_alerter ./deploy-daemon.sh [user@host] [remote-dir] # Examples: ./deploy-daemon.sh root@10.0.0.0 ./deploy-daemon.sh root@10.0.0.0 /opt/net_alerter ``` ### Manual Deployment 1. **Copy files to device:** ```bash scp net_alerter.py root@10.0.0.0:/opt/net_alerter/ scp net_alerter.service root@10.0.0.0:/etc/systemd/system/ ``` 2. **Configure .env on device:** ```bash ssh root@10.0.0.0 cat > /opt/net_alerter/.env < MATRIX_ROOM_ID=!REDACTED:example.org EOF chmod 600 /opt/net_alerter/.env ``` 3. **Remove old cron:** ```bash ssh root@10.0.0.0 "crontab -l 2>/dev/null | grep -v net_alerter | crontab -" ``` 4. **Enable and start service:** ```bash ssh root@10.0.0.0 " systemctl daemon-reload systemctl enable net_alerter systemctl restart net_alerter " ``` ## Verification ### Service Status ```bash ssh root@10.0.0.0 "systemctl status net_alerter --no-pager" ``` Expected output: ``` ● net_alerter.service - Net Alerter Loaded: loaded (/etc/systemd/system/net_alerter.service; enabled; preset: enabled) Active: active (running) ``` ### View Logs ```bash ssh root@10.0.0.0 "journalctl -u net_alerter -n 50 --no-pager" ``` Expected startup logs: ``` Net alerter starting on interface eth0 Seeded 12 devices from ARP cache Net alerter running — DHCP sniffer + Netlink neighbor watcher active ``` ### Real-time Monitoring ```bash ssh root@10.0.0.0 "journalctl -u net_alerter -f" ``` Then connect a test device to the network — you should see arrival alerts. ## Event Examples ### Device Arrival (DHCP-based) ``` [NET] ARRIVED: mobile.local (10.0.0.0) [Apple Inc.] MAC:a4:5e:60:00:11:22 ``` ### Device Departure (ARP timeout) ``` [NET] DEPARTED: mobile.local (10.0.0.0) [Apple Inc.] MAC:a4:5e:60:00:11:22 — present 2h 34m ``` ## Configuration Environment Variables Can override via env or .env file: | Variable | Default | Purpose | |----------|---------|---------| | `NET_ALERTER_ENV` | `/opt/net_alerter/.env` | Path to config file | | `MATRIX_HOMESERVER` | `https://m.example.org` | Matrix server URL | | `MATRIX_ACCESS_TOKEN` | (required) | Auth token for bot account | | `MATRIX_ROOM_ID` | (required) | Room ID to send alerts to | ## Troubleshooting ### Service won't start ```bash ssh root@10.0.0.0 "journalctl -u net_alerter -n 30" ``` Check for permission errors or missing dependencies. ### No alerts being sent - Verify `MATRIX_ACCESS_TOKEN` is valid: `curl https://m.example.org/_matrix/client/v3/account/whoami -H "Authorization: Bearer "` - Verify bot is in the room: check room membership on Matrix client - Check logs for HTTP errors: `journalctl -u net_alerter -e` ### Not detecting devices - Ensure DHCP traffic is visible on the interface (some switches may filter it) - For static IP devices, Netlink RTM_NEWNEIGH should still detect them - Check ARP cache: `ip neigh show` ### High CPU usage - Unlikely — threads sleep on socket reads. Check for malformed packets in logs. - Reduce logging level if debug spam is heavy. ## Uninstall ```bash ssh root@10.0.0.0 " systemctl stop net_alerter systemctl disable net_alerter rm /etc/systemd/system/net_alerter.service systemctl daemon-reload rm -rf /opt/net_alerter " ``` ## Migration from Cron The old cron-based implementation: - Ran `net_alerter.py` every 5 minutes - Had a cold start on each run - Could miss transient devices in the 5-minute window - Was CPU-hungry during scans (nmap probes) The new daemon: - Runs continuously, detecting changes in real-time - Zero active probing - Uses Kernel Netlink notifications for instant feedback - Lower overall CPU + network overhead