====== Monitoraggio SNMP ====== ===== Introduzione ===== L'architettura SNMP è di tipo client server. Il server viene interrogato o impostato dal client con i comandi GET, GET-NEXT, GET-RESPONSE e SET. Il server può informare il client con il comando TRAP. Gli attributi monitorabili sono organizzati in un MIB (Management Information Base) che ha una struttora ad albero. Ogni oggetto ho un identificativo (OID) che indica anche la sua gerarchia (es: "1.1.0") e pure una label descrittiva (es: "system.sysDescr.0"). Quindi si puo' usare indifferentemente una di queste sintassi per riferirsi ad un attributo: 1.1.0 system.sysDescr.0 1.sysDescr.0 La gerarchia (albero) dei simboli e i loro nomi sono codificati nel RFC1066 MIB. La radice degli oggetti - se non indicata - è per convenzione ''**.iso.org.dod.internet.mgmt.mib.**'' cioè in numeri ''**.1.3.6.1.2.1.**''. Vedi a proposito man ''**variables(5snmp)**''. Nota che i nomi dei simboli distinguono le maiuscole/minuscole a differenza di quello che dice la man page. Per convertire i nomi degli attributi dal formato testuale a quello numerico: # snmptranslate -On IF-MIB::ifName.2 .1.3.6.1.2.1.31.1.1.1.1.2 # snmptranslate -m ALL .1.3.6.1.2.1.31.1.1.1.1.2 IF-MIB::ifName.2 # snmptranslate -Of IF-MIB::ifName.2 .iso.org.dod.internet.mgmt.mib-2.ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifName.2 # snmpget -v1 -c public 127.0.0.1 IF-MIB::ifName.2 IF-MIB::ifName.2 = STRING: eth0 # snmpget -v1 -c public 127.0.0.1 1.3.6.1.2.1.31.1.1.1.1.2 IF-MIB::ifName.2 = STRING: eth0 # snmptranslate -Td IF-MIB::ifName IF-MIB::ifName ifName OBJECT-TYPE -- FROM IF-MIB -- TEXTUAL CONVENTION DisplayString SYNTAX OCTET STRING (0..255) DISPLAY-HINT "255a" MAX-ACCESS read-only STATUS current DESCRIPTION "The textual name of the interface. The value of this object should be the name of the interface as assigned by the local device and should be suitable for use in commands entered at the device's `console'. This might be a text ... Nota che snmptranslate e' in grado anche di cercare espressioni regolari in tutta la gerarchia MIB, cosi' che trovare un certo OID diventa piu' facile: # snmptranslate -Ib 'sys.*ime' SNMPv2-MIB::sysORUpTime ===== SNMP ===== Sulla macchina da monitorare deve essere installato il demone SNMP, si installa il pacchetto snmpd. Anche se il firewall blocca l'accesso al demone dall'esterno, conviene fare una configurazione un po' più accorta di ''**/etc/snmp/snmpd.conf**'', vedere man ''**snmpd.conf(5)**''. La configurazione di default di Debian è già particolarmente paranoica, si deve dare accesso almeno in sola lettura a 127.0.0.1 per fare in modo che MRTG possa fare le sue statistiche: aggiunta la riga: com2sec readonly 127.0.0.1 public Impostate anche ''syslocation'' e ''syscontact'' in modo che diano informazioni sensate. Per vedere se funziona si installa il pacchetto snmp (tool client) e si prova ad usare uno dei comandi: snmpwalk -v 1 -c public 127.0.0.1 snmpget -v 1 -c public 127.0.0.1 system.sysDescr.0 snmpnetstat -v 1 -c public -o -n 127.0.0.1 L'interrogazione funziona utilizzando la versione 1 o 2c del protocollo (opzione -v), per la versione 3 sarebbe richiesto impostare altre opzioni tipo la securityName, ecc. Ovviamente si deve conoscere il nome della community ("public" in questo esempio), ed avere i permessi per fare la richiesta. Con snmpwalk si ha l'elenco di tutte le label degli OID interrogabili. Con snmpget si legge il valore dell'attributo. Snmpnetstat presenta alcuni dati relativi alle interfacce di rete in modo più leggibile. La versione più recente del pacchetto Debian binda il demone solo sull'indirizzo 127.0.0.1, per mettersi in ascolto su tutti gli indirizzi IP bisogna togliere tale indirizzo dalla variabile ''**SNMPDOPTS**'' dal file ''**/etc/default/snmpd**''. ==== Controllo del log ==== L'installazione predefinita di Debian Wheezy genera una riga di log per ogni interrogazione SNMP, se pare eccessiva basta modificare il livello di log agendo sulla variabile ''**SNMPDOPTS**'' del file ''**/etc/default/snmpd**'': SNMPDOPTS='-LS0-5d ... In questo caso **S0-5** significa loggare su syslog da ''LOG_EMERG'' to ''LOG_NOTICE'', **d** indica la facility ''LOG_DAEMON''. Vedere ''snmpcmd(1)''. ===== Aggiunta di sensori SNMP ===== Creato uno script per interfacciare snmpd a varie utility di sistema come i sensori della scheda madre, utility per misurare latenza e pacchetti persi (netmonitor), ecc. Poi si aggiungono in ''**/etc/snmp/snmpd.conf**'' delle righe del tipo: exec sensors1 /usr/local/sbin/snmpd-helper fan exec sensors2 /usr/local/sbin/snmpd-helper cpu A questo punto il sensore è leggibile con: snmpwalk -v1 -c public 127.0.0.1 UCD-SNMP-MIB::extOutput.1 Come si vede il valore è disponibile sotto un MIB differente, la radice in questo caso è .1.3.6.1.4.1.2021.8.1. (UCD-SNMP-MIB::). Con la nuova sintassi di **''snmpd.conf''** (introdotta con la versione 5.2.x e quindi da preferire ad esempio con ''snmpd'' 5.4.3) la direttiva **''exec''** viene deprecata, al suo posto si usa **''extend''**: extend sensors_cpu_fan /usr/local/sbin/snmpd-helper fan extend sensors_sys_fan /usr/local/sbin/snmpd-helper fan2 in questo caso l'OID da leggere è: snmpwalk -v1 -c public 127.0.0.1 'NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."sensors_cpu_fan"' Il vantaggio è che l'OID viene indirizzato non con l'indice numerico (che dipende dall'ordine in cui è definito nel file di configurazione), ma da una etichetta. Notare l'uso degli apici nel comando da shell, in quanto le **doppie virgolette** fanno parte a tutti gli effetti del nome dell'OID. ===== Esempi configurazione ===== Per comodità si può suddividere la configurazione in diversi file ed includerli nel file **''/etc/mrtg/mrtg.cfg''**: #LoadMIBs: /usr/share/snmp/mibs/UCD-SNMP-MIB.txt LoadMIBs: /usr/share/mibs/netsnmp/UCD-SNMP-MIB WorkDir: /var/www/mrtg Include: eth0 Include: cpu1 Include: fan1 Include: free ### Interface eth0 Target[eth0]: \eth0:public@localhost: Title[eth0]: Traffic for interface eth0 PageTop[eth0]:

