# mac_watcher Polls a switch MAC address table via SNMP. Sends email alerts for unknown MACs. Exposes a Prometheus metrics endpoint reflecting the current switch state. ## Requirements - Debian Linux - Python 3.11+ - `snmpwalk` (`apt install snmp`) - Python dependencies: `pip install -r requirements.txt --break-system-packages` ## Install ``` apt install snmp cd /opt git clone https://git.mosad.xyz/localhorst/mac_watcher.git cd /opt/mac_watcher pip install -r requirements.txt --break-system-packages ``` Edit `config.py` and set all values. ``` chmod +x /opt/mac_watcher/mac_watcher.py cp scripts/mac-watcher.service /etc/systemd/system/ systemctl daemon-reload systemctl enable --now mac-watcher.service ``` ## Configuration All settings are in `config.py`. | Setting | Description | |---|---| | `switch_ip_addr` | IP of the managed switch | | `switch_snmp_community` | SNMP v2c community string | | `snmp_poll_interval` | Seconds between polls | | `snmpwalk_bin` | Full path to `snmpwalk` binary | | `trusted_mac_addresses` | Known/allowed MACs — case-insensitive, normalized at startup | | `vendor_cache_file` | Path to persistent vendor cache JSON | | `exporter_host` | Bind address for Prometheus exporter | | `exporter_port` | Port for Prometheus exporter | | `exporter_prefix` | Metric name prefix | | `mail_*` | SMTP credentials and recipients | ## Prometheus Metrics Endpoint: `http://:/metrics` ### Device presence Single gauge reflecting the **last SNMP readout as-is**. Every MAC currently in the switch table is emitted with value `1`. MACs from previous readouts that are no longer present are dropped. Between startup and the first successful poll no device series are emitted. ``` mac_watcher_device_present{mac="AA:BB:CC:DD:EE:FF",trusted="true"} 1 mac_watcher_device_present{mac="11:22:33:44:55:66",trusted="false"} 1 ``` The `trusted` label reflects whether the MAC is in `trusted_mac_addresses`. ### Exporter / cache statistics ``` mac_watcher_exporter_uptime_seconds mac_watcher_exporter_requests_total mac_watcher_snmp_polls_total mac_watcher_vendor_cache_size mac_watcher_vendor_cache_hits_total mac_watcher_vendor_cache_misses_total ``` ### prometheus.yml example ```yaml scrape_configs: - job_name: 'mac_watcher' static_configs: - targets: ['localhost:9200'] scrape_interval: 60s ```