Archivi tag: nms

CentOS 6: configurare Nagios/NRDP per la ricezione dei check passivi

In questo blog ho ampiamente discusso del mio MNS preferito (Nagios), mostrandone le diverse modalità di utilizzo e pubblicando, con una certa frequenza, alcuni plugin (da me realizzati) in grado di tenere sotto controllo un determinato servizio attivo su uno o più dispositivi.

Occorre precisare, però, che fin’ora ho discusso solo ed esclusivamente dei cosiddetti check attivi, ovvero quelli che vengono inizializzati dall’NMS ad intervalli di tempo specifici (di default ogni 5 minuti). Tale configurazione è più che sufficiente nella stragrande maggioranza dei casi, ma ovviamente esistono delle ecezioni.

nagiosUna di queste riguarda, ad esempio, la presenza di un firewall tra Nagios ed il server da tenere sotto controllo, il quale potrebbe bloccare i tentativi di connessione diretti verso quest’ultimo. Un’altra, invece, potrebbe riguardare l’individuazione di eventi totalmente asincroni (ad esempio le trap SNMP oppure i security alert), i quali, per loro natura, non possono essere collezionati mediante del semplice polling.

Per configurare in modo corretto i check passivi, occorre utilizzare alcuni elementi indispensabili:

1) Un tool da integrare a Nagios (NRDP Server) in grado di riconoscere gli eventi generati dai dispositivi monitorati e di girarli all’NMS;

2) Un client (NRDP Client per i sistemi *nix oppure NSCA Client per i sistemi Windows), il cui compito è quello di inviare gli eventi all’NMS.

Logica di funzionamento

NRDP Server è una Web applicaiton sviluppata in PHP, contattabile utilizzando il protocollo HTTP (o, in alternativa, HTTPS). Essa rimane in ascolto su una specifica porta (solitamente la TCP 80, ma dipende dalla configurazione dei Web server), in attesa degli eventi generati dai client NRDP. Nella fattispecie, anche in quest’ultimo caso, parliamo di uno scrip PHP il cui scopo è quello di generare un codice XML (in base ai parametri che gli vengono dati in pasto), da inoltrare al server. A questo punto, dopo aver ricevuto l’evento, il server NRDP popolerà il file nagios.cmd con una stringa che reca il seguente formato:

PROCESS_SERVICE_CHECK_RESULT;host;servicedescription;checkresult;output

ad esempio:

PROCESS_SERVICE_CHECK_RESULT;mysql-server1;test;1;questo è un evento di test

In seguitò verrà generato un file temporaneo all’interno della directory /var/log/nagios/spool/checkresults, il quale verrà poi processato da Nagios per l’aggiornamento dello status del servizio interessato.

Installazione e configurazione di NRDP Server

Per prima cosa scarichiamo il suddetto applicativo e scompattiamo l’archivio:

[root@linuxbox ~]# cd /usr/local

[root@linuxbox ~]# wget https://assets.nagios.com/downloads/nrdp/nrdp.zip

[root@linuxbox local]# unzip nrdp.zip

[root@linuxbox local]# chown -R nagios:nagios /usr/local/nrdp

Creiamo quindi la directory in cui Nagios dovrà salvare i file temporanei (/var/log/nagios/spool/tmp):

[root@linuxbox local]# mkdir /var/log/nagios/spool/tmp

[root@linuxbox local]# chown apache:nagios /var/log/nagios/spool/tmp

[root@linuxbox local]# chmod 770 /var/log/nagios/spool/tmp

Inoltre, poichè NRDP Server gira grazie ad un Web server opportuno (ad esempio Apache), è necessario fare in modo che nella directory /var/log/nagios/spool/checkresults/ (in cui Nagios salverà i risultati dei check attivi e passivi utilizzando dei file temporanei), Apache abbia i diritti di lettura e scrittura:

[root@linuxbox local]# chown apache:nagios /var/log/nagios/spool/checkresults

[root@linuxbox local]# chmod 770 /var/log/nagios/spool/checkresults

A questo punto possiamo dedicarci alla configurazione vera e propria di NRDP Server, editando il file /usr/local/nrdp/server/config.inc.php.

Di seguito riporto quella da me utilizzata:

$cfg['authorized_tokens'] = array(
"vostrotoken",
);
$cfg["nagios_command_group"]="nagios";
// full path to Nagios external command file
$cfg["command_file"]="/var/spool/nagios/cmd/nagios.cmd";
// full path to check results spool directory
$cfg["check_results_dir"]="/var/log/nagios/spool/checkresults";
// full path to directory where temp scratch files can be written
// NOTE: the Apache user need to be able create files here, and the Nagios user needs to read/delete those same files, so the /tmp system directory won't work (it has a sticky bit on it)
$cfg["tmp_dir"]="var/log/nagios/spool/tmp";

Passiamo ora alla configurazione di Apache, creando un file opportuno (nrdp.conf) all’interno della directory /etc/httpd/conf.d, il cui contenuto dovrebbe essere simile al seguente:

Alias /nrdp "/usr/local/nrdp/server"

<Directory "/usr/local/nrdp">
   Options None
   AllowOverride None
   Order allow,deny
   Allow from all
   Order deny,allow
   Deny from all
   Allow from <IP1>
   Allow from <IP2>
   Allow from <IP3>
</Directory>

Come si può notare, ho consentito l’accesso alla suddetta pagina Web solo a determinati indirizzi IP (quelli di management e quelli dei server che devono inviare i check a Nagios/NRDP).

Ricarichiamo la configurazione di Apache per rendere effettive le suddette modifiche:

[root@linuxbox local]# service httpd reload

e finalmente NRDP Server dovrebbe essere attivo e funzionante. Per esserne sicuri al 100% conviene contattare la seguente URL:

http://IPNAGIOS/nrdp

e popolare il campo Token: con quello da noi inserito nella configurazione del server (config.inc.php), lasciando il campo Check Data: inalterato. Se entrambi i check vegnono processati correttamente da NRDP Server significa che il suddetto applicativo sta funzionando come dovrebbe.

Un consiglio: verificate che anche l’invio dei comandi via NRDP Server vada a buon fine (attraverso la sezione Submit Nagios Command:), in modo da scongiurare eventuali blocchi perpetrati da SElinux.

