Whether it is for the internet or locals links it can be interesting to have a graphical representation of the bandwidth usage over time.
We will see here how to proceed using the SNMP protocol coupled with Munin.
From wikipedia : Munin is a free and open-source computer system monitoring, network monitoring and infrastructure monitoring software application.
It comes with its own plugins and tools (to monitor : cpu, memory, network interfaces, disks…)
Unfortunately I couldn't find plugin that met my needs, so I decided do develop my own one.
Am I willing to share it here for free? This is what you'll find out by reading this article…
In my example I want to monitor the WAN link of my router.
Simple Network Management Protocol is an Internet Standard protocol for collecting and organizing information about managed devices on IP networks and for modifying that information to change device behaviour. Devices that typically support SNMP include cable modems, routers, switches, servers, workstations, printers, and more.
As a reminder we can use SNMP by many ways : snmp get to retrieve information, snmp set to drive a device and snmp trap which allow an agent to send notifications to a manager
We will use snmp get here with SNMPv3 which is the most secure version of the protocol which allow cryptographic security.
So I will configure my router to use SNMPv3 with AES for encryption protocol and SHA1 as authentication protocol.
There are many tools to interact with the snmp protocol. I personally use the net-snmp tools.
root@host:~# apt update && apt-get install snmp
root@host:~# snmpwalk -OQse -v 3 -t 10 -l AuthPriv -u USER -a SHA1 -A AUTH_PASSWORD -x AES -X ENCRYPT_PASSWORD 192.168.1.254 1.3.6.1.2.1.2 iso.3.6.1.2.1.2.2.1.2.1 = "LAN" iso.3.6.1.2.1.2.2.1.2.2 = "WAN" iso.3.6.1.2.1.2.2.1.2.7 = "Resrved" […] iso.3.6.1.2.1.2.2.1.10.1 = 993231759 iso.3.6.1.2.1.2.2.1.10.2 = 44681268 iso.3.6.1.2.1.2.2.1.11.1 = 21739 iso.3.6.1.2.1.2.2.1.12.1 = 657070 […] iso.3.6.1.2.1.2.2.1.15.1 = 239874 iso.3.6.1.2.1.2.2.1.16.1 = 3744831080 iso.3.6.1.2.1.2.2.1.16.2 = 671461169 […] iso.3.6.1.2.1.2.2.1.17.1 = 12892 iso.3.6.1.2.1.2.2.1.17.2 = 47095
As we can see it is hard to know which informations we have to process. To translate received information to human readable text we need to install snmp-mibs-downloader package which contain MIB files.
deb http://deb.debian.org/debian/ bullseye main non-free deb-src http://deb.debian.org/debian/ bullseye main non-free
root@host:~# apt update && apt install snmp-mibs-downloader
# As the snmp packages come without MIB files due to license reasons, loading # of MIBs is disabled by default. If you added the MIBs you can reenable # loading them by commenting out the following line. #mibs : mibs ALL # If you want to globally change where snmp libraries, commands and daemons # look for MIBS, change the line below. Note you can set this for individual # tools with the -M option or MIBDIRS environment variable. # # mibdirs /usr/share/snmp/mibs:/usr/share/snmp/mibs/iana:/usr/share/snmp/mibs/ietf
root@host:~# snmpwalk -OQse -v 3 -t 10 -l AuthPriv -u USER -a SHA1 -A AUTH_PASSWORD -x AES -X ENCRYPT_PASSWORD 192.168.1.254 1.3.6.1.2.1.2 ifDescr.1 = LAN ifDescr.2 = WAN ifDescr.7 = Resrved […] ifInOctets.1 = 1247598139 ifInOctets.2 = 4105313719 ifInUcastPkts.1 = 4751 ifInNUcastPkts.1 = 146063 […] ifInUnknownProtos.1 = 61144 ifOutOctets.1 = 3285593712 ifOutOctets.2 = 2913538784 […] ifOutUcastPkts.1 = 2037 ifOutUcastPkts.2 = 13573
Now we can say that we will have to work with ifInOctets.2 (1.3.6.1.2.1.2.2.1.10.2) and ifOutOctets.2 (1.3.6.1.2.1.2.2.1.16.2).
root@host:~# snmpget -OQse -v 3 -t 10 -l AuthPriv -u USER -a SHA1 -A AUTH_PASSWORD -x AES -X ENCRYPT_PASSWORD 192.168.1.254 1.3.6.1.2.1.2.2.1.10.1 ifInOctets.1 = 854863486
root@host:~# apt update && apt install apache2 libapache2-mod-fcgid
root@host:~# a2enmod fcgid
root@host:~# apt update && apt install munin munin-node munin-plugins-extra
root@host:~# a2enconf munin
ScriptAlias /munin-cgi/munin-cgi-graph /usr/lib/munin/cgi/munin-cgi-graph Alias /munin/static/ /var/cache/munin/www/static/ <Directory /var/cache/munin/www> Require all granted Options None </Directory> <Directory /usr/lib/munin/cgi> Require all granted <IfModule mod_fcgid.c> SetHandler fcgid-script </IfModule> <IfModule !mod_fcgid.c> SetHandler cgi-script </IfModule> </Directory> # ***** SETTINGS FOR CGI/CRON STRATEGIES ***** # pick _one_ of the following lines depending on your "html_strategy" # html_strategy: cron (default) Alias /munin /var/cache/munin/www
root@host:~# systemctl restart apache2
root@host:~# apt update && apt install bc snmp
#!/bin/sh # Role : munin script to collect upload and download values of an interface # Autor : http://shebangthedolphins.net/ # 1.0 first version AUTH_PASSWORD="AUTH_PASSWORD" ENCRYPT_PASSWORD="ENCRYPT_PASSWORD" USER="user" HOST="192.168.1.254" OID_UPLOAD="1.3.6.1.2.1.2.2.1.16.2" OID_DOWNLOAD="1.3.6.1.2.1.2.2.1.10.2" output_config() { echo "graph_category network" echo "graph_title Bandwidth" echo "plugins.label WAN Bandwidth" echo "graph_vlabel bytes" echo "wan1_upload.label upload" echo "wan1_download.label download" } output_values() { printf "wan1_upload.value %d\n" $(snmp_wan_upload) & printf "wan1_download.value %d\n" $(snmp_wan_download) wait } snmp_wan_upload() { TimeEnd_UL=$(date +"%s") #epoch time if [ ! -f /tmp/wan_upload ]; then sleep 5s; snmpget -OQne -v 3 -t 10 -l AuthPriv -u "$USER" -a SHA1 -A "$AUTH_PASSWORD" -x AES -X "$ENCRYPT_PASSWORD" "$HOST" "$OID_UPLOAD" | awk '{ print $3 }' > /tmp/wan_upload; sleep 5s; TimeEnd_UL=$(date +"%s"); fi #at first launch creation of the /tmp/wan_upload file ifInOctets_WAN1=$(cat /tmp/wan_upload) #value in bytes of the last reading (5 minutes ago) TimeStart_UL=$(date -r /tmp/wan_upload +"%s") #epoch time of the modification of the file /tmp/wan_upload ifInOctets_WAN2=$(snmpget -OQne -v 3 -t 10 -l AuthPriv -u "$USER" -a SHA1 -A $AUTH_PASSWORD -x AES -X $ENCRYPT_PASSWORD "$HOST" "$OID_UPLOAD" | awk '{ print $3 }' | tee /tmp/wan_upload) #current reading (+5 minutes compared to the previous reading) Time_UL=$(($TimeEnd_UL-$TimeStart_UL)) #difference in seconds between the current epoch time and that of the /tmp/wan_upload file Result_UL=$(echo "scale=0;($ifInOctets_WAN2 - $ifInOctets_WAN1)/($Time_UL)" | bc) #difference in bytes between the -5min record and the current record if [ $Result_UL -gt 0 ]; then #if difference is less than 0 then normal operation echo "scale=0;($ifInOctets_WAN2 - $ifInOctets_WAN1)/($Time_UL)" | bc else #if difference is less than 0 then the counter has been reset after the value 4294967295, the counter is reset to 0 echo "scale=0;($ifInOctets_WAN2 - $ifInOctets_WAN1 + 4294967295)/($Time_UL)" | bc fi } snmp_wan_download() { TimeEnd_DL=$(date +"%s") #epoch time if [ ! -f /tmp/wan_download ]; then sleep 5s; snmpget -OQne -v 3 -t 10 -l AuthPriv -u "$USER" -a SHA1 -A "$AUTH_PASSWORD" -x AES -X "$ENCRYPT_PASSWORD" "$HOST" "$OID_DOWNLOAD" | awk '{ print $3 }' > /tmp/wan_download; sleep 5s; TimeEnd_DL=$(date +"%s"); fi #at first launch creation of the file /tmp/wan_download ifOutOctets_WAN1=$(cat /tmp/wan_download) #value in bytes of the last reading (5 minutes ago) TimeStart_DL=$(date -r /tmp/wan_download +"%s") #epoch time of the modification of the file /tmp/wan_download ifOutOctets_WAN2=$(snmpget -OQne -v 3 -t 10 -l AuthPriv -u "$USER" -a SHA1 -A "$AUTH_PASSWORD" -x AES -X "$ENCRYPT_PASSWORD" "$HOST" "$OID_DOWNLOAD" | awk '{ print $3 }' | tee /tmp/wan_download) #current reading (+5 minutes compared to the previous reading) Time_DL=$(($TimeEnd_DL-$TimeStart_DL)) #difference in seconds between the current epoch time and that of the /tmp/wan_download file Result_DL=$(echo "scale=0;($ifOutOctets_WAN2 - $ifOutOctets_WAN1)/($Time_DL)" | bc) #difference in bytes between the -5min record and the current record if [ $Result_DL -gt 0 ]; then echo "scale=0;($ifOutOctets_WAN2 - $ifOutOctets_WAN1)/($Time_DL)" | bc else echo "scale=0;($ifOutOctets_WAN2 - $ifOutOctets_WAN1 + 4294967295)/($Time_DL)" | bc fi } output_usage() { printf >&2 "%s - munin plugin to graph bandwith links\n" ${0##*/} printf >&2 "Usage: %s [config]\n" ${0##*/} } case $# in 0) output_values ;; 1) case $1 in config) output_config ;; *) output_usage exit 1 ;; esac ;; *) output_usage exit 1 ;; esac
root@host:~# chmod +x /usr/share/munin/plugins/bandwidth
root@host:~# ln -s /usr/share/munin/plugins/bandwidth /etc/munin/plugins/bandwidth
[bandwidth] user root
root@host:~# systemctl restart munin-node
root@host:~# munin-run bandwidth
root@host:~# /usr/sbin/munin-node-configure | grep bandwidth
Contact :