Archivi categoria: Networking

Hub vs switch: facciamo un po’ di chiarezza

Qualche tempo fa un mio collega (che svolge tutt’altra mansione rispetto alla mia e che quindi non è un tecnico), mi ha chiesto quale fosse la differenza tra hub e switch, dato che i primi sono ormai quasi del tutto irreperibili sul mercato (a meno di qualche aggeggio usato).

In soldoni, gli hub non sono altro che dei repeater “multiporta” (lasciatemi passare il termine), ovvero il traffico ricevuto su ciascuna porta viene inoltrato, indifferentemente, su tutte le altre. Toccherà poi alle schede di rete dei dispositivi connessi all’hub “capire” se il MAC address di destinazione del frame è il proprio (in questo caso lo accetteranno) oppure è associato a qualche altra macchina, scartandolo. L’ultima affermazione è vera solo ed esclusivamente se la suddetta scheda di rete non è configurata in modalità promiscua. Questa modalità, infatti, le consentirebbe di “accettare” tutti i frame, indifferentemente dal fatto che siano destinati ad essa o meno (e ciò è indispensabile nel caso in cui si voglia sniffare il traffico dei dispositivi connessi all’hub).

comparison

Ad esempio, per mettere un’interfaccia in modalità promiscua su una macchina Linux, occorre digitare il comando:

[root@linuxbox ~]# ifconfig <nome_interfaccia> promisc

Inoltre, tale modalità viene abilitata in automatico nel caso in cui sulla Linux box sia installato ed attivo un software che funge da NIDS, quale snort.

Un’altra peculiarità dell’hub riguarda la gestione dei cosiddetti domini di collisione. Infatti, tutti i dispositivi collegati ad esso faranno parte del medesimo dominio di collisione, mentre gli switch, per definizione, riescono a garantire un dominio di collisione ad-hoc per ciascuna porta di cui sono dotati. Per essere più precisi, gli switch sono caratterizzati dalla presenza di una memoria interna, in gergo CAM (acronimo che sta per Content Access Memory), in cui vengono memorizzate le accoppiate MAC address sorgente/porta su cui è stato ricevuto. Tale fase di popolamento della CAM avviene per gradi, ovvero man mano che i dispositivi collegati a ciascuna porta iniziano a trasmettere: quando lo switch vede come MAC sorgente un dato indirizzo L2 su una specifica porta, memorizzerà tale accoppiata all’interno della CAM. Successivamente, quando un frame recante uno specifico MAC di destinazione verrà ricevuto dallo switch, esso lo inoltrerà solo ed esclusivamente sulla porta in cui il dispositivo recante il suddetto MAC è collegato.

Il vantaggio di tale meccanismo di gestione del traffico è abbastanza chiaro: mettendo in comunicazione solo mittente e destinatario, si viene a creare una sorta di “mezzo trasmissivo” dedicato tra di essi, riducendo notevolmente (ma non eliminando completamente) il rischio di collisioni (almeno per quanto riguarda le reti half duplex in cui tale fenomeno può verificarsi). Tirando le somme, è proprio per questo motivo che lo switch “garantisce” un dominio di collisione dedicato per ciascuna porta di cui è dotato. Inoltre, lo sniffing del traffico risulta impossibile, a meno che su una delle porte dello switch sia configurato il cosiddetto port mirroring (che la Cisco chiama SPANCatalyst Switched Port Analyzer). Nella fattispecie, essa consente di inoltrare il traffico ricevuto (su una o più porte) su quella in cui è configurato il mirroring (solitamente utilizzo allo scopo l’ultima porta dello switch o le ultime 2). Va da se che anche in questo caso l’interfaccia del PC adibito a sniffer deve essere configurata in modalità promiscua.

Spero di aver fatto un po’ di luce sulla questione.

Alla prossima.

lftp: mirroring di un sito remoto da CLI

Supponiamo che vi sia la necessità di trasferire il contenuto di un sito Web su un altro sito Web autorizzato (tale pratica, in gergo, prende il nome di mirroring). Supponiamo, inoltre, che il task in questione debba essere automatizzato tramite un cronjob oppure uno scheduled task di Windows. Cosa fare dunque? Semplice, iniziare ad utilizzare lftp.

lftp

Il suddetto tool è dotato di una console integrata, che può essere richiamata digitando semplicemente lftp, ad esempio:

[root@linux ~]# lftp
lftp :~>

Nel caso in cui si volesse creare un task automatico, sconsiglio fortemente l’uso della console in questione (a meno di tool esterni, quali expect, in grado di interagire con essa), e raccomando di avvalersi dell’opzione -e, grazie alla quale i comandi lftp possono essere inviati direttamente da CLI, ad esempio:

lftp -u vostrouser,vostrapassword sitodamirrorare -e 'set ftp:use-feat off; set ftp:ssl-allow off; mirror -c / ../sitemirrored; exit'

Nella fattispecie, ho disabilitato l’invio del comando FEAT (ftp:use-feat off) ed ho inibito qualsiasi tentativo di connessione tramite FTPS (ftp:ssl-allow off). Inoltre, ho inizializzato il mirroring (comprensivo di resume in caso di disconnessione, grazie all’opzione -c che sta per –continue), specificando la directory sorgente (in questo caso /) e quella di destinazione (../sitemirrored).

Attenzione: se state utilizzando la versione Windows di lftp, consiglio di copiare l’eseguibile nella stessa unità in cui si trova la dir di destinazione, in quanto ho riscontrato diversi problemi relativi all’attraversamento delle directory.

Una volta completato il mirroring del sito, è possibile effettuare la stessa operazione in modo incrementale, ovvero “copiando” solo ed esclusivamente i nuovi file (quelli che non presenti durante la prima tornata). Il comando da utilizzare è il seguente:

lftp -u vostrouser,vostrapassword sitodamirrorare -e 'set ftp:use-feat off; set ftp:ssl-allow off; mirror -n / ../sitemirrored; exit'

dove l’opzione -n sta per –only-newer.

Non ci resta che creare il cronjob (o lo scheduled task) ed abbiamo finito.

Alla prossima.

auto_clean_zombies: event handler per Nagios in grado di ripulire il sistema dai processi zombie

In questo post ho illustrato il codice di uno scrip da me realizzato, in grado di ripulire il sistema dai processi zombie. Ora vedremo come fare ad integrare, sotto forma di event handler, il predetto scrip con Nagios. Per prima cosa è necessario creare l’event handler vero e proprio (che funge da wrapper), il quale richiamerà lo scrip clean_zombies in caso di necessità:

#!/bin/bash

case "$1" in
OK)
        ;;
WARNING)
        ;;
UNKNOWN)
        ;;
CRITICAL)
       case "$2" in
                SOFT)
                        case "$3" in
                        3)
                                echo -n "Cleaning zombie processes (3rd soft critical state)..."
                                usr/bin/sudo /root/scrips/clean_zombies
                                ;;
                                esac
                        ;;
                HARD)
                        echo -n "Cleaning zombie processes (3rd soft critical state)..."
                        usr/bin/sudo /root/scrips/clean_zombies
                        ;;
                esac
                ;;
        esac

exit 0

Successivamente occorre creare un apposito comando all’interno del file /etc/nagios/object/commands.cfg:

# 'auto_clean_zombies' command definition
define command {
        command_name      auto_clean_zombies
        command_line      /usr/lib64/nagios/plugins/eventhandlers/auto_clean_zombies $SERVICESTATE$ $SERVICESTATETYPE$ $SERVICEATTEMPT$
        }

A questo punto possiamo assegnare l’event handler al servizio Total Processes definito nel file di configurazione dell’host per il quale si intende monitorare il numero dei processi:

define service{
        use                            local-service         
        host_name                      localhost
        service_descripion             Total Processes
        event_handler                  auto_clean_zombies
        check_command                  check_local_procs!280!400!RSZDT
        }

Inoltre, affinchè l’untente nagios possa lanciare il suddetto scrip senza che vi sia la necessità di inserire la password di autenticazione, occorre editare il file /etc/sudoers nel seguente modo:

nagios   ALL=NOPASSWD:   /root/scrips/clean_zombies

Ricarichiamo la configurazione di Nagios:

[root@linuxbox ~]# service nagios reload

ed abbiamo finito. Alla prossima.

check_ntp_peers: script bash per il monitoraggio dei peer NTP mediante Nagios

Il protocollo NTP ci consente, in soldoni, di tenere aggiornate la data e l’ora di sistema, sincronizzandole con un’apposita sorgente di tempo. Per i sistemi *nix, nella stragrande maggioranza dei casi, è sufficiente configurare il servizio NTP (attivo mediante il demone ntpd, o, in alternativa, utilizzando l’accoppiata ntpdate + crontab) agendo sul suo file diconfigurazione (ovvero ntp.conf) e definendo le sorgenti alle quali sincronizzarsi.

ntpAd esempio:

server ntp1.inrim.it
server ntp2.inrim.it

Ora, per saggiare lo stato di sincronizzazione del nostro server, a parte il classico comando date, è possibile utilizzare un apposito tool per le interrogazioni NTP, ovvero ntpq:

[root@linuxbox ~]# ntpq
ntpq> pe
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*ntp1.inrim.it   .CTD.            1 u    4   64  377   45.819    0.219   2.655
+ntp2.inrim.it   .CTD.            1 u  903 1024  377   48.974    1.788   0.978

In particolare, con il comando pe, sono riuscito a recuperare la lista dei peers (ovvero le sorgenti di tempo) con i relativi valori di offset (i quali rappresentano la discrepanza, in ms, tra l’ora locale di sistema e quella del peer stesso), di jitter (ovvero il ritardo, anch’esso espresso in ms, accumulato tra 2 aggiornamenti immediatamente successivi) e di delay (RTT, in ms, associato alla comunicazione con il time server remoto). Da notare, inoltre, che il campo refid indica qual è (se esiste, dipende dallo stratum, specificato dal campo st) la sorgente di tempo utilizzata a loro volta dai server che sto interrogando (rispettivamente ntp1.inrim.it ed ntp2.inrim.it), mentre il carattere * mostra quale dei 2 server da me definiti all’interno del file ntp.conf sto utilizzando per sincronizzare la data e l’ora di sistema.

Dopo questa breve carrellata introduttiva veniamo al dunque, per cui riporto il contenuto dello scrip bash in grado di tenere sotto controllo i valori associati alle sorgenti NTP definite sul nostro sistema:

#!/bin/bash

warn_values=$1
crit_values=$2

warn_delay=`echo $warn_values | awk -F "," '{print $1}'`
warn_offset=`echo $warn_values | awk -F "," '{print $2}'`
warn_jitter=`echo $warn_values | awk -F "," '{print $3}'`