Installazione e configurazione di NRDP Client

Il primo step per mettere in funzione il suddetto client consiste nel copiarlo sui server da monitorare:

[root@linuxbox ~]# scp /usr/local/nrdp/client/send_nrdp.php root@serverdamonitorare:/usr/lib64/nagios/plugins

Una volta fatto ciò si può procedere con l’invio di un check di prova, utilizzando, ad esempio, la seguente sintassi:

[root@linuxbox ~]# /usr/bin/php send_nrdp.php --url=http://IPNAGIOS/nrdp --token="vostrotoken" --host="mysql-server" --state="1" --service="Test" --output="Questo è un evento di test"

Per una maggiore compatibilità con il sistema ospite, consiglio di modificare lo scrip send_nrdp.php, sostituendo il tag di apertura <? con <?php. Inoltre, se si vuole fare un pò di troubleshooting, conviene decommentare alcune parti di codice, ad esempio:

 echo "XML=\n$xml\n";

linea 162;

echo "URL=$theurl\n";

linea 168;

echo "RESULT=\n";
print_r($result);

linee 177 e 178.

Configurazione di Nagios

Come ultimo passo procediamo con la creazione del servizio in grado di ricevere i check passivi, associandolo ad un determinato host.

Ad esempio:

 define service{
        use                   local-service
        host_name             localhost
        service_description   Test
        check_command         check_passive
        passive_checks_enabled  1
        active_checks_enabled   0
        is_volatile             1
        check_freshness         1
        freshness_threshold     600
        flap_detection_enabled  0
        }

In particolare, ho abilitato le opzioni is_volatile, check_freshness e freshness_threshold. La prima serve a far generare un alert anche nel caso in cui vi sia solo una variazione dell’output restituito dal check (e non necessariamente un cambio di stato); la seconda serve a verificare che un determinato evento venga ricevuto entro un tempo limite (espresso in secondi), specificato mediante la terza direttiva, ovvero freshness_threshold.

Inoltre ho disabilitato la flap detection, poichè i check passivi possono cambiare stato molto frequentemente ed è mia intenzione tenere traccia (mediante alert) di tutti gli eventi.

Per ciò che concerne il comando check_passive (definito in /etc/nagios/objects/commands.cfg), esso presenta la seguente struttura:

# 'check_passive' command definition
define command{
        command_name check_passive
        command_line $USER1$/check_dummy 2 "No alerts received in 600 seconds"
}

dove l’applicativo check_dummy non fa altro che restituire lo stato (in questo caso 2, ovvero CRITICAL), affiancato da un’opportuna descrizione (No alerts received in 600 seconds).

Ricarichiamo la configurazione di Nagios:

[root@linuxbox local]# service nagios reload

ed abbiamo finito. Alla prossima

check_noise_margin e check_attenuation: script Nagios per verificare la qualità della nostra linea ADSL

Premessa

Vi sono numerosi fattori che possono influenzare negativamente o positivamente la qualità della nostra linea ADSL, ma i più importanti sono sicuramente il rapporto segnale rumore (SNR o noise margin) e l’attenuazione.

In particolare, nel primo caso un valore elevato indica una qualità migliore; viceversa, nel secondo caso, un valore elevato indica una qualità peggiore. Inoltre, i valori di attenuazione sono molto influenzati dalla distanza che intercorre tra la nostra abitazione e la centrale di zona dell’ISP (va da se che maggiore sarà questa distanza, maggiore sarà l’attenuazione).

Esistono comunque dei valori di massima (sia per l’SNR che per l’attenuazione) sui quali ci si può basare per fare una stima qualitativa del nostro collegamento ADSL. Li riporto di seguito:

SNR

1) <= 6dB : pessimo, numerosi errori si sincronizzazione con la portante;
2) tra i 7dB ed i 10dB: scarso;
3) tra gli 11dB ed i 20dB: buono;
4) tra i 20dB ed i 28dB: eccellente;
5) >= 29dB: eccezionale.

 Attenuazione

1) < = 20dB: eccezionale;
2) tra i 20dB ed i 30dB: eccellente:
3) tra i 30dB ed i 40dB: molto buona;
4) tra i 40dB ed i 50dB: buona;
5) tra i 50dB ed i 60dB: scarsa, con diversi errori di connessione.
6) >= 60dB: pessima, con numerosi errori di connessione.

Tenendo conto dei suddetti valori, ho deciso di realizzare 2 scrip bash (da integrare a Nagios), in modo da tenere traccia dei valori di SNR ed attenuazione relativi alla mia linea ADSL. Il router di riferimento è un Cisco 877.

Entrambi gli scrip in questione (check_noise_margin e check_attenuation), si basano su un ulteriore scrip expect (get_dsl_info) che esegue la query sul router, lanciando il comando sh dsl int atm0.

Il contenuto di tale scrip è il seguente:

#!/usr/bin/expect

set ip [lindex $argv 0]
set password1 [lindex $argv 1]
set password2 [lindex $argv 2]

spawn ssh -l nightfly "$ip"
expect "*?assword:*"
send "$password1\r"
expect ">"
send "ena\r"
expect "Password:"
send "$password2\r"
expect "#"
send "sh dsl int atm0\r"
send " "
expect "#"
send "exit\r"
expect eof

L’output da esso generato verrà quindi dato in pasto ed elaborato da check_noise_margin e da check_attenuation. Il loro contenuto è molto simile ed è (rispettivamente):

#!/bin/bash

host=$1
password1=$2
password2=$3
warning=$4
critical=$5

usage="check_noise_margin <host> <password1> <password2> <warning> <critical>"

