Sinistra <- Un altro punto di Vista... - Indice Generale - Copertina - Realizzazione di un firewall con pfSense -> Destra

Sistemi Liberi


Monitoraggio di sistemi - parte 3

di Rudi Giacomini Pilon

L'articolo...

Dopo aver concluso la trattazione di Nagios si ritorna dalla pratica alla teoria con SNMP.



SNMP

Il Simple Network Management Protocol è un protocollo per l'amministrazione delle reti definito dallo standard internet RFC1157 e integrato da numerosi altri RFC successivi. Si tratta quindi di un protocollo e non di un'applicazione specifica e fu sviluppato per fornire risposte alla necessità di un protocollo di amministrazione per le reti con gli obiettivi principali di semplicità e robustezza. Nelle specifiche veniva previsto un basso sovraccarico sia per i dispositivi che avrebbero utilizzato il protocollo sia per la rete.

La prima volta che ho affrontato questo protocollo ho fatto l'errore, comune a molti, di tradurre simple con semplice (nel senso di facile da usare) mentre una traduzione più consona potrebbe essere semplificato nel senso che la struttura e i metodi del protocollo sono semplificati. Vengono infatti supportati solo tre metodi fondamentali:

Non si desidera di seguito entrare troppo nel dettaglio del protocollo ma è importante evidenziare che la semplicità è proprio nella struttura del pacchetto che consiste sempre di un pacchetto UDP monolitico (l'aggettivo inglese atomic rende meglio se tradotto con monolitico a mio parere).
Il pacchetto è costituito da:

Le PDU contengono sia un identificativo di tipo sia i dati/variabili su cui si va ad agire.
Ci sono solo cinque tipi di PDU che sostanzialmente corrispondono a cinque diverse azioni: get-request, get-next-request, set-request, get-response e trap.

Un pacchetto get-request, inviato a un dispositivo, ottiene in risposta un get-response che restituisce il valore di una variabile.
Un pacchetto get-next-request è utilizzato per iterare fra gli elementi di un albero di variabili e ottiene sempre un get-response.
Un pacchetto set-request configura una variabile di un dispositivo. Anch'esso ottiene in risposta un get-response.

I trap sono differenti in quanto vengono inviati dal dispositivo ad un indirizzo IP memorizzato nel dispositivo stesso al verificarsi di determinati eventi che il dispositivo è programmato per riconoscere. Il pacchetto in questione contiene una serie di variabili/valori che il dispositivo ritiene utili per descrivere l'evento. Non viene attesa risposta all'invio di un trap. Verificare cosa succede all'indirizzo di destinazione o, perfino, se esista qualcosa a quell'indirizzo non è a carico del dispositivo, il quale si limita all'invio della segnalazione.
Le porte usate dal protocollo sono la UDP 161 per le richieste e le risposte e la UDP 162 come destinazione dei trap SNMP è necessario tenerne conto quando gli apparecchi da monitorare e quelli di monitoraggio sono posti sui due lati di un firewall.
La versione 2 e seguenti del protocollo implementano anche dei comandi aggiuntivi e delle estensioni agli oggetti gestiti. Vi rimando alla lettura degli RFC 1441 e 1442 per ulteriori dettagli.

Nelle immagini che seguono viene mostrato un pacchetto UDP inviato per richiedere un valore ad uno switch e la successiva risposta. Il pacchetto è stato rilevato con ethereal [http://www.ethereal.com/] e come si vede si tratta una richiesta di una variabile (GET) e della successiva risposta. In entrambe le immagini è identificabile la community string di default ("public").

Come già detto SNMP offre, per ogni dispositivo, una variabile detta community string che ha la funzione di una password. Si può; vedere dalle immagini che la stringa in questione è visibile in chiaro, quindi, in realtà, è un provvedimento di sicurezza debolissimo ed è uno dei motivi per i quali sono state, teoricamente, abbandonate le versioni 1 e 2c del protocollo (anche se in realtà sono ancora le più utilizzate) a favore della versione 3.

Come già anticipato SNMP tratta degli oggetti che essenzialmente sono delle variabili. Tali variabili sono definite e descritte nella Management Information Base (MIB). MIB non è un database ma una struttura dati ovvero un file scritto in uno specifico linguaggio (SMI - Structure and Identification of Management Information) che elenca delle variabili assegnando ad ogni variabile un nome, un numero ed un elenco di permessi.

Il file viene visto come una gerarchia ad albero e ogni variabile è considerata una foglia nell'albero. Tutto ciò che riguarda SNMP si trova al di sotto del ramo denominato .iso.org.dod.internet che ha come identificativo numerico 1.3.6.1.

L'immagine seguente è uno snapshot dal sito http://support.ipmonitor.com/ e rappresenta un esempio di gerarchia ad albero:

L'identificativo numerico di ciascun oggetto è detto OID (Object Identifier) e non dovrebbe iniziare con un punto anche se, in molte notazioni, il punto iniziale viene sempre riportato. E' utile tenere presente che, in una qualsiasi operazione, qualora l'OID specificato non sia completo (ovvero qualora venga specificato un nodo anziché un oggetto) tutti gli oggetti del nodo richiesto saranno forniti in risposta.
Oltre all'albero standard definito dal comitato di standardizzazione esistono dei sotto-alberi registrati da aziende private presso l'ente di standardizzazione. Per impieghi interni all'azienda è ovviamente possibile definire un proprio sotto-albero qualora ve ne fosse la necessità.

Gli oggetti veri e propri, o variabili che dir si voglia, possono essere di cinque tipi:

In base al tipo di dispositivo vi sono un'infinità di parametri che possono essere misurati o rilevati con SNMP, ad esempio: il carico di una CPU, il numero di processi di un server, i pacchetti in errore di un router, le collisioni di una rete, la memoria libera di una stampante e così via.

Il dispositivo che si incarica del monitoraggio SNMP o della ricezione dei trap, sia esso un server, un PC o un tester dedicato, viene denominato Network Management Station (NMS).

Nel dispositivo da monitorare o amministrare il protocollo SNMP prevede la presenza di un programma, detto agente. Vi sono agenti SNMP nei router, negli switch, nelle stampanti, ad esempio, ma vi sono agenti disponibili anche per i sistemi operativi, sia per i vari UNIX e derivati sia per le varie versioni di Windows. L'agente, oltre a rispondere alle richieste dirette di lettura o modifica di una variabile, potrebbe venir programmato (qualora sia programmabile) per generare un trap in risposta ad un determinato evento.

Un esempio semplice è quello delle stampanti: molte di esse hanno il protocollo SNMP attivo al loro interno e sono in grado di generare un avviso per eventi quali l'esaurimento della carta o del toner. Il segnale in questione può essere monitorato da una funzione dedicata o da un NMS predisposto per ricevere la notifica del problema.

Il vantaggio dei trap rispetto all'interrogazione delle variabili è che con quest'ultimo metodo può accadere di perdere un evento fra un'interrogazione e l'altra mentre nel primo caso è proprio l'evento a creare la notifica e quindi è meno probabile che esso venga perso. La perdita di una segnalazione è comunque sempre possibile in quanto potrebbe accadere che il server che gestisce le notifiche, se ha in carico un numero troppo elevato di dispositivi e molti di essi sono in errore, può non essere in grado di gestire tutte le segnalazioni. Chiaramente la situazione è improbabile in un ambiente ben dimensionato. Inoltre un server che interroga attivamente le variabili è soggetto ad un maggior carico elaborativo rispetto ad uno che si limita ad attendere passivamente la segnalazione di un problema e quindi l'interrogazione attiva sarebbe comunque meno efficiente.

Chiaramente se non si deve monitorare un evento ma effettuare delle misure a intervalli prestabiliti il metodo corretto è il polling da parte della NMS e non l'utilizzo dei trap.

Per quanto riguarda il carico creato dal polling sulla rete riporto un divertente indicazione di John Blommers (SNMP and RMON [http://faculty.washington.edu/blommers/snmp.pdf]):

"State per implementare un sistema di monitoraggio delle performance della rete basato su SNMP:

Ma perché gli amministratori di rete si preoccupano così tanto per l'aggiunta alla rete di traffico di monitoraggio quando web e mail server vengono installati a ritmo di record e gli utenti navigano in rete senza riguardo o preoccupazione su quale impatto ciò abbia sulla rete?"

RMON

RMON è un MIB introdotto dalla versione 2 di SNMP che definisce uno standard per il monitoraggio di rete. In tale MIB, che inizia da .iso.org.dod.internet.mgmt.mib-2.rmon e che ha come identificativo numerico 1.3.6.1 2.1.16 , sono definite 9 sezioni:

  1. statistic: mantiene dati relativi agli errori e all'utilizzo per ogni sottorete monitorata: byte, pacchetti, collisioni, etc.
  2. history: campionamenti periodici prelevati tipicamente ogni 30 secondi
  3. alarm: gruppo che permette la definizione di valori di soglia, da utilizzare per gli allarmi, per ogni variabile di tipo contatore
  4. host: contatori per ogni host della sottorete
  5. hostTopN: statistiche relative agli host
  6. matrix: matrice di errori e utilizzo
  7. filter: consente di definire dei filtri da utilizzare per catturare i pacchetti
  8. capture: indicazioni sulla modalità di invio dei dati alla console di monitoraggio
  9. event: tabella di eventi generati dall'agente RMON
Chiaramente a seconda del dispositivo ciascun gruppo può essere o non essere implementato e avere o non avere un senso.

Ora, dopo aver ribadito più volte che SNMP è un protocollo e dopo aver capito che disponiamo di un database di informazioni (MIB), vediamo un'implementazione che utilizza tale protocollo e passiamo dalla teoria alla pratica.

Net SNMP

Il progetto Net SNMP, precedentemente noto come UCD-SNMP, è una raccolta di strumenti per gestire le informazioni SNMP in ambiente *NIX. Attraverso vari programmi permette le varie operazioni di lettura, scrittura e monitoraggio del protocollo fornendo sia quanto necessario per l'implementazione di un client sia gli strumenti per la gestione di una NMS. Il sito ufficiale del progetto è http://www.net-snmp.org/.

I MIB supportati dal pacchetto sono:

La prima versione rilasciata con il nome di Net SNMP (la 5.0 in quanto le versioni precedenti sono state rilasciate come UCD-SNMP) ha adottato fin dall'inizio dei concetti di modularità che non erano presenti nella versione UCD per cui, a titolo di esempio, per aggiungere un MIB a quelli in dotazione è sufficiente copiarlo in /usr/local/share/snmp/mibs (o /usr/share/snmp/mibs a seconda della distribuzione e del sistema operativo in uso) e con la stessa relativa semplicità è possibile estendere gli applicativi.

Non andrò, di seguito, a spiegare l'installazione dei programmi visto che esiste un pacchetto Net SNMP praticamente per ogni distribuzione posso solo segnalare che nella versione per Fedora manca una qualche forma di collegamento fra il pacchetto del modulo SNMP Perl e quello di Net SNMP e il browser grafico dei MIB (tkmib) non funziona.

Non andrò nemmeno a spiegare in dettaglio tutti i comandi in quanto le pagine del manuale in linea sono esaustive in merito quindi mi limiterò ad una carrellata sui comandi principali con qualche esempio d'uso.

Snmpwalk

Il primo comando da prendere in considerazione è snmpwalk. Questo comando produce come risultato la stampa dell'intero albero delle variabili di un dispositivo a partire dal punto passato come parametro. Se non si fornisce alcun punto di partenza il risultato sarà l'intero albero.

Ecco un esempio di output di snmpwalk che si riferisce ad uno switch:

# snmpwalk -m all 192.168.1.254 -c public
system.sysDescr.0 = "HP J4813A ProCurve Switch 2524, revision F.02.11, ROM F.02.01  (/sw/code/build/info(f00))"
system.sysObjectID.0 = OID: enterprises.11.2.3.7.11.19
system.sysUpTime.0 = Timeticks: (244993657) 28 days, 8:32:16.57
system.sysContact.0 = ""
system.sysName.0 = "Switch 5"
system.sysLocation.0 = "Corridoio 1"
system.sysServices.0 = 74
interfaces.ifNumber.0 = 28
interfaces.ifTable.ifEntry.ifIndex.1 = 1
interfaces.ifTable.ifEntry.ifIndex.2 = 2
interfaces.ifTable.ifEntry.ifIndex.3 = 3
interfaces.ifTable.ifEntry.ifIndex.4 = 4
interfaces.ifTable.ifEntry.ifIndex.5 = 5
interfaces.ifTable.ifEntry.ifIndex.6 = 6
interfaces.ifTable.ifEntry.ifIndex.7 = 7
interfaces.ifTable.ifEntry.ifIndex.8 = 8
[...]

Il resto dell'output è stato troncato per brevità in quanto continuerebbe per molte pagine. A tal proposito, quando dovete esplorare un MIB, è molto utile redirigere l'output del comando verso un file in quanto spesso il buffer video non riesce a contenerlo completamente.

Indicando un solo ramo (ad esempio system) otteniamo un risultato più breve in quanto viene mostrato solo quanto richiesto:

# snmpwalk -mall -cpublic 192.168.1.254 system
system.sysDescr.0 = "HP J4813A ProCurve Switch 2524, revision F.02.11, ROM F.02.01  (/sw/code/build/info(f00))"
system.sysObjectID.0 = OID: enterprises.hp.nm.system.netElement.hpEtherSwitch.hpSwitchJ4813A
system.sysUpTime.0 = Timeticks: (262307843) 30 days, 8:37:58.43
system.sysContact.0 = ""
system.sysName.0 = "Switch 5"
system.sysLocation.0 = "Corridoio 1"
system.sysServices.0 = 74

Questo comando è molto utile in particolare per esplorare il "contenuto" di dispositivi dei quali non si conoscono le variabili. L'assenza di descrizioni in alcuni OID è sintomo della mancanza di un MIB specifico per il dispositivo esaminato e si risolve facilmente, se si riesce a rintracciare il MIB, installandolo come sopra accennato.

E' possibile utilizzare il comando in maniera molto "sporca" per dei monitoraggi improvvisati e a scopo di test. Nell'esempio seguente, mancando il MIB specifico per una stampante di rete, si vuole verificare se un certo ramo individuato è proprio quello relativo allo stato della stampante.
Per individuare il ramo prima eseguiamo un comando snmpwalk su tutto l'albero e poi, per affinare la ricerca, togliamo la carta da due cassetti ed eseguiamo il comando che segue:

# snmpwalk -mall -cpublic 192.168.1.236 43.18.1.1.8.1
43.18.1.1.8.1.3 = "Carta assente: Cassetto 4 {13500}"
43.18.1.1.8.1.84= "Carta assente: Cassetto 1 {13200}"

A questo punto, con uno script con un ciclo infinito riusciamo a verificare che il ramo individuato è proprio quello che cercavamo:

# vi testerrori.sh

inseriamo i seguenti comandi:

#!/bin/sh
while [ 1 ] do
  snmpwalk -mall -cpublic 192.168.1.236 43.18.1.1.8.1
done
#Per bloccare lo script premere ctrl-C

rendiamo lo script eseguibile e lo eseguiamo:

# chmod +x testerrori.sh
# ./testerrori.sh

43.18.1.1.8.1.90 = "Non rilevato: Cassetto 2 {12301}"
43.18.1.1.8.1.90 = "Non rilevato: Cassetto 2 {12301}"
43.18.1.1.8.1.90 = "Non rilevato: Cassetto 2 {12301}"
43.18.1.1.8.1.90 = "Non rilevato: Cassetto 2 {12301}"
43.18.1.1.8.1.90 = "Non rilevato: Cassetto 2 {12301}"
43.18.1.1.8.1.91 = "Non rilevato: Cassetto 3 {12401}"
43.18.1.1.8.1.91 = "Non rilevato: Cassetto 3 {12401}"
43.18.1.1.8.1.91 = "Non rilevato: Cassetto 3 {12401}"
43.18.1.1.8.1.91 = "Non rilevato: Cassetto 3 {12401}"
43.18.1.1.8.1.91 = "Non rilevato: Cassetto 3 {12401}"

Il risultato è stato ottenuto estraendo i cassetti della stampante. Ovviamente il monitoraggio vero è proprio è stato effettuato con altri strumenti ma nulla vieta di migliorare lo script di cui sopra per gestioni molto semplici.

Snmpget

Il comando snmpget permette di ottenere il valore di una singola variabile ad esempio:

snmpget -Cf -mall 192.168.1.254 -c public .1.3.6.1.4.1.11.2.14.11.5.1.9.6.1.0
enterprises.11.2.14.11.5.1.9.6.1.0 = 13

Come si vede, la forma dell'OID nella risposta è abbreviata e manca tutto ciò che precede "enterprises". La parte finale è invece in forma numerica per mancanza dello specifico MIB relativo al dispositivo interrogato. Una forma analoga con un MIB più completo è:

snmpget 192.168.1.236 -c public system.sysDescr.0
system.sysDescr.0 = NRG 3525/3508/3502 5.21 / NRG Network Printer C model / NRG Network Scanner C model

che, in questo esempio, permette di ottenere la descrizione del sistema (si tratta di una stampante).

Tornando all'esempio utilizzato per il comando snmpwalk, è possibile controllare la presenza della carta nella stessa stampante, in maniera molto più efficiente, con il seguente comando:

# snmpget -mall -cpublic 192.168.1.236 43.18.1.1.8.1.2
43.= "Carta assente: Cassetto 3 {13400}"

Come è facile intuire è semplice costruire degli script che sfruttano il comando snmpget e verificando le risposte ricevute segnalano un problema all'amministratore del dispositivo sotto controllo. Il linguaggio solitamente usato a tale scopo è il Perl (vedi ad es. The Cuddletech Guide to SNMP Programming) ma nulla vieta di implementare dei semplici script di shell.

Snmptable

A volte alcune informazioni di un MIB sono correlate tra di loro come elementi di una tabella. La normale rappresentazione ad albero fa perdere la visione di insieme su tali elementi in quanto è difficile esaminare tali informazioni visualizzandole in maniera sequenziale. Il comando snmptable permette di ottenere una rappresentazione tabellare delle informazioni con l'unico inconveniente di risultare di difficile lettura per tabelle molto ampie.
Tale problema è risolvibile limitando l'output del comando ad un numero prestabilito di caratteri o con un copia e incolla su un altro programma.

Vediamo come semplice esempio la tabella degli indirizzi di uno switch:

# snmptable 192.168.1.253 ipAddrTable -cpublic
SNMP table: ip.ipAddrTable

  ipAdEntAddr ipAdEntIfIndex ipAdEntNetMask ipAdEntBcastAddr ipAdEntReasmMaxSize
     127.0.0.1          4124      255.0.0.0                1               65535
 192.168.1.253            29    255.255.0.0                1               65535

Tale forma è sicuramente più leggibile dell'equivalente visualizzazione ad albero:

# snmpwalk 192.168.1.253 ipAddrTable -cpublic
ip.ipAddrTable.ipAddrEntry.ipAdEntAddr.127.0.0.1 = IpAddress: 127.0.0.1
ip.ipAddrTable.ipAddrEntry.ipAdEntAddr. 192.168.1.253 = IpAddress: 192.168.1.253
ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.127.0.0.1 = 4124
ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex. 192.168.1.253 = 29
ip.ipAddrTable.ipAddrEntry.ipAdEntNetMask.127.0.0.1 = IpAddress: 255.0.0.0
ip.ipAddrTable.ipAddrEntry.ipAdEntNetMask. 192.168.1.253 = IpAddress: 255.255.0.0
ip.ipAddrTable.ipAddrEntry.ipAdEntBcastAddr.127.0.0.1 = 1
ip.ipAddrTable.ipAddrEntry.ipAdEntBcastAddr. 192.168.1.253  = 1
ip.ipAddrTable.ipAddrEntry.ipAdEntReasmMaxSize.127.0.0.1 = 65535
ip.ipAddrTable.ipAddrEntry.ipAdEntReasmMaxSize. 192.168.1.253  = 65535

Snmptrapd

Come già anticipato, l'invio di trap è il metodo con il quale un dispositivo puo' segnalare ad un NMS il verificarsi di un evento. Net SNMP, oltre a permettere di creare dei trap, ha in dotazione un demone che permette di costruire una NMS. Il demone in questione è snmptrapd ed ha la possibilità di ricevere dei trap ed attivare appositi programmi in risposta agli eventi che li hanno generati. Di default snmptrapd ascolta sulla porta UDP 162 per cui se attivate tale demone è opportuno verificare che tale porta non sia bloccata da un firewall.
Per poter intercettare un evento è necessario definire un traphandle (ovvero un aggancio) per tale evento nel file snmtrapd.conf.
La sintassi per definire un traphandle è la seguente:

traphandle	OID 	comando 

quindi ad esempio per intercettare un errore da una stampante la configurazione potrebbe essere:

traphandle 	.1.3.6.1.2.1.25.3.2.1.5.1	/usr/local/bin/sendmessage_to_admin.sh

dove il comando /usr/local/bin/sendmessage_to_admin.sh è uno script di shell che invia un messaggio email ad un responsabile dell'operatività della stampante. E' anche possibile passare al programma dei parametri predefiniti, alcuni dei quali molto utili come ad esempio HOSTNAME e IPADDRESS che rappresentano il nome e l'indirizzo IP dell'host che ha generato il trap.

Concludo questa veloce panoramica su SNMP con la speranza di non aver tediato nessuno.
Il prossimo numero tratterà di RRDtool, con qualche esempio pratico che forse risulterà più appetibile.
Come al solito vi invito ad inviare commenti, critiche e suggerimenti.

Riferimenti bibliografici

Essential SNMP di Kevin Schmidt, Douglas Mauro - O'Reilly - ISBN: 0596000200

RFC 1157 su SNMP

RFC 1351: SNMP Administrative model

RFC 1441 Introduction to version 2 of INMF

RFC 1442 Structure of MIF for SNMP v2

NET SNMP FAQ

The Simple Times magazine


L'autore

Rudi Giacomini Pilon, programmatore dall'età di 14 anni, ex progettista elettronico, ex hardwarista e sistemista presso un Microsoft Solution Provider, ex esperto di reti e programmatore in una concessionaria IBM, incontra Linux nel 1994 e da allora vede pinguini ovunque. Dal 1999 è responsabile EDP in una SpA ove affronta l'informatica a 538 gradi (360 erano pochi).


Sinistra <- Un altro punto di Vista... - Indice Generale - Copertina - Realizzazione di un firewall con pfSense -> Destra