warn_delay_len=$((${#warn_delay} - 1))
warn_offset_len=$((${#warn_offset} - 1))
warn_jitter_len=$((${#warn_jitter} - 1))

crit_delay=`echo $crit_values | awk -F "," '{print $1}'`
crit_offset=`echo $crit_values | awk -F "," '{print $2}'`
crit_jitter=`echo $crit_values | awk -F "," '{print $3}'`

crit_delay_len=$((${#crit_delay} - 1))
crit_offset_len=$((${#crit_offset} - 1))
crit_jitter_len=$((${#crit_jitter} - 1))

if [[ "$warn_delay_len" -gt 5 ]];then
        echo "UNKNOWN: bad value for warning delay"
        echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
        exit 3;
fi

if [[ "$warn_offset_len" -gt 5 ]];then
        echo "UNKNOWN: bad value for warning offset"
        echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
        exit 3;
fi

if [[ "$warn_jitter_len" -gt 5 ]];then
        echo "UNKNOWN: bad value for warning jitter"
        echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
        exit 3;
fi

if [[ "$crit_delay_len" -gt 5 ]];then
        echo "UNKNOWN: bad value for critical delay"
        echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
        exit 3;
fi

if [[ "$crit_offset_len" -gt 5 ]];then
        echo "UNKNOWN: bad value for critical offset"
        echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
        exit 3;
fi

if [[ "$crit_jitter_len" -gt 5 ]];then
        echo "UNKNOWN: bad value for critical jitter"
        echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
        exit 3;
fi

ntp_delay=`/usr/sbin/ntpq -p | grep '*' | awk '{print $8}'`
ntp_offset=`/usr/sbin/ntpq -p | grep '*' | awk '{print $9}'`
ntp_jitter=`/usr/sbin/ntpq -p | grep '*' | awk '{print $10}'`

if [[ ! -z $warn_values ]];then
         if [[ ! -z $crit_values ]];then
                if [[ ! -z $warn_delay ]];then
                        if [[ ! -z $crit_delay ]];then
                                if [[ "$(echo $ntp_delay '>=' $warn_delay | bc)" -eq 1 ]] && [[ "$(echo $ntp_delay '<' $crit_delay | bc)" -eq 1 ]];then
                                        delay="NTP delay is $ntp_delay ms";
                                        delay_perf="| ntp_delay=$ntp_delay"
                                        retval_1=1;
                                elif [[ "$(echo $ntp_delay '>=' $crit_delay | bc)" -eq 1 ]];then
                                        delay="NTP delay is $ntp_delay ms";
                                        delay_perf="| ntp_delay=$ntp_delay"
                                        retval_1=2;
                                else
                                        delay="NTP delay is $ntp_delay ms";
                                        delay_perf="| ntp_delay=$ntp_delay"
                                        retval_1=0;
                                fi
                        else
                                echo "UNKNOWN: NTP critical delay is unknown"
                                exit 3;
                        fi
                else
                        echo "UNKNOWN: NTP warning delay is unknown"
                        exit 3;
                fi
                if [[ ! -z $warn_offset ]];then
                        if [[ ! -z $crit_offset ]];then
                                if [[ "$(echo $ntp_offset '<' 0 | bc)" -eq 1 ]];then
                                        warn_offset=$(echo "-1 * $warn_offset" | bc)
                                        crit_offset=$(echo "-1 * $crit_offset" | bc)
                                        if [[ "$(echo $ntp_offset '<=' $warn_offset | bc)" -eq 1 ]] && [[ "$(echo $ntp_offset '>' $crit_offset | bc)" -eq 1 ]];then
                                                offset="NTP offset is $ntp_offset ms";
                                                offset_perf=" ntp_offset=$ntp_offset"
                                                retval_2=1;
                                        elif [[ "$(echo $ntp_offset '<' $crit_offset | bc)" -eq 1 ]];then
                                                offset="NTP offset is $ntp_offset ms";
                                                offset_perf=" ntp_offset=$ntp_offset"
                                                retval_2=2;
                                        else
                                                offset="NTP offset is $ntp_offset ms";
                                                offset_perf=" ntp_offset=$ntp_offset"
                                                retval_2=0;
                                        fi
                                else
                                        if [[ "$(echo $ntp_offset '>=' $warn_offset | bc)" -eq 1 ]] && [[ "$(echo $ntp_offset '<' $crit_offset | bc)" -eq 1 ]];then
                                                offset="NTP offset is $ntp_offset ms";
                                                offset_perf=" ntp_offset=$ntp_offset"
                                                retval_2=1;
                                        elif [[ "$(echo $ntp_offset '>' $crit_offset | bc)" -eq 1 ]];then
                                                offset="NTP offset is $ntp_offset ms";
                                                offset_perf=" ntp_offset=$ntp_offset"
                                                retval_2=2;
                                        else
                                                offset="NTP offset is $ntp_offset ms";
                                                offset_perf=" ntp_offset=$ntp_offset"
                                                retval_2=0;
                                        fi
                                fi
                        else
                                echo "UNKNOWN: NTP critical offset is unknown"
                                exit 3;
                        fi
                else
                        echo "UNKNOWN: NTP warning offset is unknown"
                        exit 3;
                fi
                if [[ ! -z $warn_jitter ]];then
                        if [[ ! -z $crit_jitter ]];then
                                if [[ "$(echo $ntp_jitter '>' $warn_jitter | bc)" -eq 1 ]] && [[ "$(echo $ntp_jitter '<' $crit_jitter | bc)" -eq 1 ]];then
                                        jitter="NTP jitter is $ntp_jitter ms";
                                        jitter_perf=" ntp_jitter=$ntp_jitter"
                                        retval_3=1;
                                elif [[ "$(echo $ntp_offset '>' $crit_jitter | bc)" -eq 1 ]];then
                                        jitter="NTP jitter is $ntp_jitter ms";
                                        jitter_perf=" ntp_jitter=$ntp_jitter"
                                        retval_3=2;
                                else
                                        jitter="NTP jitter is $ntp_jitter ms";
                                        jitter_perf=" ntp_jitter=$ntp_jitter"
                                        retval_3=0;
                                fi
                        else
                                echo "UNKNOWN: NTP critical jitter is unknown"
                                exit 3;
                        fi
                else
                        echo "UNKNOWN: NTP warning jitter is unknown"
                        exit 3;
                fi
        else
                 echo "UNKNOWN: Critical values are unknown"
                 echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
                 exit 3;
        fi
else
        echo "UNKNOWN: Warning values are unknown"
        echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
        exit 3;
fi

if [[ "$retval_1" -eq 1 ]] || [[ "$retval_2" -eq 1 ]] || [[ "$retval_3" -eq 1 ]];then

        echo "WARNING: $delay $offset $jitter $delay_perf $offset_perf $jitter_perf"
        exit 1

elif [[ "$retval_1" -eq 2 ]] || [[ "$retval_2" -eq 2 ]] || [[ "$retval_3" -eq 2 ]];then

        echo "CRITICAL: $delay $offset $jitter $delay_perf $offset_perf $jitter_perf"
        exit 2

else

        echo "OK: $delay $offset $jitter $delay_perf $offset_perf $jitter_perf"
        exit 0

fi

Per prima cosa viene verificata la consistenza delle soglie di WARNING e CRITICAL per ciauscuno dei 3 valori monitorati (offset, jitter e delay), sia per quanto riguarda il numero di cifre utilizzate (5) che per ciò che concerne la coerenza logica (ad esempio il jitter/offset/delay di WARNING deve essere strettamente minore di quello CRITICAL).

A questo punto non ci rimane che configurare Nagios, editando, in prima istanza, il file /etc/nagios/objects/commands.cfg, dove verrà definito il comando che si avvarrà del suddetto plugin:

 # 'check_ntp_peers' command definition
define command{
        command_name check_ntp_peers
        command_line $USER1$/check_ntp_peers $ARG1$ $ARG2$
}

e successivamente associando uno specifico servizio all’host che rappresenta la nostra macchina, in modo da monitorare i valori associati all’NTP:

define service{
        use                             local-service         ; Name of service template to use
        host_name                       localhost
        service_description             NTP Peers Status
        check_command                   check_ntp_peers!80.000,2.000,2.000!90.000,3.000,3.000
        }

Facciamo il solito reload del nostro NMS:

[root@linuxbox ~]# service nagios reload

ed abbiamo finito.

Alla prossima.

PS: ho deciso di scrivere il suddetto scrip per sopperire alle limitazioni intrinseche del plugin Nagios (nativo) check_ntp_peer (senza la s finale). Nella fattispecie, quest’ultimo consente di ricavare solo ed esclusivamente il valore di offset associato alla sorgente di tempo remota e per funzionare è necessario che il server interrogato sia configurato in modo da rispondere alle query NTP (e quindi non solo alle richieste di sincronizzazione). Da notare che, nella stragrande maggioranza dei casi e per questioni di sicurezza, il server consentirà la sola sincronizzazione, ignorando gli altri tipi di query, come riportato nero su bianco (ad esempio) nella configurazione standard di ntpd:

restrict default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery

cURL: interagire con l’interfaccia Web dei dispositivi di rete mediante linea di comando

Spesso e volentieri abbiamo a che fare con delle macchine *nix sprovviste di Desktop Enviroment (altrimenti conosciuto come server X), attraverso le quali è necessario accedere all’interfaccia Web di alcuni dispositivi di rete SOHO, in modo da effettuare le classiche operazioni di management (cambio di configurazione, riavvio, ecc.).

A tal proposito, esiste un tool molto potente da utilizzare mediante CLI, che prende il nome di cURL.

curlAdesso vedremo quali sono le analisi preliminari che ci permetteranno di capire se l’interfaccia Web con cui vogliamo interagire potrà essere manipolata tramite cURL o meno.

Analisi del codice sorgente

Il primo step consiste nello scaricare il codice sorgente dalla pagina, utilizzando le giuste credenziali di accesso (se previste). Ad esempio:

[root@linuxbox ~]# curl -u username:password http://192.168.1.1

A questo punto possiamo distinguere due macro casi:

1) la pagina Web contiene prevalentemente del codice HTML ed i cambi di configurazione possono essere effettuati mediante dei semplici form e l’invio dei dati attraverso HTTP POST o GET. In tal caso siamo stati fortunati e potremo procedere;

2) la pagina Web contiene soprattutto del codice javascrip e tutte le operazioni di management si avvalgono del suddetto codice. In questo caso siamo stati sfortunati e dovremo demordere, in quanto cURL non supporta javascrip.

Poniamoci quindi nel caso 1 e procediamo.

Per prima cosa occorre analizzare il codice sorgente della pagina di interesse andando alla ricerca dei tag:

<form></form>

all’interno dei quali è presente l’attributo action che punta alla pagina Web che si occuperà di processare i dati del form. Ad esempio:

 
<form action="apply.cgi" method="post">
<input type="hidden" name="page" value="device.asp">

    <input type="submit" name="action" value="Reboot">
</form>

Inoltre, bisogna capire quali e quanti campi di input (con relativo valore), identificati mediante gli attributi id o name, è necessario sottoporre alla suddetta pagina Web. Infatti, molto spesso, come misura molto blanda per contrastare alcuni attacchi Web quali il CSRF (vedi qui per ulteriori dettagli), vengono utilizzati dei campi di input di tipo hidden da inviare insieme al contenuto degli altri campi del form.

Una volta capito quali sono i campi da inoltrare alla pagina specificata dall’attributo action del form HTML (magari utilizzando il classico metodo trial-and-error), possiamo procedere con il loro inoltro vero e proprio, avvalendoci, ad esempio, del seguente comando:

curl -u username:password -s -d "action=Reboot&page=device.asp" http://192.168.1.1/apply.cgi

Nella fattispecie, la pagina che si occuperà di processare i dati è apply.cgi, mentre i campi di input inviati sono action, il cui valore è Reboot, e page, il cui valore è device.asp. Da notare che le suddette informazioni sono state inviate in formato querystring (ovvero utilizzando il carattere & di concatenazione).

Infine, occorre precisare che la flag -s evita di inviare allo standard output le statistiche relative al processamento della pagina richiesta, mentre la flag -d (data) è quella che ci permette di inviare i dati attraverso un semplice HTTP POST.

Per ora è tutto. Alla prossima.

PMTUD e TCP MSS

Topologia di massima

Due filiali interconnesse mediante un tunnel GRE/IPSEC instaurato sfruttando le rispettive linee ADSL. In particolare, sul sito A sono presenti diversi client che hanno necessità di “dialogare” con un server Web posto nel sito B.

Problema

I client accedono al server Web remoto con estrema lentezza e molte delle richieste effettuate vanno in timeout. Nella fattispecie, trattasi di un problema legato alla MTU (Maximum Transmission Unit) configurata sulle interfacce dei router delle 2 filiali, che provoca la suddetta sintomatologia.

Un po’ di teoria

Ma cos’è l’MTU? Essa, molto semplicemente, definisce la dimensione massima (in byte) di un pacchetto (o di un frame) che può attraversare una determinata interfaccia di rete. Ad esempio, nel caso del protocollo IP (layer 3) parliamo generalmente di 1500 byte, mentre nel caso del protocollo Ethernet (layer 2) la MTU è pari a 1526 byte (1500 byte “ereditati” dal protocollo IP + 22 byte di instestazione Ethernet e 4 byte di CRC). Quest’ultima è sicuramente la più rognosa, in quanto molto spesso gli switch sono unmanaged e quindi non è possibile accorgersi immediatamente dei cosiddetti frame giant, che vegnono quindi scartati “silenziosamente” provocando una comunicazione “a singhiozzo” (vedi questo post per ulteriori dettagli).

Per quanto riguarda invece la MTU IP, si avranno sicuramente dei problemi nel caso in cui:

1) i valori configurati sulle interfacce del router A e del router B differiscono tra di loro (in gergo parliamo di MTU mismatch);

2) lungo il cammino tra router A e il router B esiste un segmento la cui MTU è inferiore rispetto a quella configurata sui 2 router.

Nel primo caso possiamo correre ai ripari molto velocemente, configurando un valore di MTU identico sulle interfacce dei router delle 2 filiali. Ad esempio, possiamo definire la MTU di una data interfaccia utilizzando il comando:

Router(config-if)# ip mtu <valore in byte>

Nel secondo caso, invece, occorre fare un po’ di diagnostica ed eventualmente utilizzare delle configurazioni ad hoc.

In entrambi i casi i pacchetti che superano la MTU più bassa verranno “frammentati” e ricostruiti in fase di ricezione. Ovviamente tale operazione, oltre a causare un overhead sui router coinvolti, provocherà dei seri problemi a livello 4 (TCP) e superiori, inficiando in modo notevole l’accesso al servizio da parte degli utenti.

PMTUD

Per evitare quindi che si verifichi un’eccessiva frammentazione è stato messo a punto un meccanismo tale per cui un router riuscirà ad accorgersi automaticamente della presenza di un valore di MTU inferiore rispetto a quello configurato sulla propria interfaccia, riducendo di conseguenza la dimensione dei pacchetti che intende inoltrare. Tale meccanismo prende il nome di Path MTU Discovery, abbreviato in PMTUD. Più in dettaglio, essa si basa sull’invio/ricezione di messaggi ICMP unreachable type 3 code 4 ( vedi qui per ulteriori dettagli): se la MTU dei pacchetti ricevuti da un router supera la dimensione massima definita sulla propria interfaccia in ricezione, esso procederà con l’inoltro del suddetto messaggio verso il router mittente. In tal modo, quest’ultimo si accorgerà di quanto sta avvenendo e ridurrà di conseguenza la MTU in modo da riuscire ad “attraversare” il router interessato.

PMTUDOra, occorre precisare che non è tutto oro ciò che luccica, nel senso che molto spesso i pacchetti ICMP unreachable vengono disabilitati sia in TX che in RX (in questo caso si parla di PMTUD blackhole). Ad esempio, nel caso dei dispositivi di casa Cisco, essi sono disabilitati di default:

Router#sh ip int dia0 | i ICMP
  ICMP redirects are never sent
  ICMP unreachables are never sent
  ICMP mask replies are never sent

Il perchè di tale configurazione è presto detto: per loro stessa natura, i messaggi ICMP consentono di ottenere informazioni “sensibili” sulla rete target e possono anche essere utilizzati per generare attacchi di tipo DoS/DDoS. Infatti, se un utente malevolo facesse in modo di “sollecitare” la generazione dei messaggi ICMP unreachable da parte del router oggetto dell’attacco, riuscirebbe certamente a sovraccaricarlo, poichè la generazione del suddetto tipo di messagistica avviene a livello di CPU. Come workaround è comunque possibile settare un rate limit specifico, ad esempio:

Router(config)# ip icmp rate-limit unreachable df 500

dove 500 rappresenta il numero di millisecondi che deve intercorrere tra la generazione di un messaggio ICMP unreachable e quello successivo.

A titolo di cronaca, per abilitare i suddetti messaggi su una data interfaccia è sufficiente digitare il comando:

Router(config-if)# ip unreachable

Identificare il valore di MTU corretto: metodo trial and error

Occorre precisare che esiste un modo empirico per determinare la dimensione della MTU più piccola presente lungo il percorso tra il router A ed il router B. Esso si basa sull’utilizzo del comando ping dotato delle flag -f (che imposta a 1 il bit do not fragment nell’header IP) e -l (che imposta la dimensione del solo payload). Se ad esempio la MTU configurata sulla scheda di rete del nostro PC (con Windows 7 a bordo) fosse pari a 1500 byte, potremmo utilizzare il comando:

C:\Users\pippo> ping 192.168.1.1 -f -l 1472

dove 1472 è il massimo payload definibile senza che vi sia frammentazione, poichè ad esso verranno sommati i 20 byte di intestazione IP e gli 8 byte di instestazione ICMP (per un totale di 1500 byte). Utilizzando un payload di 1473 byte, la nostra scheda ci indicherà che abbiamo superato la MTU attraverso il seguente output:

C:\Users\pippo>ping 192.168.1.1 -l 1473 -f

Esecuzione di Ping 192.168.1.1 con 1473 byte di dati:
E' necessario frammentare il pacchetto ma DF è attivo.
E' necessario frammentare il pacchetto ma DF è attivo.
E' necessario frammentare il pacchetto ma DF è attivo.
E' necessario frammentare il pacchetto ma DF è attivo.

Tale metodo può essere utilizzato per identificare la MTU di interesse, abbassando di volta in volta la dimensione del payload fino a quando al posto del suddetto messaggio verranno visualizzati dei semplici ICMP echo reply.

Una piccola nota a margine: nel caso in cui si volesse utilizzare questa metodologia direttamente dalla CLI del router Cisco, è possibile utilizzare il seguente comando:

ping 192.168.1.1 source fa0/0 df-bit size 1500

dove 1500, in questo caso, rappresenta la dimensione totale del messaggio ICMP echo request (e non del solo payload come avveniva nel caso di Windows 7).

TCP MSS

L’acronimo MSS sta per Maximum Segment Size e rappresenta la dimensione massima (in byte) che può avere il payload (e solo il payload) di un segmento TCP. Il valore di default è 1460, ovvero 1500 byte di MTU meno i 20 byte di instestazione TCP ed i 20 byte di intestazione IP. Nel caso in cui la MTU più piccola relativa al percorso tra A a B fosse inferiore a quella di default, è possibile “forzare” il valore di MSS (in gergo parliamo di MSS clamping). Ad esempio, per i router Cisco potremo utilizzare il comando:

Router(config-if)# ip tcp adjust-mss <byte>

dove i byte da utilizzare sono dati dalla MTU più piccola meno 40 byte.

Un caso pratico (e molto diffuso tra gli end user) in cui l’MSS clamping torna davvero utile riguarda il protocollo PPPoE, che usa una MTU pari a 1492 byte (a differenza del PPPoA la cui MTU è quella classica, ovvero 1500 byte). In tal caso si può procedere con questa configurazione sull’interfaccia dia0:

Router(config-if)# ip mtu 1492
Router(config-if)# ip tcp adjust-mss 1452

Spero di aver fatto un minimo di chiarezza sul concetto di MTU e su quanto esso sia importante nell’ambito della comunicazione client/server basata sul protocollo TCP e superiori.

Alla prossima.

NRPE_NT e Nagios: tenere sotto controllo gli aggiornamenti di Windows

Installare prontamente gli aggiornamenti di Windows, soprattutto se si ha a che fare con i security update, è sempre cosa buona e giusta. Spesso, però, capita che l’amministratore di sistema debba gestire N macchine e non abbia il tempo materiale di loggarsi su ciascuna di esse e constatare l’eventuale disposnibilità di aggiornamenti. Personalmente credo che non li si debba mai scaricare nè tantomeno installare automaticamente sulla macchina ospite, soprattutto se si ha a che fare con dei sistemi in produzione.

Cosa fare dunque per automatizzare tale task di verifica della disponibilità degli aggiornamenti? Semplice, utilizzare il nostro NMS preferito, ovvero Nagios.

nagiosIngredienti

Per prima cosa è necessario che sulla macchina da monitorare sia installato (ed attivo) il servizio NRPE_NT. Inoltre, ai plugin utilizzati dal servizio in questione, occorre aggiungere uno scrip PowerShell creato appositamente. Infine,  occorre creare su Nagios un comando ed un servizio specifico, in modo che il nostro NMS sia in grado di effettuare il controllo degli aggiornamenti in modo automatico e ad intervalli di tempo regolari.

Configurazione di NRPE_NT

Poichè la verifica della disponibilità degli aggiornamenti è un’operazione che può richiedere parecchio tempo, è necessario fare in modo che il timeout di NRPE_NT venga appositamente incrementato, editando la direttiva command_timeout presente all’interno del file nrpe.cfg (nel mio caso ho impostato una soglia pari a 600 secondi):

command_timeout= 600

Per ciò che concerne lo scrip PowerShell, esso può essere scaricato da qui, per poi posizionarlo all’interno della directory Plugins di NRPE_NT. A questo punto, sempre lato NRPE_NT, è possibile creare un comando specifico che si occuperà di verificare la disponibilità degli aggiornamenti di Windows. Tale definizione va inserita all’interno del file V2_nrpe_commands.cfg e presenta la seguente struttura:

command[get_windows_updates]=cscrip.exe //nologo //T:600 c:\nrpe\plugins\v2\check_windows_updates.wsf /w:0 /c:1

Restartiamo infine il servizio NRPE_NT mediante i comandi:

net stop NRPE_NT
net start NRPE_NT

e passiamo alla configurazione di Nagios.

Configurazione di Nagios

Come già affermato in precedenza, la configurazione dell’NMS si basa su due passaggi: la creazione del comando e l’assegnazione del check che ne fa uso ad un servizio legato all’host da monitorare.

Di seguito riporto il comando (da inserire nel file commands.cfg presente in /etc/nagios/objects):

# nagios-WMI-windows-updates check command definition

define command {
        command_name    check_WMI_windows_updates
        command_line    /usr/lib64/nagios/plugins/check_nrpe -H $HOSTADDRESS$ -t $ARG1$ -c get_windows_updates
        }

Mentre il servizio è così definito:

define service{
        use                             generic-service         ; Name of service template to use
        host_name                       Windows-Machine
        service_description             query WMI Updates for Microsoft Windows Machine
        check_command                   check_WMI_windows_updates!600
        normal_check_interval           120
        }

Da notare che l’unico parametro passato al comando riguarda il numero di secondi di attesa (600) prima del timeout. Inoltre, ho fatto in modo che i check vengano eseguiti a distanza di 2 ore l’uno dall’altro (normal_check_interval 120).

A configurazione ultimata riavviamo Nagios per rendere effettive le modifiche:

[root@NMS ~]# service nagios reload

In caso di disponibilità di aggiornamenti, il cruscotto dell’NMS ci apparirà in un modo simile al seguente:

cruscotto_nagios

Alla prossima.

Cisco 877: configurare il QoS per il traffico VOIP (SIP/RTP)

Un po’ di teoria (ToS vs DiffServ)

Il QoS (acronimo che sta ad indicare il cosiddetto Quality of Service) è una tecnica L3 per la prioritizzazione del traffico, in grado cioè di garantire una banda minima e/o bassi livelli di latenza e jitter (a seconda dei casi e delle esigenze). Tutte le politiche di QoS si basano su un campo dell’header IP, denominato DS filed (un tempo ToS – Type of Service – ormai deprecato). In particolare, esso presenta la seguente struttura:

DS5     DS4     DS3     DS2     DS1     DS0     ECN     ECN

dove i 3 bit più significativi (DS5, DS4 e DS3) rappresentano, per il ToS, alla cosiddetta IP Precedence. Ad esempio, il pattern DiffServ 101 000 indica una priorità pari a 5 (ovvero la traduzione del digit 101 in decimale). Da ciò si evince che tutte le politiche QoS basate su DiffServ che tengono conto dei soli 3 bit più significativi, sono perfettamente retrocompatibili con il  ToS (e quindi con tutti i dispositivi più datati che supportano esclusivamente tale tipologia di QoS).

NB: I 6 bit DS prendono il nome di DSCP (Differentiated Services Code Point).

Il motivo per cui il protocollo DiffServ è riuscito a soppiantare quasi completamente il ToS è molto semplice: la sua maggiore granularità nella gestione del traffico interessante (ovvero quello oggetto delle politiche di QoS) rispetto al suo predecessore.

 Ancora teoria (DiffServ PHB)

qosdiagramIl DiffServ prevede 5 tipologie di comportamento (PHB – Per Hop Behaviour) che i router attraversati da uno specifico datagramma possono intraprendere. Essi sono i seguenti:

1) Default PHB, con i bit DS  settati a  000 000 – Best Effort (aka nessuna garanzia di instradamento);

2) Expedited Forwarding (EF PHB), con i bit DS settati a 101110 – il migliore in assoluto (poichè molto affidabile, prevede bassissimi tempi di latenza e valori di jitter minimi, nonchè basse probabilità che il datagramma venga droppato);

3) Assured Forwarding (AF PHB), che fa fede alla seguente tabella:

Low Drop AF11 (DSCP 10) AF21 (DSCP 18) AF31 (DSCP 26) AF41 (DSCP 34)
Med Drop AF12 (DSCP 12) AF22 (DSCP 20) AF32 (DSCP 28) AF42 (DSCP 36)
High Drop AF13 (DSCP 14) AF23 (DSCP 22) AF33 (DSCP 30) AF43 (DSCP 38)

4) Voice Admit PHB, con i bit DS settati a 101100 – identico all’EF PHB per affidabilità e bassa latenza, si basa sul CAC (Call Admission Control);

5) Class Selector (CS PHB):  retrocompatibile con l’IP Precedence del ToS, fa fede alla seguente tabella:

DSCP    Binary     Decimal  Typical Application     Examples
CS0     000 000    0        N/A                  N/A (best effort)    
CS1     001 000    8        Scavenger            YouTube, Gaming, P2P
CS2     010 000    16       OAM                  SNMP,SSH,Syslog
CS3     011 000    24       Signaling            SCCP,SIP,H.323
CS4     100 000    32       Realtime             TelePresence
CS5     101 000    40       Broadcast video      Cisco IPVS
CS6     110 000    48       Network Control      EIGRP,OSPF,HSRP,IKE

In definitiva, è possibile utilizzare la seguente tabella per la mappatura dei pattern DSCP con l’IP Precedence:

Value Decimal Meaning Drop Probability Equivalent IP Precedence Value
 101 110 46   EF               N/A        101 Critical
 000 000  0   Best Effort      N/A        000 - Routine
 001 010 10   AF11             Low        001 - Priority
 001 100 12   AF12             Medium     001 - Priority
 001 110 14   AF13             High       001 - Priority
 010 010 18   AF21             Low        010 - Immediate
 010 100 20   AF22             Medium     010 - Immediate
 010 110 22   AF23             High       010 - Immediate
 011 010 26   AF31             Low        011 - Flash
 011 100 28   AF32             Medium     011 - Flash
 011 110 30   AF33             High       011 - Flash
 100 010 34   AF41             Low        100 - Flash Override
 100 100 36   AF42             Medium     100 - Flash Override
 100 110 38   AF43             High       100 - Flash Override

Definizione delle politiche di QoS sul router Cisco 877

Dopo questa breve carrellata teorica veniamo alla pratica. Per prima cosa occorre distinguere tra le politiche di QoS in ingresso e quelle in uscita.

Le prime si basano sul cosiddetto CAR (Committed Access Rate); per le seconde, invece, bisogna utilizzare l’accoppiata class-map/policy-map. In entrambi i casi occorre definire un’opportuna ACL per l’identificazione del traffico interessante, ad esempio:

access-list 105 remark inbound VOIP (SIP/RTP) traffic gets top priority (5) with CAR
access-list 105 permit udp any any eq 5060
access-list 105 permit udp any any range 10000 20000

Alla luce di quanto detto, per il QoS del traffico in ingresso possiamo utilizzare la seguente configurazione:

rate-limit input access-group 105 128000 65536 65536 conform-action set-prec-transmit 5 exceed-action set-prec-continue 0 
rate-limit input 13414000 13000000 13400000 conform-action transmit exceed-action drop

Per il traffico in uscita, invece, dobbiamo digitare:

class-map voice
match access-group 105

policy-map policy1
class voice
priority 128
class class-default
bandwidth 795
fair-queue

Per prima cosa abbiamo definito la class-map voice che fa uso dell’ACL precedentemente definita. La suddetta class-map andrà a popolare la policy-map policy1 (che può essere vista come una sorta di contenitore di una o più class-map), dentro la quale definiremo il traffico prioritario (grazie alla direttiva priority). Il valore si intende espresso in kbps.

La class-default, invece, consente di riservare la banda minima garantita per tutto il traffico che non rientra nel QoS, dove fair-queue è sinonimo di best effort. Anche in questo caso parliamo di kbps. Ovviamente i valori assegnati sono stati calcolati basandosi sull’uplink rate dell’interfaccia ADSL del router.

NB: per traffico prioritario si intende quello con bassa probabilità di drop e bassi valori di latenza/jitter.

L’ultimo step consiste nell’assegnazione della policy-map policy1 all’interfaccia fa0 (LAN) ed ATM0 (WAN). Per la LAN avremo:

 interface FastEthernet0
 no ip address
 service-policy output policy1

mentre per la WAN:

interface ATM0
 no ip address
 no atm ilmi-keepalive
 pvc 8/35
  vbr-nrt 923 923 1
  tx-ring-limit 3
  service-policy out policy1
  pppoe-client dial-pool-number 1
 !

In particolare, la policy-map va assegnata direttamente al PVC ATM (e non all’interfaccia dialer come ci si potrebbe aspettare), previa definizione delle direttive vbr-nrt e tx-ring-limit.

La prima è indispensabile per la politica di controllo del traffico (detta GTS Generic Traffic Shaping) supportata da questo tipo di interfaccia, dove il termine vbr-nrt sta per variable bit rate not real time (GTS ed ubr, ovvero l’undefined bit rate impostato di default sul PVC, non sono tra loro compatibili). La sintassi da utilizzare è la seguente:

vbr-nrt <Peak Cell Rate> <Sustained Cell Rate> <Maximum Burst Size>

Inoltre, per individuare i valori di PCR ed SCR ho applicato la seguente prassi:

1) ho identificato l’uplink rate della linea ADSL, utilizzando il comando:

sh atm int atm0

il cui output è simile al seguente:

VCIs per VPI: 1024,
Max. Datagram Size: 4528
PLIM Type: ADSL - 972Kbps Upstream, DMT, TX clocking: LINE

2) ho calcolato il 95% dell’ upstream rate, ed il valore risultante è servito a popolare sia PCR che SCR;

3) ho impostato l’MBR a 1.

La seconda direttiva (ovvero tx-ring-limit), serve, invece, per la gestione della coda (a livello HW) dell’interfaccia ATM. Nella fattispecie, limitando il buffer a soli 3 pacchetti, si fa in modo che la politica QoS possa essere applicata ai dati prima del loro ingresso nel buffer (dove il QoS non può più essere attuato).

Per ciò che concerne la visualizzazione delle statistiche relative al QoS (ad esempio il drop rate), è sufficiente utilizzare il comando show policy map, specificando l’interfaccia oggetto di analisi:

#sh policy-map interface atm0

il cui output sarà simile al seguente:

 ATM0: VC 8/35 -

  Service-policy output: policy1

    queue stats for all priority classes:

      queue limit 64 packets
      (queue depth/total drops/no-buffer drops) 0/0/0
      (pkts output/bytes output) 5590/3316821

    Class-map: voice (match-all)
      5590 packets, 3316821 bytes
      5 minute offered rate 0 bps, drop rate 0 bps
      Match: access-group 105
      Priority: 128 kbps, burst bytes 4470, b/w exceed drops: 0

    Class-map: class-default (match-any)
      270413 packets, 94967696 bytes
      5 minute offered rate 7000 bps, drop rate 0 bps
      Match: any
      Queueing
      queue limit 64 packets
      (queue depth/total drops/no-buffer drops/flowdrops) 0/147/0/147
      (pkts output/bytes output) 270266/94753611
      Fair-queue: per-flow queue limit 16
      bandwidth 795 kbps

Prima di concludere il post occorre fare una precisazione: ho adoperato un’ACL per la definizione del traffico interessante poichè, in questo modo, lato PBX non è stato necessario effettuare alcuna modifica di configurazione. Infatti, per utilizzare, ad esempio, una class-map così definita:

class-map match-any VOIP-SIGNAL
 match ip dscp cs5
 match ip precedence 4
 match ip precedence 3
class-map match-any VOIP-RTP
 match ip dscp ef
 match ip precedence 5

sarebbe stato necessario imporre al PBX (Asterisk nel mio caso) di “modificare” il contenuto dell’header dei pacchetti IP (DS Field) applicando un particolare pattern DSCP o un determinato valore di IP Precedence (definendo, nel file sip.conf, delle entry come tos_sip=cs3 per la segnalazione, tos_audio=ef per il traffico RTP audio e tos_video=af41 per il traffico RTP video).

E’ tutto, alla prossima.

PS: La banda che ho definito per il QoS si riferisce ad un’unica chiamata in ingresso/uscita. In particolare, essa dipende strettamente da 2 fattori, ovvero:

1) il numero di chiamate che si vogliono gestire in contemporanea;

2) il tipo di codec da utilizzare per il traffico voce (specificato all’interno del protocollo SDP, insieme alle porte coinvolte nel traffico RTP). Per maggiori dettagli sulla corrispondenza codec/banda è possibile consultare la seguente tabella:

VoIP-Codec-table-from-Cisco-sml

CentOS 6: monitorare le ACL del nostro router Cisco mediante Nagios ed snmptt

Durante gli ultimi mesi ho discusso ampiamente della configurazione di Nagios per la ricezione dei check passivi, quali trap SNMP o security alert. Adesso vi mostrerò come integrare le predette tipologie di allarmi in modo da riuscire a monitorare le ACL del nostro router Cisco.

Premessa

Esiste un modo più veloce per ottenere il monitoraggio delle ACL rispetto a quello che sto per illustrare. Esso consiste, fondamentalmente, nella configurazione di un syslog server (dotato dell’applicativo swatch per l’analisi in tempo reale dei file di log) a cui il nostro router Cisco dovrà puntare. Nel caso in cui un determinato pattern (ad esempio / denied /) dovesse essere matchato da swatch, quest’ultimo genererà un’opportuna notifica email da inoltrare all’amministratore di rete.

La mia configurazione, invece, si basa sulla logica seguente: il router Cisco genererà delle opportune trap SNMP segnalando ciò che avviene a livello di ACL (traffico consentito oppure negato). Esse verranno intercettate da snmptrapd e tradotte da snmptt, per poi essere elaborate dall’event handler submit_check_result e date in pasto a Nagios. Ho optato per tale configurazione poichè sulla mia linux box che funge da syslog server e da NMS sono già attivi sia snmptrapd che snmptt e quindi ho ritenuto conveniente sfruttarli piuttosto che mettere in funzione swatch.

nagiosConfigurazione del router Cisco

La configurazione del router Cisco si basa in 3 passaggi: settaggio della direttiva log per ciascuna entry che andrà a formare l’ACL da monitorare,  settaggio del syslog server a cui inviare le trap ed abilitazione di queste ultime.

Ad esempio, l’ACL di nostro interesse dovrà essere formata da entry di questo tipo:

access-list 102 deny ip host 255.255.255.255 any log

Inoltre, per definire la community string RO (read only) e l’indirizzo IP del server che si occuperà della ricezione delle trap, occorrerà digitare le seguenti direttive:

snmp-server host 192.168.1.1 keypublic
snmp-server community keypublic RO

mentre le trap potranno essere abilitate nel modo seguente:

snmp-server enable traps snmp authentication linkdown linkup coldstart warmstart
snmp-server enable traps tty
snmp-server enable traps config-copy
snmp-server enable traps config
snmp-server enable traps resource-policy
snmp-server enable traps cpu threshold
snmp-server enable traps syslog
snmp-server enable traps firewall serverstatus

 Contenuto dello scrip submit_check_result

Secondo quanto già riportato in questo post, sappiamo che snmptt effettua una traduzione “statica” delle trap (mediante il comando snmpttconvertmib). Per tale motivo, affinchè si possa indurre Nagios a generare dei security alert solo dopo la ricezione di trap ben determinate, occorre modificare il codice sorgente relativo all’event handler submit_check_result. Di seguito riporto il contenuto dello scrip in questione da me customizzato:

 echocmd="/bin/echo"

CommandFile="/var/spool/nagios/cmd/nagios.cmd"

# get the current date/time in seconds since UNIX epoch
datetime=`date +%s`

# create the command line to add to the command file
if [[ $1 == "ip router" ]];then

        if [[ $4 =~ "denied igmp" ]];then

                exit 0;

        elif  [[ $4 =~ "denied" ]];then

                service="Router ACL Connection Denied";

                output="$4 | connection_denied=1"
                cmdline="[$datetime] PROCESS_SERVICE_CHECK_RESULT;router;$service;$3;$output";

        else

                cmdline="[$datetime] PROCESS_SERVICE_CHECK_RESULT;router;$2;$3;$4";

        fi

else

   cmdline="[$datetime] PROCESS_SERVICE_CHECK_RESULT;$1;$2;$3;$4";

fi

# append the command to the end of the command file
`$echocmd $cmdline >> $CommandFile`

Nella fattispecie, vengono dapprima identificate le trap che riguardano il router. Successivamente, nel caso in cui esse contengano il pattern igmp denied, lo scrip uscirà senza effettuare alcuna operazione. Tale “scrematura” è stata necessaria poichè il mio ISP effettua regolarmente del polling IGMP mediante il proprio querier 192.168.100.1 (per il servizio IPTV).

Nel caso in cui, invece, le trap dovessero contenere la stringa denied, la variabile cmdline verrà popolata con l’host name dell’oggetto monitorato da Nagios (per il quale si dovrà aggiornare lo stato del servizio che si occupa di tenere d’occhio le ACL). Nel mio caso tale host name è semplicemente router. Inoltre, l’output  verrà rimaneggiato in modo da tenere traccia delle performance data (graficizzandole mediante l’uso di pnp4nagios).

MIB da utilizzare e configurazione di Nagios

Per prima cosa occorre scaricare le MIB CISCO-SYSLOG-MIB e CISCO-SYSLOG-MIB-V1SMI dal repository FTP della Cisco, effettuandone il parsing mediante snmpttconvertmib.

Successivamente, su Nagios occorrerà definire per l’host name router il servizio che si occuperà di monitorare le ACL:

define service{
        use                             local-service
        host_name                       router
        service_descripion              Router ACL Connection Denied
        check_command                   check_passive
        passive_checks_enabled          1
        active_checks_enabled           0
        max_check_attempts              1
        is_volatile                     1
        check_freshness                 1
        freshness_threshold             600
        flap_detection_enabled          0
        }

Come ultimo step, a configurazione ultimata possiamo riavviare Nagios per rendere effettive le suddette modifiche:

[root@NMS ~]# service nagios reload

ed abbiamo finito.

A presto.