if [ -n "$host" ]; then

        if [ -n "$password1" ];then

                if [ -n "$password2" ];then

                        if [ -n "$warning" ];then

                                if [ -n "$critical" ];then

                                        if [ "$critical" -gt "$warning" ];then

                                                echo "UNKNOWN: critical has to be less than warning"
                                                exit 3;

                                        else

                                                output=`/usr/lib64/nagios/plugins/get_dsl_info $1 $2 $3 | grep "Noise"  | awk -F " " '{print $3,$5}'`
                                                output1=`echo $output | awk '{print $1}'`
                                                output2=`echo $output | awk '{print $2}'`
                                                unit="db"
                                        fi

                                        if [ -n "$output" ];then

                                                if [ $(echo "$output1 < $critical" | bc) -eq 1 -o $(echo "$output2 < $critical" | bc) -eq 1 ];then

                                                        echo "CRITICAL: downstream noise margin is $output1 db, upstream noise margin is $output2 db | downstream_noise_margin=$output1$unit;$warning;$critical upstream_noise_margin=$output2$unit;$warning;$critical";
                                                        exit 2;

                                                elif [ $(echo "$output1 > $critical" | bc) -eq 1 -a  $(echo "$output1 < $warning" | bc) -eq 1 -o $(echo "$output2 > $critical" | bc) -eq 1 -a $(echo "$output2 < $warning"  |bc) -eq 1 ];then

                                                        echo "WARNING: downstream noise margin is $output1 db, upstream noise margin is $output2 db| downstream_noise_margin=$output1$unit;$warning;$critical upstream_noise_margin=$output2$unit;$warning;$critical" ;
                                                        exit 1;

                                                else

                                                        echo "OK: downstream noise margin is $output1 db, upstream noise margin is $output2 db | downstream_noise_margin=$output1$unit;$warning;$critical upstream_noise_margin=$output2$unit;$warning;$critical";
                                                        exit 0;

                                                fi
                                        else

                                                echo "UNKNOWN: output is null"
                                                exit 3;

                                        fi

                                else

                                        echo "$usage"
                                        exit 3;
                                fi

                        else

                                echo "$usage"
                                exit 3;
                        fi

                else

                        echo "$usage"
                        exit 3;
                fi
        else

                echo "$usage"
                exit 3;
        fi

else

        echo "$usage"
        exit 3;

fi

per check_noise_margin, e:

#!/bin/bash

host=$1
password1=$2
password2=$3
warning=$4
critical=$5

usage="check_attenuation <host> <password1> <password2> <warning> <critical>"

if [ -n "$host" ]; then

        if [ -n "$password1" ];then

                if [ -n "$password2" ];then

                        if [ -n "$warning" ];then

                                if [ -n "$critical" ];then

                                        if [ "$critical" -lt "$warning" ];then

                                                echo "UNKNOWN: critical has to be greater than warning"
                                                exit 3;

                                        else

                                                output=`/usr/lib64/nagios/plugins/get_dsl_info $1 $2 $3 | grep "Attenuation"  | awk -F " " '{print $2, $4}'`

                                                output1=`echo $output | awk '{print $1}'`
                                                output2=`echo $output | awk '{print $2}'`
                                                unit="db"
                                        fi

                                        if [ -n "$output" ];then

                                                if [ $(echo "$output1 > $critical" | bc) -eq 1 -o $(echo "$output2 > $critical" | bc) -eq 1 ];then

                                                        echo "CRITICAL: downstream attenuation is $output1 db, upstream attenuation is $output2 db | downstream_attenuation=$output1$unit;$warning;$critical upstream_attenuation=$output2$unit;warning;$critical";
                                                        exit 2;

                                                elif [ $(echo "$output1 < $critical" | bc) -eq 1 -a  $(echo "$output1 > $warning" | bc) -eq 1 -o $(echo "$output2 < $critical" | bc) -eq 1 -a  $(echo "$output2 > $warning" | bc) -eq 1 ];then

                                                        echo "WARNING: downstream attenuation is $output1 db, upstream attenuation is $output2 db | downstream_attenuation=$output1$unit;$warning;$critical upstream_attenuation=$output2$unit;$warning;$critical";
                                                        exit 1;

                                                else

                                                        echo "OK: downstream attenuation is $output1 db, upstream attenuation is $output2 db | downstream_attenuation=$output1$unit;$warning;$critical upstream_attenuation=$output2$unit;$warning;$critical";
                                                        exit 0;

                                                fi
                                        else

                                                echo "UNKNOWN: output is null"
                                                exit 3;

                                        fi

                                else

                                        echo "$usage"
                                        exit 3;
                                fi

                        else

                                echo "$usage"
                                exit 3;
                        fi

                else

                        echo "$usage"
                        exit 3;
                fi
        else

                echo "$usage"
                exit 3;
        fi

else

        echo "$usage"
        exit 3;

fi

per check_attenuation.

Da notare che in entrambi i casi ho aggiunto le perfdata da dare in pasto a pnp4nagios. Inoltre, poichè i valori restituiti possono contenere dei decimali, ho dovuto utilizzare il comando bc per i calcoli aritmetici. Ciò si è reso necessario poichè bash tratta nativamente le variabili come stringhe.

Una volta fatto ciò, ho semplicemente creato i comandi per Nagios:

# 'check_noise_margin' command definition
 define command{
 command_name    check_noise_margin
 command_line    $USER1$/check_noise_margin $HOSTADDRESS$ $ARG1$ $ARG2$ $ARG3$ $ARG4$
 }
# 'check_attenuation' command definition
 define command{
 command_name    check_attenuation
 command_line    $USER1$/check_attenuation $HOSTADDRESS$ $ARG1$ $ARG2$ $ARG3$ $ARG4$
 }

collegandoli, successivamente, ai servizi del router Cisco:

define service{
 use                             local-service         ; Name of service template to use
 host_name                       router
 service_descripion             Noise Margin
 check_command                   check_noise_margin!pass1!pass2!10!6
 }
define service{
 use                             local-service         ; Name of service template to use
 host_name                       router
 service_descripion             Attenuation
 check_command                   check_attenuation!pass1!pass2!51!61
 }

Infine, ho lanciato un reload del servizio:

[root@nightbox objects]# service nagios reload

e finalmente la qualità della mia linea ADSL è sotto monitoraggio.

Alla prossima.

PS: per chi le preferisse, ecco le varianti in Perl dei suddetti scrip:

#!/usr/bin/perl

use strict;
use warnings;

my $host=$ARGV[0];
my $password1=$ARGV[1];
my $password2=$ARGV[2];
my $warning=$ARGV[3];
my $critical=$ARGV[4];

my $usage="check_noise_margin.pl <host> <password1> <password2> <warning> <critical>";

