GNU/Linux - Comment monitorer l'utilisation de la bande passante d'un lien réseau avec SNMP et Munin

Munin logo Munin graph

Que se soit pour un lien internet ou local il est souvent utile d'avoir une représentation graphique à travers le temps de l'utilisation de la bande passante.

Nous allons voir ici comment procéder en utilisant SNMP et le logiciel Munin.

D'après wikipedia : Munin est un logiciel libre et gratuit de surveillance système, réseau en présentant ses résultats sous forme de graphiques.

Le logiciel propose ses propres plugins et outils (pour surveiller : le cpu, la mémoire, les interfaces réseau, les disques…)

Malheuresement je n'ai pas trouvé le plugin qui répondait à mes besoins, j'ai donc décidé de développer le mien.

Est ce que je vais le partager gratuitement ici? C'est ce que vous allez découvrir en lisant cet article…

Architecture Réseau

Dans mon exemple je monitorerais le lien WAN du routeur.

Munin | Architecture munin pour surveiller la bande passante WAN via SNMP
Monitorer l'utilisation de la bande passante avec Munin.

SNMP

Intro

SNMP pour Simple Network Management Protocol est un protocole standard internet dont le but est de collecter et d'organiser les informations de périphériques sur des réseaux IP, il donne également la possibilité de piloter ces périphériques. Généralement les équipements qui supportent SNMP sont : les routeurs, les commutateurs, les serveurs et postes de travail, les imprimantes…

Pour rappel SNMP peut être utilisé de plusieurs façons : snmp get pour récupérer une information, snmp set pour piloter un périphérique et snmp trap qui permet à un agent (le périphérique) d'envoyer des notifications à un manager (le serveur de supervision).

Nous utiliserons ici snmp get avec la version 3 du protocole SNMP car elle permet une sécurité cryptographique.

Nous configurerons donc le routeur en SNMPv3 avec AES pour le chiffrement et SHA1 pour l'intégrité.

MIB

  • Les données SNMP sont stockées à l'intérieur d'un arbre appelé MIB. Ici nous voulons récupérer les informations stockées dans la branche interfaces réseau, nous devons donc intérroger l'oid (1.3.6.1.2.12) :
SNMP | Arbre MIB pour accéder au interfaces réseau
MIB tree.

Applications Net-SNMP

Il existe de nombreux outils pour gérer le protocole snmp. J'utiliserai ici les outils net-snmp parce que je fais ce que je veux.

  • Net-SNMP nous donne accès à de nombreux outils en ligne de commande :
    • snmpwalk : pour récupérer les valeurs contenues dans une branche. Il utilise les requètes SNMP GETNEXT
    • snmpget : pour dialoguer avec un périphérique réseau en utilisant les requètes SNMP GET
    • etc…

Installation

  • Installation sur Debian :
root@host:~# apt update && apt-get install snmp

Utilisation

  • Options :
    • -On : Affiche les OID numériquements
    • -Oe : Supprime les étiquettes symboliques des valeurs d'énumération
    • -OQ : Supprime l'information sur le type lors de l'affichage des valeurs de type varbind
    • -Os : Affiche le nom de l'objet MIB (plus une instance ou d'autres sous-identifiants)
    • -t 10 : Spécifie le délai d'attente en secondes entre les tentatives.
    • -l authPriv : Définir le niveau de sécurité pour les messages SNMPv3
    • -v 3 : Spécifie l'utilisation de la version 3 du protocole SNMP
snmpwalk
  • snmpwalk pour récupérer toutes les informations contenues dans une branche :
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

Comme on peut le constater il est difficile d'identifier les informations qui nous interessent. Afin de traduire les informations reçues de façon compréhensible nous aurons besoin d'installer le paquet snmp-mibs-downloader qui contient les fichiers MIB.

  • Éditer le fichier /etc/apt/sources.list et ajouter non-free :
deb http://deb.debian.org/debian/ bullseye main non-free
deb-src http://deb.debian.org/debian/ bullseye main non-free
  • Installer le paquet snmp-mibs-downloader :
root@host:~# apt update && apt install snmp-mibs-downloader
  • Éditer le fichier de configuration /etc/snmp/snmp.conf :
# 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
  • En exécutant snmpwalk de nouveau, nous pouvons voir que les informtions récupérées sont plus parlantes :
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

Nous pouvons ici dire que nous allons devoir travailler avec les oid ifInOctets.2 (1.3.6.1.2.1.2.2.1.10.2) et ifOutOctets.2 (1.3.6.1.2.1.2.2.1.16.2).

snmpget
  • Exemple d'utilisation de snmpget :
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

Munin

Installation

Serveur web Apache

root@host:~# apt update && apt install apache2 libapache2-mod-fcgid
root@host:~# a2enmod fcgid

Munin

  • Installer Munin :
root@host:~# apt update && apt install munin munin-node munin-plugins-extra
  • Activer la configuration apache :
root@host:~# a2enconf munin
  • Éditer le fichier de configuration /etc/apache2/conf-enabled/munin.conf :
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
  • Redémarrer le service apache :
root@host:~# systemctl restart apache2

Bandwidth Plugin

  • Installation des prérequis :
root@host:~# apt update && apt install bc snmp
  • Créer le fichier /usr/share/munin/plugins/bandwidth en prenant soin de ⚠️ modifier les variables suivantes ⚠️ :
    • AUTH_PASSWORD : mot de passe SHA
    • ENCRYPT_PASSWORD : mot de passe AES
    • HOST : adresse ip du routeur
    • OID_UPLOAD : oid du lien pour l'upload
    • OID_DOWNLOAD : oid du lien pour le download
#!/bin/sh
# Role : script munin pour relever les valeurs d'upload et de download d'une interface
# Auteur : http://shebangthedolphins.net/
# 1.0 premiere version


AUTH_PASSWORD="AUTH_PASSWORD"
ENCRYPT_PASSWORD="ENCRYPT_PASSWORD"
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
  • Ajouter les droits en exécution :
root@host:~# chmod +x /usr/share/munin/plugins/bandwidth
  • Créer un lien symbolique :
root@host:~# ln -s /usr/share/munin/plugins/bandwidth /etc/munin/plugins/bandwidth
  • Éditer le fichier /etc/munin/plugin-conf.d/munin-node et ajouter :
[bandwidth]
user root
  • Redémarrer le service munin-node :
root@host:~# systemctl restart munin-node

L'interface Web

  • Prendre un ☕, patienter 5 minutes, puis se connecter au serveur Munin à l'adresse http://192.168.1.100/munin/, enfin cliquer sur localdomain, puis Bandwidth :
Munin | Main menu
  • Les graphs Bandwidth devraient apparatre :
Munin | Bandwidth graphs

Commandes utiles

  • Exécuter un plugin manuellement :
root@host:~# munin-run bandwidth
  • Afficher l'état des plugins :
root@host:~# /usr/sbin/munin-node-configure | grep bandwidth
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Contact :