OpenWrt智能设备监控:用Shell脚本打造自动化网络管家
家里智能设备越来越多,路由器上显示的连接设备列表也愈发杂乱无章。作为技术爱好者,我们总希望能第一时间知道哪些新设备接入了家庭网络——可能是朋友的手机,也可能是孩子新买的智能手表,甚至是可疑的未知设备。传统的手动刷新路由器管理页面显然不够优雅,而OpenWrt这个开源路由器系统正好为我们提供了自动化监控的可能。
本文将带你开发一个运行在OpenWrt上的"设备管家"脚本,它能自动检测新接入的设备,并通过多种方式实时通知你。不同于简单的设备列表查询,这个方案实现了全自动化监控,特别适合智能家居爱好者、小型办公室管理员或任何对网络安全有基本要求的用户群体。我们将从ARP和DHCP协议的工作原理入手,逐步构建一个稳定可靠的监控系统。
1. 监控原理与技术选型
在OpenWrt系统上监控新设备接入,主要有三种技术路线可供选择:ARP缓存分析、DHCP租约监控和无线客户端列表。每种方法各有优劣,理解它们的特性对构建可靠系统至关重要。
ARP(地址解析协议)缓存是操作系统维护的IP地址到MAC地址的映射表。在OpenWrt中,可以通过/proc/net/arp文件查看当前ARP缓存:
IP address HW type Flags HW address Mask Device 192.168.1.1 0x1 0x2 00:11:22:33:44:55 * br-lan 192.168.1.100 0x1 0x2 aa:bb:cc:dd:ee:ff * br-lan其中Flags字段的0x2表示设备当前在线。ARP监控的优点是响应快,设备一接入网络就会出现在ARP表中;缺点是缓存有时间限制(通常几分钟),不活跃设备会被移除。
DHCP租约则是路由器分配给设备的IP地址记录,存储在/tmp/dhcp.leases文件中:
1234567890 aa:bb:cc:dd:ee:ff 192.168.1.100 my-phone *这个文件包含租约到期时间、MAC地址、IP地址和设备名(如果设备提供了主机名)。DHCP监控的优势是信息更完整(包含设备名),且记录会持久保存到租约到期;缺点是只有当设备请求或续约DHCP时才会更新。
无线客户端列表可以通过iwinfo命令获取,但只适用于无线连接设备。综合比较,ARP+DHCP组合方案最为全面可靠。
2. 基础脚本开发与设备识别
让我们从最简单的设备发现脚本开始。这个脚本将比较当前设备列表与之前保存的记录,找出新增设备。
首先创建存储已知设备数据库的文件:
KNOWN_DEVICES="/etc/device_monitor/known_devices.db" mkdir -p /etc/device_monitor [ -f "$KNOWN_DEVICES" ] || touch "$KNOWN_DEVICES"接下来是核心的对比函数,使用DHCP租约文件作为数据源:
check_new_devices() { current_devices=$(cat /tmp/dhcp.leases | awk '{print $2,$3,$4}') while read -r mac ip name; do if ! grep -q "$mac" "$KNOWN_DEVICES"; then echo "New device found: MAC=$mac IP=$ip Name=$name" echo "$mac $ip $name $(date +%s)" >> "$KNOWN_DEVICES" fi done <<< "$current_devices" }这个基础版本有几个明显问题:设备改名会导致重复通知,重启路由器会丢失/tmp/dhcp.leases文件。我们需要改进数据持久化方式:
# 改进的数据存储路径 PERSISTENT_STORAGE="/etc/device_monitor/device_history.log" LOG_ROTATE_SIZE=1000 record_device() { local mac=$1 ip=$2 name=$3 local timestamp=$(date +"%Y-%m-%d %H:%M:%S") # 检查是否已有记录 local last_record=$(grep "^$mac" "$PERSISTENT_STORAGE" | tail -n1) if [ -z "$last_record" ]; then echo "[NEW] $timestamp $mac $ip $name" >> "$PERSISTENT_STORAGE" return 1 elif ! echo "$last_record" | grep -q "$name"; then echo "[RENAME] $timestamp $mac $ip $name (was ${last_record##* })" >> "$PERSISTENT_STORAGE" return 2 fi return 0 } # 日志轮转检查 [ $(wc -l < "$PERSISTENT_STORAGE") -gt $LOG_ROTATE_SIZE ] && { mv "$PERSISTENT_STORAGE" "$PERSISTENT_STORAGE.old" gzip "$PERSISTENT_STORAGE.old" }3. 增强可靠性:ARP与DHCP双校验
单纯依赖DHCP租约可能漏掉静态IP设备,而仅用ARP缓存又缺少设备名信息。结合两者能显著提高监控可靠性。
check_arp_table() { awk '$3=="0x2"{print $4,$1}' /proc/net/arp | while read mac ip; do local dhcp_info=$(grep "$mac" /tmp/dhcp.leases) local name=$(echo "$dhcp_info" | awk '{print $4}') [ -z "$name" ] && name="unknown" if ! grep -q "^$mac" "$PERSISTENT_STORAGE"; then record_device "$mac" "$ip" "$name" case $? in 1) handle_new_device "$mac" "$ip" "$name" ;; 2) handle_rename_device "$mac" "$ip" "$name" ;; esac fi done }实际部署时还需要考虑ARP缓存的时效性问题。OpenWrt默认ARP缓存超时时间为30秒到几分钟不等,可以通过调整内核参数延长:
# 设置ARP缓存超时为1小时(3600秒) echo 3600 > /proc/sys/net/ipv4/neigh/default/gc_stale_time echo 3600 > /proc/sys/net/ipv4/neigh/br-lan/gc_stale_time4. 通知系统集成与实践
检测到新设备后,及时通知非常重要。OpenWrt上常见的通知方式有邮件、Telegram Bot和LED指示灯。
邮件通知配置示例:
send_email_notification() { local subject="[OpenWrt] New Device Alert" local body="MAC: $1\nIP: $2\nName: $3\nTime: $(date)" echo -e "$body" | msmtp -a default recipient@example.com }需要先安装msmtp和mailx包,并配置SMTP服务器信息。
Telegram Bot通知更实时:
TELEGRAM_BOT_TOKEN="YOUR_BOT_TOKEN" TELEGRAM_CHAT_ID="YOUR_CHAT_ID" send_telegram_notification() { local message="*New device detected!* MAC: \`$1\` IP: $2 Name: $3 Time: $(date)" curl -s -X POST \ -H 'Content-Type: application/json' \ -d "{\"chat_id\":\"$TELEGRAM_CHAT_ID\",\"text\":\"$message\",\"parse_mode\":\"Markdown\"}" \ "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" >/dev/null }物理LED提示适合快速响应:
blink_led() { local led="/sys/class/leds/tp-link:blue:wps" local original_brightness=$(cat "$led/brightness") for i in 1 2 3; do echo 1 > "$led/brightness" sleep 0.5 echo 0 > "$led/brightness" sleep 0.5 done echo "$original_brightness" > "$led/brightness" }不同路由器LED路径可能不同,需要根据实际硬件调整。
5. 生产环境部署与优化
开发完成后,我们需要将脚本部署为定期运行的监控服务。OpenWrt的Cron是最简单的调度方案:
# 安装必要的软件包 opkg update opkg install cron msmtp curl # 添加每5分钟执行一次的定时任务 (crontab -l 2>/dev/null; echo "*/5 * * * * /usr/bin/device_monitor.sh") | crontab -完整的脚本应该包含错误处理和日志记录:
LOG_FILE="/var/log/device_monitor.log" MAX_LOG_SIZE=1048576 # 1MB log() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE" } # 日志轮转 [ $(stat -c%s "$LOG_FILE" 2>/dev/null || echo 0) -gt $MAX_LOG_SIZE ] && { mv "$LOG_FILE" "$LOG_FILE.old" gzip "$LOG_FILE.old" } # 主程序 main() { log "Starting device monitoring" check_arp_table log "Monitoring completed" } main "$@"对于更复杂的部署,可以考虑将这些功能打包为OpenWrt软件包:
# Makefile示例 include $(TOPDIR)/rules.mk PKG_NAME:=device-monitor PKG_VERSION:=1.0 PKG_RELEASE:=1 include $(INCLUDE_DIR)/package.mk define Package/device-monitor SECTION:=net CATEGORY:=Network TITLE:=Device Monitoring Service DEPENDS:=+msmtp +curl endef define Package/device-monitor/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) ./files/device_monitor.sh $(1)/usr/bin/ $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_BIN) ./files/device_monitor.init $(1)/etc/init.d/device_monitor endef $(eval $(call BuildPackage,device-monitor))6. 高级功能扩展
基础监控实现后,可以考虑添加更多实用功能:
设备分类与友好命名:
# /etc/device_monitor/device_categories.conf aa:bb:cc:*:*:* smartphone "家庭手机" 00:11:22:*:*:* iot "智能家居设备"流量监控集成:
# 获取设备当日流量(需要安装vnstat) get_device_traffic() { local mac=$1 local ip=$(grep "$mac" "$PERSISTENT_STORAGE" | awk '{print $2}' | tail -n1) vnstat --dumpdb | grep "$ip" | awk -F\; '{print $4,$5}' }可疑设备检测:
check_suspicious_device() { local mac=$1 local oui=$(echo "$mac" | cut -d: -f1-3 | tr -d ':') # 检查MAC厂商是否在已知列表中 if ! grep -q "^$oui" "/etc/device_monitor/known_oui.txt"; then send_telegram_notification "Suspicious device detected!\nMAC: $mac" return 1 fi return 0 }7. 可视化与历史数据分析
长期运行的监控系统会产生大量有价值的数据,简单的日志分析就能提供丰富洞察:
# 生成最近一周的设备连接报告 generate_weekly_report() { local start_date=$(date -d "7 days ago" +"%Y-%m-%d") local end_date=$(date +"%Y-%m-%d") echo "Device Connection Report ($start_date to $end_date)" echo "==========================================" awk -v start="$start_date" -v end="$end_date" ' $1 >= start && $1 <= end { if ($2 == "[NEW]") count[$4]++ } END { print "New devices per day:" for (date in count) { print date, count[date] } } ' "$PERSISTENT_STORAGE" }对于更复杂的分析,可以将数据导出到外部系统:
# 导出到InfluxDB进行可视化 export_to_influxdb() { local mac=$1 ip=$2 name=$3 curl -i -XPOST 'http://localhost:8086/write?db=network' \ --data-binary "devices,host=router,mac=$mac,ip=$ip,name=$name status=1 $(date +%s%N)" }这个OpenWrt设备管家项目展示了如何用简单的Shell脚本实现实用的网络监控功能。从最初的设备发现到完整的通知系统,再到高级分析和可视化,每个阶段都能根据实际需求灵活扩展。