if ($host ne "") {
        if ($password1 ne "")
        {
                if ($password2 ne "")
                {
                        if ($warning ne "")
                        {
                                if ($critical ne "")
                                {
                                        if ($critical > $warning)
                                        {
                                                print "UNKNOWN: critical has to be less than warning";
                                                exit 3;
                                        }
                                        else
                                        {
                                                my $output=`/usr/lib64/nagios/plugins/get_dsl_info $host $password1 $password2 | /bin/grep "Noise"`;

                                                if($output ne "")
                                                {

                                                        my @columns = split /\s+/, $output;
                                                        my $downstream = $columns[2];
                                                        my $upstream = $columns[4];
                                                        my $unit = "db";

                                                        if ($downstream < $critical || $upstream < $critical)
                                                        {
                                                                print "CRITICAL: downstream noise margin is $downstream db; upstream noise margin is $upstream db | downstream_noise_margin=$downstream$unit;$warning;$critical upstream_noise_margin=$upstream$unit;$warning;$critical\n";
                                                                exit 2;
                                                        }
                                                        elsif ($downstream > $critical && $downstream < $warning || $upstream > $critical && $upstream < $warning)
                                                        {
                                                                print "WARNING: downstream noise margin is $downstream db; upstream noise margin is $upstream db | downstream_noise_margin=$downstream$unit;$warning;$critical upstream_noise_margin=$upstream$unit;$warning;$critical\n";
                                                                exit 1;
                                                        }
                                                        else
                                                        {
                                                                print "OK: downstream noise margin is $downstream db, upstream noise margin is $upstream db | downstream_noise_margin=$downstream$unit;$warning;$critical upstream_noise_margin=$upstream$unit;$warning;$critical\n";
                                                                exit 0;
                                                        }
                                                }
                                                else
                                                {
                                                                print "UNKNOWN: output is null";
                                                                exit 3;
                                                }
                                        }
                                }
                                else
                                {
                                        print "$usage";
                                        exit 3;
                                }
                        }
                        else
                        {
                                print "$usage";
                                exit 3;
                        }
                }
                else
                {
                        print "$usage";
                        exit 3;
                }
        }
        else
        {
                print "$usage";
                exit 3;
        }
}
else
{
        print "$usage";
        exit 3;
}

e

#!/usr/bin/perl

use strict;
use warnings;

my $host=$ARGV[0];
my $password1=$ARGV[1];
my $password2=$ARGV[2];
my $warning=$ARGV[3];
my $critical=$ARGV[4];

my $usage="check_attenuation.pl <host> <password1> <password2> <warning> <critical>";

if ($host ne "") {
        if ($password1 ne "")
        {
                if ($password2 ne "")
                {
                        if ($warning ne "")
                        {
                                if ($critical ne "")
                                {
                                        if ($critical < $warning)
                                        {
                                                print "UNKNOWN: critical has to be more than warning";
                                                exit 3;
                                        }
                                        else
                                        {
                                                my $output=`/usr/lib64/nagios/plugins/get_dsl_info $host $password1 $password2 | /bin/grep "Attenuation"`;

                                                if($output ne "")
                                                {

                                                        my @columns = split /\s+/, $output;
                                                        my $downstream = $columns[1];
                                                        my $upstream = $columns[3];
                                                        my $unit = "db";

                                                        if ($downstream > $critical || $upstream > $critical)
                                                        {
                                                                print "CRITICAL: downstream attenuation is $downstream db; upstream attenuation is $upstream db | downstream_attenuation=$downstream$unit;$warning;$critical upstream_attenuation=$upstream$unit;$warning;$critical\n";
                                                                exit 2;
                                                        }
                                                        elsif ($downstream < $critical && $downstream > $warning || $upstream < $critical && $upstream > $warning)
                                                        {
                                                                print "WARNING: downstream attenuation is $downstream db; upstream attenuation is $upstream db | downstream_attenuation=$downstream$unit;$warning;$critical upstream_attenuation=$upstream$unit;$warning;$critical\n";
                                                                exit 1;
                                                        }
                                                        else
                                                        {
                                                                print "OK: downstream attenuation is $downstream db, upstream attenuation is $upstream db | downstream_attenuation=$downstream$unit;$warning;$critical upstream_attenuation=$upstream$unit;$warning;$critical\n";
                                                                exit 0;
                                                        }
                                                }
                                                else
                                                {
                                                                print "UNKNOWN: output is null";
                                                                exit 3;
                                                }
                                        }
                                }
                                else
                                {
                                        print "$usage";
                                        exit 3;
                                }
                        }
                        else
                        {
                                print "$usage";
                                exit 3;
                        }
                }
                else
                {
                        print "$usage";
                        exit 3;
                }
        }
        else
        {
                print "$usage";
                exit 3;
        }
}
else
{
        print "$usage";
        exit 3;
}

PPS: se sul vostro router è stato abilitato il protocollo SNMP, gli OID che consentono di monitorare SNR ed attenuazione sono i seguenti:

.1.3.6.1.2.1.10.94.1.1.3.1.5.11 = downstream attenuation 
.1.3.6.1.2.1.10.94.1.1.2.1.5.11 = upstream attenuation 
.1.3.6.1.2.1.10.94.1.1.3.1.4.11 = downstream noise margin
.1.3.6.1.2.1.10.94.1.1.2.1.4.11 = upstream noise margin

In particolare, l’ultima parte dell’OID (.11) si riferisce all’Interface Index della Dialer (nel mio caso si tratta della Dialer0).

Configurare il protocollo SNMP su un router Cisco 2811

In questo post abbiamo visto come configurare una linux box affinchè possa ricevere le trap SNMP. Adesso vedremo come configurare il portocollo SNMP (sia polling che trap) su un router Cisco 2811.

cisco2811Configurazione generica

Per prima cosa occorre accedere alla CLI del router in modalità ena e successivamente lanciare i seguenti comandi:

Router# conf t
Router(config)# snmp-server host <IP> keypublic
Router(config)# snmp-server community keypublic RO
Router(config)# snmp-server community keyprivate RW

Mediante il primo comando stiamo definento l’host target delle trap SNMP, mentre con il secondo ed il terzo comando specifichiamo rispettivamente la community string in lettura e quella in scrittura.

Abilitazione delle trap

A questo punto possiamo definire le trap che dovranno essere inviate alla nostra linux box, ad esempio:

