N'oublions pas que l'objet de ce chapitre est SNMP et non MRTG...
Les exemples qui suivent sont destinés à montrer comment utiliser SNMP et pas à montrer toutes les finesses de MRTG. Pour ça, vous avez la documentation fournie avec :)
En l'occurrence, il s'agit d'une machine Mandrake 9.0 sur laquelle MRTG 2.9.21 a été installé, comme vu plus haut.
Cette machine est équipée de deux interfaces Ethernet, l'une pour le LAN et l'autre pour le modem-câble. Par dessus, nous trouvons un lien PPP (PPPoE oblige). Ce qui nous donne ceci :
[root@gw1 root]# ifconfig eth0 Lien encap:Ethernet HWaddr 00:20:18:2C:0E:E9 inet adr:192.168.0.250 Bcast:192.168.0.255 Masque:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:2157836 errors:0 dropped:0 overruns:0 frame:0 TX packets:2075111 errors:1 dropped:0 overruns:0 carrier:1 collisions:1840 lg file transmission:100 RX bytes:189444177 (180.6 Mb) TX bytes:691138390 (659.1 Mb) Interruption:10 Adresse de base:0xe000 eth1 Lien encap:Ethernet HWaddr 00:60:8C:50:F3:3E inet adr:192.168.100.250 Bcast:192.168.100.255 Masque:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:2788786 errors:0 dropped:0 overruns:0 frame:0 TX packets:2266845 errors:0 dropped:0 overruns:0 carrier:0 collisions:2250 lg file transmission:100 RX bytes:991395133 (945.4 Mb) TX bytes:228369369 (217.7 Mb) Interruption:3 Adresse de base:0x300 lo Lien encap:Boucle locale inet adr:127.0.0.1 Masque:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:28457 errors:0 dropped:0 overruns:0 frame:0 TX packets:28457 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 lg file transmission:0 RX bytes:3438607 (3.2 Mb) TX bytes:3438607 (3.2 Mb) ppp0 Lien encap:Protocole Point-à-Point inet adr:80.8.146.171 P-t-P:80.8.144.1 Masque:255.255.255.255 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1492 Metric:1 RX packets:401251 errors:0 dropped:0 overruns:0 frame:0 TX packets:523520 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 lg file transmission:3 RX bytes:180973212 (172.5 Mb) TX bytes:41086532 (39.1 Mb)
Nous utilisons, comme d'habitude le script cfgmaker :
[root@gw1 root]# cfgmaker \ > --global 'WorkDir: /var/www/html/mrtg/local' \ > --global 'Language: french' \ > --global 'Options[_]: bits,growright' \ > --ifdesc=descr public@localhost \ > --output /var/www/html/mrtg/local/local.cfg
Seulement voilà, nous rencontrons un problème sur ppp0 :
... ### Interface 4 >> Descr: 'ppp0' | Name: '' | Ip: '80.8.146.171' | Eth: '' ### ### The following interface is commented out because: ### * has a speed of 0 which makes no sense # # Target[localhost_4]: 4:public@localhost: # SetEnv[localhost_4]: MRTG_INT_IP="80.8.146.171" MRTG_INT_DESCR="ppp0" # MaxBytes[localhost_4]: 0 # Title[localhost_4]: ppp0 -- gw1.maison.mrs # PageTop[localhost_4]: <H1>ppp0 -- gw1.maison.mrs</H1> # <TABLE> # <TR><TD>System:</TD> <TD>gw1.maison.mrs in Le local technique</TD></TR> # <TR><TD>Maintainer:</TD> <TD>Root <root@localhost> (configure /etc/snmp/snmp.conf)</TD></TR> # <TR><TD>Description:</TD><TD>ppp0 </TD></TR> # <TR><TD>ifType:</TD> <TD>ppp (23)</TD></TR> # <TR><TD>ifName:</TD> <TD></TD></TR> # <TR><TD>Max Speed:</TD> <TD>0.0 bits/s</TD></TR> # <TR><TD>Ip:</TD> <TD>80.8.146.171 (ca-marseille-19-171.w80-8.abo.wanadoo.fr)</TD></TR> # </TABLE>
SNMP ne donne pas la vitesse maxi de ppp0 et MRTG ne sait pas comment calculer les graphes. Nous allons devoir modifier tout ça à la main. Fort heureusement, ce n'est pas trop compliqué.
La vitesse maxi, nous la connaissons, elle dépend de l'abonnement. Ici, 512 kilo bits par seconde. Nous prendrons 640 kilo bits par seconde, soit 80 kilo octets par seconde. Nous modifions comme suit :
# MaxBytes[localhost_4]: 80000 ... # <TR><TD>Max Speed:</TD> <TD>640.0 Kbits/s</TD></TR>
De plus, laisser l'IP telle qu'elle a été trouvée au moment de la construction du fichier n'a aucun sens puisque cette adresse va changer à chaque nouvelle session PPPoE (sauf si vous disposez d'une IP fixe, bien entendu). Nous modifions donc la dernière ligne du tableau :
# <TR><TD>Ip:</TD> <TD>Adresse dynamique</TD></TR>
Ca devrait suffire à obtenir quelque chose de propre. Bien entendu, il ne faudra pas oublier de dé-commenter toutes les lignes nécessaires.
Il ne nous reste plus qu'à construire la page d'index :
[root@gw1 root]# indexmaker --columns=1 --sort=descr \ > --sidebyside /var/www/html/mrtg/local/local.cfg \ > --output=/var/www/html/mrtg/local/index.html
Il est clair que les graphes représentant ppp0 et eth1 vont être très similaires, puisque ppp0 passe sur eth1. Ce ne sera probablement pas la peine de garder les deux, du moins dans ma configuration simple.
Afficher le trafic réseau, c'est bien, mais SNMP donne bien plus d'informations. Ce serait par exemple intéressant de tracer le graphe de la charge CPU.
Pour y arriver, c'est assez simple, il suffit de lire le tutoriel de net-snmp sur http://net-snmp.sourceforge.net/tutorial/mrtg/ et d'adapter le modèle à notre configuration :
LoadMIBs: /usr/share/snmp/mibs/UCD-SNMP-MIB.txt ### Attention, les trois lignes qui suivent doivent en fait n'en faire qu'une seule Target[gw1.cpusum]:ssCpuRawUser.0&ssCpuRawUser.0:public@localhost + ssCpuRawSystem.0&ssCpuRawSystem.0:public@localhost + ssCpuRawNice.0&ssCpuRawNice.0:public@localhost RouterUptime[gw1.cpusum]: public@localhost MaxBytes[gw1.cpusum]: 100 Title[gw1.cpusum]: CHARGE CPU PageTop[gw1.cpusum]: <H1>Charge Active CPU %</H1> Unscaled[gw1.cpusum]: ymwd ShortLegend[gw1.cpusum]: % YLegend[gw1.cpusum]: Utilisation CPU Legend1[gw1.cpusum]: CPU Actif en % (Charge) Legend2[gw1.cpusum]: Legend3[gw1.cpusum]: Legend4[gw1.cpusum]: LegendI[gw1.cpusum]: Actif LegendO[gw1.cpusum]: Options[gw1.cpusum]: growright,nopercent
Il nous faut aller dans la MIB, chercher les bonnes valeurs. Comme nous utilisons une représentation textuelle des feuilles à lire, il nous faut charger le fichier qui permettra d'interpréter cette représentation. Avec une représentation numérique, ça n'aurait pas été nécessaire.
l'outil snmptranslate va nous servir à repérer la partie de la MIB qui nous intéresse ici. Pour éviter de faire trop long, cherchons tout de suite dans la branche "private" :
[root@gw1 root]# snmptranslate -Tp -IR private
+--private(4)
|
+--enterprises(1)
|
+--ucdavis(2021)
|
+--prTable(2)
| |
| +--prEntry(1)
| | Index: prIndex
| |
| +-- -R-- Integer32 prIndex(1)
| | Range: 0..65535
| +-- -R-- String prNames(2)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- Integer32 prMin(3)
| +-- -R-- Integer32 prMax(4)
| +-- -R-- Integer32 prCount(5)
| +-- -R-- Integer32 prErrorFlag(100)
| +-- -R-- String prErrMessage(101)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -RW- Integer32 prErrFix(102)
| +-- -R-- String prErrFixCmd(103)
| Textual Convention: DisplayString
| Size: 0..255
|
+--memory(4)
| |
| +-- -R-- Integer32 memIndex(1)
| +-- -R-- String memErrorName(2)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- Integer32 memTotalSwap(3)
| +-- -R-- Integer32 memAvailSwap(4)
| +-- -R-- Integer32 memTotalReal(5)
| +-- -R-- Integer32 memAvailReal(6)
| +-- -R-- Integer32 memTotalSwapTXT(7)
| +-- -R-- Integer32 memAvailSwapTXT(8)
| +-- -R-- Integer32 memTotalRealTXT(9)
| +-- -R-- Integer32 memAvailRealTXT(10)
| +-- -R-- Integer32 memTotalFree(11)
| +-- -R-- Integer32 memMinimumSwap(12)
| +-- -R-- Integer32 memShared(13)
| +-- -R-- Integer32 memBuffer(14)
| +-- -R-- Integer32 memCached(15)
| +-- -R-- Integer32 memSwapError(100)
| +-- -R-- String memSwapErrorMsg(101)
| Textual Convention: DisplayString
| Size: 0..255
|
+--extTable(8)
| |
| +--extEntry(1)
| | Index: extIndex
| |
| +-- -R-- Integer32 extIndex(1)
| | Range: 0..65535
| +-- -R-- String extNames(2)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- String extCommand(3)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- Integer32 extResult(100)
| +-- -R-- String extOutput(101)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -RW- Integer32 extErrFix(102)
| +-- -R-- String extErrFixCmd(103)
| Textual Convention: DisplayString
| Size: 0..255
|
+--dskTable(9)
| |
| +--dskEntry(1)
| | Index: dskIndex
| |
| +-- -R-- Integer32 dskIndex(1)
| | Range: 0..65535
| +-- -R-- String dskPath(2)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- String dskDevice(3)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- Integer32 dskMinimum(4)
| +-- -R-- Integer32 dskMinPercent(5)
| +-- -R-- Integer32 dskTotal(6)
| +-- -R-- Integer32 dskAvail(7)
| +-- -R-- Integer32 dskUsed(8)
| +-- -R-- Integer32 dskPercent(9)
| +-- -R-- Integer32 dskPercentNode(10)
| +-- -R-- Integer32 dskErrorFlag(100)
| +-- -R-- String dskErrorMsg(101)
| Textual Convention: DisplayString
| Size: 0..255
|
+--laTable(10)
| |
| +--laEntry(1)
| | Index: laIndex
| |
| +-- -R-- Integer32 laIndex(1)
| | Range: 0..3
| +-- -R-- String laNames(2)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- String laLoad(3)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- String laConfig(4)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- Integer32 laLoadInt(5)
| +-- -R-- Opaque laLoadFloat(6)
| | Textual Convention: Float
| | Size: 7
| +-- -R-- Integer32 laErrorFlag(100)
| +-- -R-- String laErrMessage(101)
| Textual Convention: DisplayString
| Size: 0..255
|
+--systemStats(11)
| |
| +-- -R-- Integer32 ssIndex(1)
| +-- -R-- String ssErrorName(2)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- Integer32 ssSwapIn(3)
| +-- -R-- Integer32 ssSwapOut(4)
| +-- -R-- Integer32 ssIOSent(5)
| +-- -R-- Integer32 ssIOReceive(6)
| +-- -R-- Integer32 ssSysInterrupts(7)
| +-- -R-- Integer32 ssSysContext(8)
| +-- -R-- Integer32 ssCpuUser(9)
| +-- -R-- Integer32 ssCpuSystem(10)
| +-- -R-- Integer32 ssCpuIdle(11)
| +-- -R-- Counter ssCpuRawUser(50)
| +-- -R-- Counter ssCpuRawNice(51)
| +-- -R-- Counter ssCpuRawSystem(52)
| +-- -R-- Counter ssCpuRawIdle(53)
| +-- -R-- Counter ssCpuRawWait(54)
| +-- -R-- Counter ssCpuRawKernel(55)
| +-- -R-- Counter ssCpuRawInterrupt(56)
| +-- -R-- Counter ssIORawSent(57)
| +-- -R-- Counter ssIORawReceived(58)
| +-- -R-- Counter ssRawInterrupts(59)
| +-- -R-- Counter ssRawContexts(60)
|
+--ucdInternal(12)
|
+--ucdExperimental(13)
| |
| +--ucdDlmodMIB(14)
| +-- -R-- Integer32 dlmodNextIndex(1)
| |
| +--dlmodTable(2)
| |
| +--dlmodEntry(1)
| | Index: dlmodIndex
| |
| +-- ---- Integer32 dlmodIndex(1)
| | Range: 1..65535
| +-- -RW- String dlmodName(2)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -RW- String dlmodPath(3)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- String dlmodError(4)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -RW- EnumVal dlmodStatus(5)
| Values: loaded(1), unloaded(2), error(3), load(4), unload(5), create(6), delete(7)
|
+--ucdDemoMIB(14)
| |
| +--ucdDemoMIBObjects(1)
| |
| +--ucdDemoPublic(1)
| |
| +-- -RW- Integer32 ucdDemoResetKeys(1)
| | Range: 0..2147483647
| +-- -RW- String ucdDemoPublicString(2)
| | Size: 0..1024
| +-- -R-- String ucdDemoUserList(3)
| +-- -R-- String ucdDemoPassphrase(4)
|
+--fileTable(15)
| |
| +--fileEntry(1)
| | Index: fileIndex
| |
| +-- -R-- Integer32 fileIndex(1)
| | Range: 0..2147483647
| +-- -R-- String fileName(2)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- Integer32 fileSize(3)
| +-- -R-- Integer32 fileMax(4)
| +-- -R-- EnumVal fileErrorFlag(100)
| | Textual Convention: TruthValue
| | Values: true(1), false(2)
| +-- -R-- String fileErrorMsg(101)
| Textual Convention: DisplayString
| Size: 0..255
|
+--version(100)
| |
| +-- -R-- Integer32 versionIndex(1)
| +-- -R-- String versionTag(2)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- String versionDate(3)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- String versionCDate(4)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- String versionIdent(5)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- String versionConfigureOptions(6)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -RW- Integer32 versionClearCache(10)
| +-- -RW- Integer32 versionUpdateConfig(11)
| +-- -RW- Integer32 versionRestartAgent(12)
| +-- -RW- Integer32 versionDoDebugging(20)
|
+--snmperrs(101)
| |
| +-- -R-- Integer32 snmperrIndex(1)
| +-- -R-- String snmperrNames(2)
| | Textual Convention: DisplayString
| | Size: 0..255
| +-- -R-- Integer32 snmperrErrorFlag(100)
| +-- -R-- String snmperrErrMessage(101)
| Textual Convention: DisplayString
| Size: 0..255
|
+--mrTable(102)
| |
| +--mrEntry(1)
| | Index: mrIndex
| |
| +-- -R-- ObjID mrIndex(1)
| +-- -R-- String mrModuleName(2)
| Textual Convention: DisplayString
| Size: 0..255
|
+--ucdSnmpAgent(250)
| |
| +--hpux9(1)
| |
| +--sunos4(2)
| |
| +--solaris(3)
| |
| +--osf(4)
| |
| +--ultrix(5)
| |
| +--hpux10(6)
| |
| +--netbsd1(7)
| |
| +--freebsd(8)
| |
| +--irix(9)
| |
| +--linux(10)
| |
| +--bsdi(11)
| |
| +--openbsd(12)
| |
| +--unknown(255)
|
+--ucdTraps(251)
|
+--ucdStart(1)
+--ucdShutdown(2)
Comme l'indique le tutoriel NET-SNMP, le système fournit trois compteurs :User, System et Nice. Si l'on souhaite, comme c'est le cas ici, afficher la charge totale, il nous faut additionner ces trois valeurs.
De plus, MRTG trace les graphes par deux sur le même diagramme. Nous traçons ici deux fois le même.
Pour le reste, il faudra regarder de plus près dans le tutoriel de MRTG si l'on souhaite comprendre les options qui sont spécifiées.
Quelques jours plus tard, voici ce que l'on peut observer...
Notez la pointe d'activité autour des 4h du matin, due à l'activitée générée par logrotate.
Là encore SNMP peut nous informer, mais voyons d'abord un peu avec la commande top.
Ici, sur la passerelle, équipée de 128 Mo de RAM :
10:06am up 11 days, 22:04, 4 users, load average: 0,40, 0,24, 0,14
81 processes: 80 sleeping, 1 running, 0 zombie, 0 stopped
CPU states: 64,9% user, 0,8% system, 0,0% nice, 34,1% idle
Mem: 127360K av, 117440K used, 9920K free, 0K shrd, 13752K buff
Swap: 401584K av, 27408K used, 374176K free 24072K cached
Linux a tendance à prendre ses aises dans la RAM disponible (il n'est pas le seul système à le faire). Deux informations sont ici utiles :
la mémoire RAM disponible (9920 Ko),
la mémoire swap disponible (374176 Ko).
Voyons ce que sait nous dire SNMP :
[root@gw1 root]# snmpwalk -v 1 localhost -c public private.enterprises.ucdavis.memory enterprises.ucdavis.memory.memIndex.0 = 0 enterprises.ucdavis.memory.memErrorName.0 = swap enterprises.ucdavis.memory.memTotalSwap.0 = 401584 enterprises.ucdavis.memory.memAvailSwap.0 = 374176 enterprises.ucdavis.memory.memTotalReal.0 = 127360 enterprises.ucdavis.memory.memAvailReal.0 = 8872 enterprises.ucdavis.memory.memTotalFree.0 = 383048 enterprises.ucdavis.memory.memMinimumSwap.0 = 16000 enterprises.ucdavis.memory.memShared.0 = 0 enterprises.ucdavis.memory.memBuffer.0 = 15356 enterprises.ucdavis.memory.memCached.0 = 27312 enterprises.ucdavis.memory.memSwapError.0 = 0 enterprises.ucdavis.memory.memSwapErrorMsg.0 =
Nous pourrions par exemple afficher le swap total et le swap disponible, la mémoire réelle (RAM) totale et la mémoire réelle disponible. Nous allons le faire pour le swap.
LoadMIBs: /usr/share/snmp/mibs/UCD-SNMP-MIB.txt Target[gw1.swap]: memAvailSwap.0&memTotalSwap.0:public@gw1.maison.mrs Options[gw1.swap]: nopercent,growright,gauge,noinfo Title[gw1.swap]: Swap PageTop[gw1.swap]: <H1>Swap.</H1> MaxBytes[gw1.swap]: 1000000000 kMG[gw1.swap]: k,M,G,T,P,X Ylegend[gw1.swap]: Octets ShortLegend[gw1.swap]: octets LegendI[gw1.swap]: Swap dispo LegendO[gw1.swap]: Swap total Legend1[gw1.swap]: Swap disponible Legend2[gw1.swap]: Swap total
Là encore, je vous laisse regarder dans la documentation de MRTG pour les détails de la configuration.
Quelques temps après, nous obtenons ceci (ce qui n'a ici, rien de passionnant, il faut bien le dire).
Juste un mot pour dire que MRTG, non seulement sait exploiter SNMP, mais qu'il peut aussi afficher des informations issues de scripts, ce qui en augmente encore la portée. Bien entendu, nous ne verrons pas comment faire ici.
Faites un "top" et observez les ressources consommées lorsque MRTG se met au travail... C'est une constante de la mesure : tout instrument de mesure perturbe le milieu dans lequel il opère. Aussi je vous conseille, si vous voulez observer quelque chose de relativement fiable d'installer MRTG sur une machine indépendante de celles dont vous voulez auditer les ressources, surtout en termes de CPU et de mémoire.
Dans le cadre d'un petit réseau domestique, SNMP/MRTG pour visualiser le trafic sur la passerelle, c'est déjà le grand luxe.