iStoresOS或OpenWRT带宽监控

14次阅读
没有评论

共计 3854 个字符,预计需要花费 10 分钟才能阅读完成。

前言

近期升级了全屋网络:

  • 入户宽带:联通政企,1000Mbps下行,250Mbps上行
  • 软路由 AC:6口2.5G工控机,6305 CPU,4G内存,iStoresOS 系统
  • 无线路由 AP:中兴晴天be5100Pro+ *2,中兴巡天be3600Pro青云 *1

然而基于openwrt下的流量或带宽监控软件的效果不如人意,我期望的是能够查询家中每个设备的历史带宽数据。

之前的站内文章介绍过:node_exporter 添加自定义指标使用 node_exporter 实现路由器监控

现在只需一个小脚本制作导出器,将指标交由 node_exporter 采集,再绘制Grafana面板即可。

配置

准备工作:

# 安装nlbw
opkg update
opkg install nlbwmon
/etc/init.d/nlbwmon enable
/etc/init.d/nlbwmon start

编写脚本:脚本中较复杂的逻辑是为了获取hostname,ip和mac不能很好的识别到究竟是什么设备。

root@iStoreOS:~# cat /usr/sbin/network_stats.sh
#!/bin/sh

# 输出目录
TEXTFILE_DIR="/tmp/node_exporter"
mkdir -p $TEXTFILE_DIR

# 创建IP到主机名的映射
create_hostname_map() {
    local map_file="/tmp/ip_hostname_map"
    > "$map_file"

    # 1. 从DHCP租约获取
    while IFS=' ' read -r timestamp mac ip hostname clientid; do
        [ -z "$timestamp" ] && continue

        # 处理无效主机名
        case "$hostname" in
            ""|"*"|"0.db")
                echo "$ip:none" >> "$map_file"
                ;;
            *)
                echo "$ip:$hostname" >> "$map_file"
                ;;
        esac
    done < /tmp/dhcp.leases 2>/dev/null

    # 2. 从UCI静态DHCP配置获取
    for section in $(uci show dhcp 2>/dev/null | grep "=host" | cut -d. -f2 | cut -d= -f1); do
        local name=$(uci get dhcp.$section.name 2>/dev/null)
        local ip=$(uci get dhcp.$section.ip 2>/dev/null)
        if [ -n "$name" ] && [ -n "$ip" ] && [ "$name" != "*" ]; then
            echo "$ip:$name" >> "$map_file"
        fi
    done

    # 去重,保留第一个找到的主机名
    sort -u "$map_file" -o "$map_file"
}

# 根据IP获取主机名
get_hostname() {
    local ip="$1"
    local map_file="/tmp/ip_hostname_map"

    if [ ! -f "$map_file" ]; then
        create_hostname_map
    fi

    local hostname=$(grep "^$ip:" "$map_file" | cut -d: -f2 | head -1)
    echo "${hostname:-none}"
}

# 清理主机名字符串
clean_hostname() {
    local hostname="$1"
    echo "$hostname" | sed 's/[^a-zA-Z0-9._-]/_/g'
}

# 获取接口总流量作为补充
get_interface_stats() {
    local interface="br-lan"

    if [ -f /proc/net/dev ]; then
        awk -v iface="$interface:" '
        $1 == iface {
            rx_bytes = $2
            tx_bytes = $10
            print rx_bytes ":" tx_bytes
            exit
        }' /proc/net/dev
    else
        echo "0:0"
    fi
}

# 重新创建主机名映射
create_hostname_map

# 生成Prometheus指标
{
    echo "# HELP openwrt_device_rx_bytes Device received bytes"
    echo "# TYPE openwrt_device_rx_bytes counter"
    echo "# HELP openwrt_device_tx_bytes Device transmitted bytes"
    echo "# TYPE openwrt_device_tx_bytes counter"

    # 使用nlbw获取设备流量统计,只处理192.168.2.*的IP
    nlbw -c csv -g ip | tail -n +2 | while IFS=$'\t' read -r ip conns rx_bytes rx_pkts tx_bytes tx_pkts; do
        # 去除引号
        ip=$(echo "$ip" | sed 's/"//g')
        rx_bytes=$(echo "$rx_bytes" | sed 's/"//g')
        tx_bytes=$(echo "$tx_bytes" | sed 's/"//g')

        # 只处理192.168.2.*的IP
        case "$ip" in
            192.168.2.*)
                # 从ARP表获取MAC地址
                mac=$(awk -v target_ip="$ip" '$1 == target_ip && $4 != "00:00:00:00:00:00" {print $4; exit}' /proc/net/arp)
                [ -z "$mac" ] && mac="unknown"

                raw_hostname=$(get_hostname "$ip")
                hostname=$(clean_hostname "$raw_hostname")

                echo "openwrt_device_rx_bytes{ip=\"$ip\",hostname=\"$hostname\",mac=\"$mac\"} $rx_bytes"
                echo "openwrt_device_tx_bytes{ip=\"$ip\",hostname=\"$hostname\",mac=\"$mac\"} $tx_bytes"
                ;;
        esac
    done

    # 添加接口总流量作为参考
    interface_stats=$(get_interface_stats)
    interface_rx=$(echo "$interface_stats" | cut -d: -f1)
    interface_tx=$(echo "$interface_stats" | cut -d: -f2)

    echo "# HELP openwrt_interface_rx_bytes Interface received bytes"
    echo "# TYPE openwrt_interface_rx_bytes counter"
    echo "# HELP openwrt_interface_tx_bytes Interface transmitted bytes"
    echo "# TYPE openwrt_interface_tx_bytes counter"
    echo "openwrt_interface_rx_bytes{interface=\"br-lan\"} $interface_rx"
    echo "openwrt_interface_tx_bytes{interface=\"br-lan\"} $interface_tx"

} > $TEXTFILE_DIR/network_stats.prom

配置计划任务:

* * * * * /bin/bash /usr/sbin/network_stats.sh 2>&1 >/dev/null

修改node_exporter的启动参数,定义获取自定义指标的路径:

root@iStoreOS:~# cat /etc/init.d/node_exporter 
#!/bin/sh /etc/rc.common

START=99
STOP=10
USE_PROCD=1

start_service() { 
    procd_open_instance
    procd_set_param command "/usr/sbin/node_exporter" \
        "--collector.textfile.directory=/tmp/node_exporter"
    procd_set_param respawn
    procd_close_instance
} 

stop_service() { 
    procd_send_signal TERM node_exporter
} 

restart_service() { 
    stop_service "$@" 
    start_service "$@" 
}

重启node_exporter

/etc/init.d/node_exporter restart

绘制Grafana面板:

iStoresOS或OpenWRT带宽监控

Promql如下:

# 入带宽
sum by (hostname, ip, mac) (rate(openwrt_device_rx_bytes[1m]))

# 出带宽
sum by (hostname, ip, mac) (rate(openwrt_device_tx_bytes[1m]))

本文介绍了在iStoresOS或OpenWRT系统上实现带宽监控的方法。文章中详细描述了如何通过安装nlbwmon工具和编写定制脚本来采集各设备的网络流量数据,然后利用node_exporter将这些指标导出,最后通过Grafana生成监控面板,实现对家中每个设备历史带宽数据的监控。

引用链接

正文完
 
pengyinwei
版权声明:本站原创文章,由 pengyinwei 2026-04-14发表,共计3854字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处:https://www.opshub.cn
评论(没有评论)