Router(config)# snmp-server enable traps snmp
Router(config)# snmp-server enable traps vrrp
Router(config)# snmp-server enable traps hsrp
Router(config)# snmp-server enable traps tty
Router(config)# snmp-server enable traps ethernet cfm cc
Router(config)# snmp-server enable traps ethernet cfm crosscheck
Router(config)# snmp-server enable traps memory
Router(config)# snmp-server enable traps config-copy
Router(config)# snmp-server enable traps config
Router(config)# snmp-server enable traps resource-policy
Router(config)# snmp-server enable traps pppoe
Router(config)# snmp-server enable traps cpu
Router(config)# snmp-server enable traps syslog
Router(config)# snmp-server enable traps isakmp policy add
Router(config)# snmp-server enable traps isakmp policy delete
Router(config)# snmp-server enable traps isakmp tunnel start
Router(config)# snmp-server enable traps isakmp tunnel stop
Router(config)# snmp-server enable traps ipsec cryptomap add
Router(config)# snmp-server enable traps ipsec cryptomap delete
Router(config)# snmp-server enable traps ipsec cryptomap attach
Router(config)# snmp-server enable traps ipsec cryptomap detach
Router(config)# snmp-server enable traps ipsec tunnel start
Router(config)# snmp-server enable traps ipsec tunnel stop
Router(config)# snmp-server enable traps ipsec too-many-sas

Inutile dire che la tipologia di trap da abilitare dipende strettamente dalla configurazione del router, dalle feature abilitate (VPN IPsec), dal tipo di connessione WAN (PPP), ecc.

Polling SNMP tramite Nagios

Premesso che gli OID SNMP possono variare in base alla versione di IOS installata sul nostro router (a tal proposito vi consiglio di consultare questo sito), per prima cosa occorre definire i comandi specifici (all’interno dei file /etc/nagios/object/commands.cfg) che dovranno essere utilizzati dal nostro NMS per interrogare il dispositivo target.

Eccone un esempio:

# 'check_snmp_if_status' command definition
define command{
        command_name    check_snmp_if_status
        command_line    $USER1$/check_snmp -t 20 -H $HOSTADDRESS$ -C $ARG1$ -o $ARG2$ -r $ARG3$
        }
# 'check_snmp_cpu_load' command definition

define command{
        command_name    check_snmp_cpu_load
        command_line    $USER1$/check_snmp -t 20 -H $HOSTADDRESS$ -C $ARG1$ -o $ARG2$ -w $ARG3$ -c $ARG4$
        }

# 'check_snmp_used_memory' command definition

define command{
        command_name    check_snmp_used_memory
        command_line    $USER1$/check_snmp -t 20 -H $HOSTADDRESS$ -C $ARG1$ -o $ARG2$ -w $ARG3$ -c $ARG4$
        }

# 'check_snmp_uptime' command definition

define command{
        command_name    check_snmp_uptime
        command_line    $USER1$/check_snmp -t 20 -H $HOSTADDRESS$ -C $ARG1$ -o $ARG2$ -w $ARG3$ -c $ARG4$
        }

Infine, definiamo i servizi che si avvarranno dei suddetti comandi:

define service{
 use                             local-service         ; Name of service template to use
 host_name                       cisco
 service_description             Uptime
 check_command                   check_snmp_uptime!keypublic!.1.3.6.1.6.3.10.2.1.3.0!@61:900!@0:60
 }
define service{
 use                             local-service         ; Name of service template to use
 host_name                       cisco
 service_description             Last Minute CPU Load
 check_command                   check_snmp_cpu_load!keypublic!.1.3.6.1.4.1.9.2.1.57.0!80!90
 }
define service{
 use                             local-service         ; Name of service template to use
 host_name                       cisco
 service_description             Last 5 Minutes CPU Load
 check_command                   check_snmp_cpu_load!keypublic!.1.3.6.1.4.1.9.2.1.58.0!80!90
 }
define service{
 use                             local-service         ; Name of service template to use
 host_name                       cisco
 service_description             Used Memory
 check_command                   check_snmp_used_memory!keypublic!1.3.6.1.4.1.9.9.48.1.1.1.5.1!100000000!120000000
 }
define service{
 use                             local-service         ; Name of service template to use
 host_name                       cisco
 service_description             Status Interface WAN
 check_command                   check_snmp_if_status!keypublic!.1.3.6.1.2.1.2.2.1.8.1!1
 }
define service{
 use                             local-service         ; Name of service template to use
 host_name                       cisco
 service_description             Status Interface LAN
 check_command                   check_snmp_if_status!keypublic!.1.3.6.1.2.1.2.2.1.8.2!1
 }

A questo punto sarà sufficiente ricaricare la configurazione di Nagios mediante il comando:

[root@linuxbox ~]# service nagios reload

ed abbiamo finito.

Alla prossima.

check_arptables: script Nagios per verificare lo stato di arptables_jf

In questo post ho discusso della configurazione di LVS in modalità Direct Routing. Tale configurazione richiedeva l’installazione e la corretta configurazione di arptables_jf per la gestione delle richieste ARP dirette ai frontend. Adesso vedremo come verificare l’effettivo funzionamento del suddetto applicativo attraverso l’NMS open source per eccellenza, Nagios.

nagiosCreazione dell’eseguibile e configurazione dell’NMS

Il codice bash che ho creato per effettuare i controlli sullo status di arptables_jf è il seguente:

#!/bin/bash

host=$1
warning=$2
critical=$3

usage="check_arptables <host> <warning> <critical>"

if [ -n "$host" ]; then

        if [ -n "$warning" ];then

                if [ -n "critical" ];then

                        if [ "$warning" -lt "$critical" ];then

                                echo "UNKNOWN: warning has to be greater than critical"
                                exit 3;

                        else

                                output=`sudo arptables -L | grep -v Chain | grep -v target | wc -l`

                                if [ "$output" -le "$critical" ];then

                                        echo "CRITICAL: total number of rules is $output";
                                        exit 2;

                                elif [ "$output" -gt "$critical"  -a  "$output" -le "$warning" ];then

                                        echo "WARNING: total number of rules is $output";
                                        exit 1;

                                else

                                        echo "OK: total number of rules is $output";
                                        exit 0;

                                fi
                        fi
                else

                        echo "$usage"
                        exit 3;

                fi
        else

                echo "$usage"
                exit 3;

        fi