Traffic for interface eth0

Options[eth0]: growright,bits,noinfo,unknaszero MaxBytes[eth0]: 13107200 #Unscaled[eth0]: dwm
### CPU Load Target[cpu1]: ( ssCpuRawUser.0&ssCpuRawUser.0:public@localhost + ssCpuRawSystem.0&ssCpuRawSystem.0:public@localhost + ssCpuRawNice.0&ssCpuRawNice.0:public@localhost ) / 2 Title[cpu1]: CPU LOAD PageTop[cpu1]:

Active CPU Load %

Colours[cpu1]: ORANGE#ff5c00,BLACK#000000,DARK GREEN#006600,VIOLET#ff00ff MaxBytes[cpu1]: 100 Unscaled[cpu1]: dwmy ShortLegend[cpu1]: % YLegend[cpu1]: CPU Utilization Legend1[cpu1]: Active CPU in % (Load) Legend2[cpu1]: Legend3[cpu1]: Legend4[cpu1]: LegendI[cpu1]: Load:  LegendO[cpu1]: #Options[cpu1]: noo,growright,nopercent,noinfo,unknaszero Options[cpu1]: growright,nopercent,noinfo,unknaszero
**NOTA**: Il carico della CPU deve essere diviso per il **numero di core** presenti (vedere con ''cat /proc/cpuinfo'', 2 nell'esempio sopra). Il contatore SNMP infatti fornisce il numero di ticks di CPU spesi nell'eseguire i processi, ci sono 100 ticks per CPU al secondo. ### CPU Fan Target[fan1]: .1.3.6.1.4.1.2021.8.1.101.1&.1.3.6.1.4.1.2021.8.1.101.2:public@localhost Title[fan1]: CPU Fan PageTop[fan1]:

CPU and System Fans

Options[fan1]: gauge,growright,nopercent,noinfo,unknaszero,integer Colours[fan1]: CYAN#92D5FF,BLUE#1000ff,DARK GREEN#006600,VIOLET#ff00ff YLegend[fan1]: RPM ShortLegend[fan1]: rpm MaxBytes[fan1]: 5000 Unscaled[fan1]: dwmy kMG[fan1]: Legend1[fan1]: CPU Fan RPM Legend2[fan1]: System Fan RPM Legend3[fan1]: Legend4[fan1]: LegendI[fan1]: CPU Fan:  LegendO[fan1]: Sys Fan: 
### Free memory Target[free]: .1.3.6.1.4.1.2021.4.4.0&.1.3.6.1.4.1.2021.4.6.0:public@localhost Title[free]: Free memory PageTop[free]:

Free memory

Options[free]: gauge,growright,nopercent,noinfo,unknaszero Colours[free]: LIGHT GREEN#73d290,GREEN#0c680c,DARK GREEN#006600,VIOLET#ff00ff MaxBytes1[free]: 1000000 MaxBytes2[free]: 2000000 kMG[free]: k,M,G,T,P,X YLegend[free]: bytes ShortLegend[free]: bytes Legend1[free]: Free swap memory, in bytes Legend2[free]: Free memory, not including swap, in bytes LegendI[free]: Free swap:  LegendO[free]: Free memory: 
The follogin example is for disk free graph. You need to adjust the **''MaxBytes''** to the size of your partition: Target[df_md0]: `/usr/local/bin/mrtg-diskfree /dev/md0` Title[df_md0]: Disk Usage /dev/md0 Unscaled[df_md0]: dwym MaxBytes[df_md0]: 4814824 PageTop[df_md0]:

Disk Usage /dev/md0

kmg[df_md0]: KB,MB,GB Colours[df_md0]: BLUE#0000ff,VIOLET#ff00ff,RED#ff0000,DARK BLUE#00007f LegendI[df_md0]: Used Disk Space LegendO[df_md0]: Total Disk Space Legend1[df_md0]: Used Disk Space Legend2[df_md0]: Total Disk Space YLegend[df_md0]: bytes ShortLegend[df_md0]: bytes Options[df_md0]: gauge, growright, noinfo
you also need the following script mrtg-diskfree: #!/bin/sh # It assumes that the command output(df -klP) looks like this: # # Filesystem 1K-blocks Used Available Use% Mounted on # /dev/md0 4814824 781300 3788944 18% / # tmpfs 1037648 0 1037648 0% /lib/init/rw # udev 10240 64 10176 1% /dev # tmpfs 1037648 4 1037644 1% /dev/shm # /dev/md2 148483184 208412 148274772 1% /home DEV="$1" if [ ! -b "$DEV" ]; then echo "Usage: $(basename $0) " exit 1 fi df="$(df -klP | egrep "^${DEV}\b")" size="$(echo $df | awk '{print $2}')" used="$(echo $df | awk '{print $3}')" echo $used echo $size This graph displays the **packet loss** percentage with a remote host. It requires the **''mrtg-ping-probe''** script, available also as a Debian package: ### Packet loss Target[loss_192.168.2.2]: `/usr/bin/mrtg-ping-probe -p loss/loss 217.58.146.19` Title[loss_192.168.2.2]: Packet loss 192.168.2.2 PageTop[loss_192.168.2.2]:

Packet loss 192.168.2.2

Options[loss_192.168.2.2]: noo,gauge,growright,nopercent,noinfo,unknaszero,withzeroes Colours[loss_192.168.2.2]: RED#d60000,BLUE#1000ff,DARK GREEN#006600,VIOLET#ff00ff MaxBytes[loss_192.168.2.2]: 100 Unscaled[loss_192.168.2.2]: dwmy YLegend[loss_192.168.2.2]: Packet loss % ShortLegend[loss_192.168.2.2]: % Legend1[loss_192.168.2.2]: Packet loss in % Legend2[loss_192.168.2.2]: LegendI[loss_192.168.2.2]: loss  LegendO[loss_192.168.2.2]:
This graph displays the packet **max/min round-trip time** (ping) with a remote host. It requires the **''mrtg-ping-probe''** script, available also as a Debian package: ### Ping Target[ping_88.149.128.3]: `/usr/bin/mrtg-ping-probe -p avg/max 88.149.128.3` Title[ping_88.149.128.3]: Ping 88.149.128.3 (ping.ngi.it) PageTop[ping_88.149.128.3]:

Ping 88.149.128.3 (ping.ngi.it)

Options[ping_88.149.128.3]: gauge,growright,nopercent,noinfo Colours[ping_88.149.128.3]: YELLOW#d37d00,RED#910000,YELLOW#d37d00,RED#910000 MaxBytes[ping_88.149.128.3]: 3000 YLegend[ping_88.149.128.3]: Ping time (ms) ShortLegend[ping_88.149.128.3]: ms Legend1[ping_88.149.128.3]: Average Round Trip Time in ms Legend2[ping_88.149.128.3]: Maximum Round Trip Time in ms LegendI[ping_88.149.128.3]:  Avg: LegendO[ping_88.149.128.3]:  Max:
Temperature graph using **lmsensors**. Verify that the version of Net-SNMP on the target system was compiled with the lmSensors extension by running **''snmpd -Dmib_init''** and looking through the output for the ''lmSensors'' string. Then you need to discover the MIB of your sensor: snmpwalk -v2c -c public localhost 1.3.6.1.4.1.2021.13.16 In my case the temperature is multiplied by 1000: ### Sensor temp1 Target[temp1]: iso.3.6.1.4.1.2021.13.16.2.1.3.1&iso.3.6.1.4.1.2021.13.16.2.1.3.1:public@localhost Factor[temp1]: 0.001 YTicsFactor[temp1]: 0.001 Title[temp1]: Temperature temp1 PageTop[temp1]:

Temperature temp1

Options[temp1]: noo,gauge,growright,nopercent,noinfo,unknaszero,withzeroes Colours[temp1]: RED#d60000,BLUE#1000ff,DARK GREEN#006600,VIOLET#ff00ff MaxBytes[temp1]: 150000 Unscaled[temp1]: dwmy YLegend[temp1]: Temp C° ShortLegend[temp1]: C° Legend1[temp1]: Temperature in C° Legend2[temp1]: LegendI[temp1]: Temp C°  LegendO[temp1]:
It seems that MRTG does not support UTF-8 (even version 2.17.4), so the configuration file should be encoded in ISO_8859-1. Special characters used in HTML output should be encoded properly. See this article: [[http://www.eric-a-hall.com/software/cacti-netsnmp-lmsensors/|lmSensors/Net-SNMP Sensor Readings ]]. ===== MIBs e Debian (Squeeze e successive) ===== Vedere il [[https://wiki.debian.org/SNMP|wiki Debian]]. Tradizionalmente i file contenenti i MIBs di [[http://www.ietf.org/|IETF]] e di [[http://www.iana.org/|IANA]] venivano distribuiti con il pacchetto **''libsnmp-base''**, per problemi di licenza questo non è più possibile (dalla versione net-snmp 5.4.2.1~dfsg-1). Tuttavia installando il pacchetto non-free **snmp-mibs-downloader** è possibile scaricare i file in questione, che verranno salvati nella directory **''/var/lib/mibs/''**. Per utilizzare i file scaricati bisogna commentare una riga nel file ''/etc/snmp/snmp.conf'': # If you added the MIBs you can reenable # loaging them by commenting out the following line. #mibs : Stessa cosa bisogna farla per il demone snmpd, aggiungendo una riga in **''/etc/default/snmpd''**: export MIBS=UCD-SNMP-MIB Utilizzare almeno la versione 1.1 del pacchetto snmp-mibs-downloader, con versioni precedenti alcuni MIBs non vengono scaricati e si incappa in errori del tipo: snmptranslate -O n UCD-SNMP-MIB::extOutput.2 No log handling enabled - turning on stderr logging Cannot find module (IANAifType-MIB): At line 13 in /usr/share/mibs/ietf/IF-MIB Did not find 'IANAifType' in module #-1 (/usr/share/mibs/ietf/IF-MIB) Cannot find module (IANA-RTPROTO-MIB): At line 12 in /usr/share/mibs/ietf/IP-FORWARD-MIB Did not find 'IANAipRouteProtocol' in module #-1 (/usr/share/mibs/ietf/IP-FORWARD-MIB) .1.3.6.1.4.1.2021.8.1.101.2 ===== Nuova sintassi per snmpd.conf ===== Con Debian Squeeze la configurazione di snmpd utilizza per default un nuovo formato che comprende regole di ACL, ecc. Come mettere il demone in ascolto su tutte le interfacce di rete: #agentAddress udp:127.0.0.1:161 agentAddress udp:161 Come esporre tutte le informazioni disponibili alla community //public//: #rocommunity public default -V systemonly rocommunity public default Come aggiungere grandezze da monitorare tramite script esterni: extend mail_incoming /usr/bin/sudo /usr/local/sbin/mail-io-stats incoming extend mail_cmpleted /usr/bin/sudo /usr/local/sbin/mail-io-stats completed Per leggere le grandezze aggiuntive si utilizza un OID indicizzato con l'etichetta invece che dalla posizione in cui compare. Notare che le doppie virgolette fanno parte dell'OID: snmpwalk -v 2c -c public 127.0.0.1 'NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."mail_incoming"' NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."mail_incoming" = STRING: 14 ===== SNMP su ipv6 ===== Con Debian Wheezy sono necessarie alcune accortezze perché SNMP risponda anche su IPV6, in particolare **''/etc/snmp/snmpd.conf''**: agentAddress udp::161 agentaddress udp6:161 rocommunity public default rocommunity6 public default ===== SNMP con systemd su Debian 9 e seguenti ===== **Debian 9 Stretch** utilizza il sistema di init **systemd** invece del vecchio //sysvinit//. Le personalizzazioni all'avvio non si fanno più in ''/etc/default/snmpd''. La risoluzione degli OIDs nella loro descrizione testuale richiede sempre l'installazione del pacchetto non-free **snmp-mibs-downloader**. Invece di impostare la variabile d'ambient **MIBS** si deve modificare il file **/etc/snmp/snmp.conf**, commentando (disattivando) la riga: #mibs : Eventuali personalizzazioni dei parametri di snmpd non si fanno più con la variabile d'ambiente **SNMPDOPTS**, bisogna piuttosto creare il file **/etc/systemd/system/snmpd.service**, prendendo come esempio quello predefinito ''/lib/systemd/system/snmpd.service''. Il file personalizzato prevale su quello di sistema (basta eseguire **systemctl daemon-reload**). Pare che non sia necessario aggiornare i link simbolici, ad esempio quello contenuto in ''/etc/systemd/system/multi-user.target.wants/''. Ecco ad esempio come modificare la riga **ExecStart** per diminuire il logging e sopprimere tutte le righe **Connection from UDP** che riempiono il syslog (nota: si modifica **%%-Lsd%%** in **%%-LSwd%%**): ExecStart=/usr/sbin/snmpd -LSwd -Lf /dev/null -u Debian-snmp -g Debian-snmp -I -smux,mteTrigger,mteTriggerConf -f -p /run/snmpd.pid In alternativa a **sostituire completamente il file unit** (cioè il file /etc/systemd/system/snmpd.service) è possibile creare un file **override** con solo le modifiche necessarie. Il file override deve stare nella directory **/etc/systemd/system/snmpd.service.d/** e può chiamarsi **local.conf** (è possibile averne più di uno). Fare attenzione al parametro **ExecStart** che deve essere svuotato prima di essere definito nuovamente: [Service] Environment="MIBS=" ExecStart= ExecStart=/usr/sbin/snmpd -LSwd -Lf /dev/null -u Debian-snmp -g Debian-snmp -I -smux,mteTrigger,mteTriggerConf -f -p /run/snmpd.pid