else

        echo "$usage"
        exit 3;

fi

Il suddetto codice è abbastanza esplicativo: dopo aver verificato la presenza di tutti i parametri richiesti e la loro consistenza (ovvero la soglia di warning deve essere strettamente maggiore di quella di critical), viene effettuato il conteggio delle regole arptables attive sul frontend monitorato. Il comando principale è il seguente:

sudo arptables -L | grep -v Chain | grep -v target | wc -l

Da notare che è presente la direttiva sudo poichè l’applicativo arptables richiede i privilegi di root per essere eseguito. Rendiamo il suddetto codice eseguibile:

[root@NMS ~]# chmod +x check_arptables

e copiamolo nella directory /usr/lib64/nagios/plugins del frontend:

[root@NMS ~]# scp check_arptables root@frontend.dominio.com:/usr/lib64/nagios/plugins

Ora è possibile, all’interno della configurazione di Nagios, definire il comando da lanciare per monitorare arptables sul frontend (all’interno del file /etc/nagios/commands.cfg):

# 'check_remote_arptables' command definition
define command{
        command_name    check_remote_arptables
        command_line    $USER1$/check_by_ssh -H $HOSTADDRESS$ -C "/usr/lib64/nagios/plugins/check_arptables $ARG1$ $ARG2$ $ARG3$"
        }

Tale comando non fa altro che connettersi al frontend via SSH (senza password, mediante un semplice scambio di chiavi RSA) e lanciare l’eseguibile precedentemente creato.

Nella configurazione di Nagios relativa allo specifico frontend, invece, occorre creare un servizio simile al seguente:

define service{
        use                             local-service         ; Name of service template to use
        host_name                       frontend.dominio.com
        service_description             Arptables Rules Status
        check_command                   check_remote_arptables!localhost!3!2
        notifications_enabled           0
        }

Configurazione del frontend

Sul frontend è sufficiente editare il file /etc/sudoers per consentire all’utente nagios di lanciare il comando arptables senza sessione TTY e senza richiesta di inserimento della password. Nella fattispecie, nel primo caso è sufficiente commentare la direttiva:

#Defaults requiretty

mentre nel secondo caso occorre inserire la seguente stringa:

nagios  ALL=(root)      NOPASSWD: /sbin/arptables

A configurazione del frontend terminata possiamo lanciare sull’NMS il comando:

[root@NMS ~]# service nagios reload

ed abbiamo finito.

Ora arptables è correttamente monitorato.

Alla prossima.

Nagios e gli event handlers

Come già affermato in più occasioni, Nagios è sicuramente uno dei migliori NMS open source in circolazione.  Esso mette a disposizione del sysadmin tutta una serie di funzioni utilissime per verificare lo stato di salute relativo agli host monitorati e consente, in alcune circostanze, di gestire i downtime in modo automatico (ad esempio riavviando il servizio che ha generato lo status di tipo CRITICAL).

Nagios_logo_blackTale gestione automatica dei downtime viene realizzata attraverso i cosiddetti event handlers. Vediamo come configurarli.

Per prima cosa è necessario creare un comando simile al seguente, editando il file /etc/nagios/object/commands.cfg

define command {
command_name      flushcache
command_line      /usr/lib/nagios/plugins/eventhandlers/flushcache $HOSTADDRESS$ $SERVICESTATE$ $SERVICESTATETYPE$ $SERVICEATTEMPT$
}

Nella fattispecie, il suddetto comando utulizza l’eseguibile flushcache, il cui compito è quello connettersi alla macchina target e di cancellare la cache del sistema operativo in caso di memory leak.

Occorre ora configurare l’event handler all’interno del servizio che si occupa del monitoraggio della RAM:

define service{        
use                            local-service              host_name                       vostrohost.vostrodominio.it        service_description             FREE RAM        check_command                   check_remote_ram!10!5        event_handler                   flushcache        notifications_enabled           0        
}

A questo punto la configurazione di Nagios può ritenersi ultimata. Non ci rimane che creare l’eseguibile flushcache all’interno della directory /usr/lib/nagios/plugins/eventhandlers/:

[root@NMS eventhandlers]# nano flushcache

il cui contenuto dovrà essere il seguente:

#!/bin/bash
if [ -n "$1" ];then
        case "$2" in
        OK)
                ;;
        WARNING)
                ;;
        UNKNOWN)
                ;;
        CRITICAL)
                case "$3" in
                SOFT)
                        case "$4" in
                        3)
                                echo -n "Flushing cache memory (3rd soft critical state)..."
                                /usr/lib/nagios/plugins/eventhandlers/connect_server.sh $1
                                ;;
                                esac
                        ;;
                HARD)
                        echo -n "Flushing cache memory..."
                        /usr/lib/nagios/plugins/eventhandlers/connect_server.sh $1
                        ;;
                esac
                ;;
        esac
else
        echo "Usage: flushcache <hostname>"
fi

exit 0

Dove $1 è la variabile $HOSTADDRESS$, $2 è il $SERVICESTATE$, $3 è il $SERVICESTATETYPE$ e $4 è il $SERVICEATTEMPT$ (sono semplicemente le variabili utilizzate nella definizione del comando flushcache in command.cfg).

Premesso che per il tipo di servizio local-service il max_check_attempts è impostato a 4 (nel file template.cfg), il suddetto codice bash non fa altro che interrogare la macchina target ($HOSTADDRESS), ricavando il $SERVICESTATE$ (OK, WARNING, UNKNOWN o CRITICAL), il $SERVICESTATETYPE$ (SOFT oppure HARD) ed il $SERVICEATTEMPT$ (ovvero il numero di check già eseguiti da Nagios nel caso in cui il $SERVICESTATE$ sia diverso da OK).

Il suddetto eseguibile prevede delle operazioni solo se il $SERVICESTATE$ è di tipo CRITICAL: in tal caso, al terzo check consecutivo (siamo ancora in SOFT state – parliamo di HARD state solo se il $SERVICESTATE$ è ancora CRITICAL dopo il quarto check), verrà lanciato l’eseguibile connect_server.sh (expect) che si occuperà di svuotare la cache della macchina monitorata. La suddetta operazione verrà eseguita nuovamente appena il $SERVICESTATETYPE$ passerà da SOFT a HARD.

Inoltre, tale eseguibile prevede come unico parametro in ingresso l’IP dell’host, ovvero $HOSTADDRESS$ (connect_server.sh $1).

Di seguito il sorgente relativo a connect_server.sh:

#!/usr/bin/expect

set hostname [lindex $argv 0]
set password "vostrapass"

spawn ssh -l root $hostname
expect "*assword:"
send "$password\n"
expect "#"
send "sync && echo 3 > /proc/sys/vm/drop_caches\n"
expect "#"
send "exit\n"
expect eof

Nella fattispecie, il comando vero e proprio che si occupa dello svuotamento della cache sulla macchina target è:

sync && echo 3 > /proc/sys/vm/drop_caches

A questo punto possiamo ricaricare la configurazione di Nagios per rendere effettive le suddette modifiche:

[root@NMS eventhandlers]# service nagios reload

ed abbiamo finito.

A presto.

Nagios e contenuti Web: script per verificare il codice HTML del nostro sito Internet

In questo blog ho dedicato diversi post a Nagios, essendo, a mio avviso, uno dei migliori NMS open source in circolazione. Tra i vari plugin messi a disposizione dal suddetto software di monitoraggio vi è check_http, il quale è in grado di inviare delle richieste apposite al sito Web che intendiamo monitorare, segnalando eventuali problemi di connessione o errori di protocollo (401, 403, 404, 500, ecc.).

nagiosSpesso, però, si rende necessario verificare anche che il contenuto del sito Web sia effettivamente visualizzato dall’utente finale (cosa non sempre vera, soprattutto quando si ha un’infrastruttura costituita na N frontend che contattano N server API per “popolare” la pagina Web da offire ai client). Per questo motivo ho deciso di creare il seguente script, in grado di saggiare il contenuto del sito Web:

#!/bin/bash

if [ -n "$1" ];then
 result=`curl -s $1 | grep ng-controller=\"Main\"`
 if [ -n "$result" ]; then
       echo "OK"
       exit 0
 else
       echo "CRITICAL"
       exit 2
 fi
else
      echo "Usage: check_content <URL>"
fi

exit 0

Il suo funzionamento è abbastanza banale. Sostanzialmente esegue una chiamata curl al sito target, cercando un determinato pattern nel sorgente della pagina Web (in questo caso la stringa cercata è ng-controller=\”Main\”).

Se il suddetto pattern viene trovato, l’eseguibile esce con status 0 (OK), altrimenti restituisce un errore di tipo CRITICAL (exit 2).

Ovviamente occorre scegliere la stringa da cercare molto attentamente, ovvero deve essere qualcosa che non varia in base alle eventuali modifiche del codice HTML (release).

Spero che il suddetto script possa tornarvi utile.

Alla prossima.

LVS e Nagios: script bash per controllare lo stato dell’interfaccia virtuale

Ho realizzato il seguente script bash (da integrare a Nagios) per verificare lo stato dell’interfaccia virtuale presente su ciascun frontend dietro bilanciatore LVS (configurato in direct routing).

nagios

#!/bin/bash

if [ -n "$1" ];then
        status=`/sbin/ifconfig | grep $1 2> /dev/null`

        if [ -n "$status" ]; then
                echo "OK"
                exit 0
        else
                echo "CRITICAL"
                exit 2
        fi

else
        echo "Usage: check_if_status <IP>"
fi

exit 0

Lo script è abbastanza semplice. Per prima cosa lancio il comando ifconfig facendo un grep sull’IP specificato nella configurazione di Nagios. Se tale comando genera un output diverso dalla stringa vuota significa che l’interfaccia virtuale è attiva e quindi esco (exit 0), altrimenti genero un errore di tipo critico (exit 2).

Alla fine dello script ho inserito anche la parte relativa allo usage.

Alla prossima.

Graficizzare i risultati dei check di Nagios mediante pnp4nagios su Centos 6

Un sistema di monitoring degno di questo nome deve prevedere la possibilità di tracciare dei grafici in base ai risultati dei check automatici da esso effettuati.

Purtroppo Nagios non supporta tale funzionalità in maniera nativa, ma, per fortuna, sono disponibili tutta una serie plugin pensati appositamente per il suddetto NMS, in grado di svolgere la funzione in oggetto.

Il plugin che ho scelto prende il nome di pnp4nagios ed è scaricabile da qui.

pnp4nagios

Una volta completato il download vediamo come installare e configurare il tutto.

Preparazione della macchina ed installazione di pnp4nagios

Per prima cosa scompattiamo la tarball mediante il comando:

 [root@NMS ~]# tar -xzvf pnp4nagios-0.6.21.tar.gz

Come prerequisiti per la compilazione degli eseguibili presenti all’interno della directory appena creata è necessario installare sul nostro sistema il compilatore (gcc), una libreria perl, ovvero perl-time-HiRes (utile per testare la configurazione ad installazione avvenuta), una libreria PHP (necessaria per l’esportazione dei grafici in formato pdf) ed il software rrdtool:

[root@NMS ~]# yum install gcc
[root@NMS ~]# yum install perl-Time-HiRes
[root@NMS ~]# yum install php-gd
[root@NMS ~]# yum install rrdtool perl-rrdtool

Ad installazione avvenuta, posizioniamoci nella dir appena creata

[root@NMS ~]# cd pnp4nagios-0.6.21

e lanciamo i comandi:

[root@NMS pnp4nagios-0.6.21]# ./configure
[root@NMS pnp4nagios-0.6.21]# make all
[root@NMS pnp4nagios-0.6.21]# make fullinstall

In particolare, il primo comando serve a verificare che il sistema sia dotato di tutti gli applicativi necessari per la compilazione dei sorgenti relativi a pnp4nagios; il secondo comando esegue la compilazione vera e propria mentre il terzo comando installa il plugin sulla nostra macchina.

La dir target dell’installazione sarà la seguente: /usr/local/pnp4nagios/

Configurazione dell’interfaccia Web di pnp4nagios

Per ragioni di sicurezza occorre dapprima disabilitare la pagina install.php, semplicemente rinominandola:

[root@NMS ~]# mv /usr/local/pnp4nagios/share/install.php /usr/local/pnp4nagios/share/install.php.ignore

In seguito dobbiamo linkare la dir share di pnp4nagios all’interno di /var/www/html, in modo che sia raggiungibile via Web:

[root@NMS ~]# ln -s /usr/local/pnp4nagios/ /var/www/html/pnp4nagios

Inoltre, bisogna fare in modo che il suddetto plugin utilizzi lo stesso file di autenticazione HTTP utilizzato da Nagios:

[root@NMS ~]# cat /etc/httpd/conf.d/nagios.conf | grep AuthUserFile

Tale file (per default) dovrebbe essere il seguente: /etc/nagios/passwd

Ergo sostituiamo la entry presente nativamente su /etc/httpd/conf.d/pnp4nagios.conf con alla voce AuthUserFile con /etc/nagios/passwd

Ricarichiamo la configurazione di httpd per rendere effettive le suddette modifiche:

[root@NMS ~]# service httpd reload

Configurazione di Nagios

Supponendo che la modalità di funzionamento di pnp4nagios sia la synchronous, le modifiche da apportare alla configurazione di Nagios (/etc/nagios/nagios.cfg) sono le seguenti:

1) Abilitare i perfdata, sostituendo

process_performance_data=0

con

process_performance_data=1 

2) Decommentare le diciture:

host_perfdata_command=process-host-perfdata service_perfdata_command=process-service-perfdata

All’interno del file /etc/nagios/objects/commands.cfg occorre sostituire le diciture:

'process-host-perfdata' command definition define command{        command_name    process-host-perfdata        command_line    /usr/bin/printf "%b" "$LASTHOSTCHECK$t$HOSTNAME$t$HOSTSTATE$t$HOSTATTEMPT$t$HOSTSTATETYPE$t$HO$        } 'process-service-perfdata' command definition define command{        command_name    process-service-perfdata        command_line    /usr/bin/printf "%b" "$LASTSERVICECHECK$t$HOSTNAME$t$SERVICEDESC$t$SERVICESTATE$t$SERVICEATTEMP$        }

con:

define command {        command_name    process-service-perfdata        command_line    /usr/bin/perl /usr/local/pnp4nagios/libexec/process_perfdata.pl } define command {        command_name    process-host-perfdata        command_line    /usr/bin/perl /usr/local/pnp4nagios/libexec/process_perfdata.pl -d HOSTPERFDATA }

Ciò si rende necessario per consentire a pnp4nagios di processare le perfdata provenienti dai plugin utilizzati per effettuare i check (se le supportano).

Per quanto riguarda il file /etc/nagios/objects/templates.cfg occorre aggiungere la stringa:

action_url      /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_

nella definizione degli host, e la stringa:

action_url      /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$ 

nella definizione dei servizi.

A configurazione di Nagios completata lanciamo un restart del demone in questione:

[root@NMS ~]# service nagios restart

Verifica della configurazione di Nagios e pnp4nagios

Per effettuare i check della configurazione relativa a Nagios ed al suo plugin pnp4nagios è possibile scaricare lo script perl verify_pnp_config:

[root@NMS ~]# wget http://verify.pnp4nagios.org/verify_pnp_config

Rendiamolo eseguibile:

[root@NMS ~]# chmod +x  verify_pnp_config

Lanciamo dunque il comando:

[root@NMS ~]# ./verify_pnp_config -m sync -c /etc/nagios/nagios.cfg -p /usr/local/pnp4nagios/etc

e se il check da risultato positivo significa che la procedura di configurazione è andata a buon fine.

Come ulteriore check, verifichiamo che nella dir /usr/local/pnp4nagios/var/perfdata vi sia una dir per ogni host su cui è stata abilitata l’action_url e che tali directory contengano dei file con estensione *.rrd (round robin data) ed *.xml.

Nel caso in cui queste dir non contengano i suddetti file (recanti nomenclatura del tipo nomeservizio.rrd e nomeservizio.xml) significa che i plugin utilizzati per effettuare i check non supportano le perfdata.

Infine, all’interno della directory /usr/local/pnp4nagios/share/templates.dist sono presenti le pagine Web contenenti la struttura dei grafici per i plugin nativi di Nagios. Se avete installato qualche plugin aggiuntivo, solitamente viene resa disponibile per il download anche la pagina Web per i grafici ad esso associati. Tale pagina dovrà essere salvata all’interno della directory /usr/local/pnp4nagios/share/templates.

Fine del post, alla prossima.

PS: per fare in modo che pnp4nagios possa creare i file *.rrd è necessario disabilitare SElinux mediante il comando:

[root@NMS ~]# setenforce 0

Nagios ed il carattere di escape

Potrebbe succedere che su un determinato sito Web monitorato da Nagios sia stata abilitata l’autentica HTTP (per ovvie ragioni di sicurezza). Nel caso in cui la coppia username/password contenesse il carattere $, ovvero un carattere speciale utilizzato abbondantemente all’interno delle configurazioni relative all’NMS in questione (ad esempio per identificare le variabili in genere ed i parametri da passare ai vari comandi per eseguire i check), è necessario utilizzare la sequenza di escape. ovvero \\.

Nagios2.png

Ad esempio, supponendo che lo username sia user e che la password sia $password$, la configurazione di Nagios dovrà essere simile alla seguente:

define service{
        use                                  local-service         ; Name of service template to use
        host_name                       sito.dominio.it
        service_description            HTTP
        check_command               check_http_auth!sito.dominio.it!user:\\$password$
        notifications_enabled         0
        }

Come al solito, per rendere effettive le modifiche sarà necessario riavviare il demone in questione.

Alla prossima.

CentOS 6: verificare la configurazione di Nagios da linea di comando

Configurare Nagios non è sicuramente un’operazione banale. Proprio per questo motivo, prima di restartare il demone in oggetto (affinchè le modifiche diventino effettive), è buona norma controllare sempre la configurazione dello stesso, utilizzando il seguente comando:

nagios -v /etc/nagios/nagios.cfg

Ovviamente tale check può essere effettuato puntando esclusivamente al file di configurazione principale (nagios.cfg), e non ai file che identificano i network element da monitorare (presenti nella directory /etc/nagios/objects).

Alla prossima.