Archivi categoria: Networking

Configurazione “IOS resilient” sui dispositivi Cisco

Pensate a cosa accadrebbe se un file di vitale importanza per il fuzionamento del nostro dispositivo Cisco (come l’immagine dell’IOS o lo startup-config) venisse cancellato erroneamente (dall’amministratore) o intenzionalmente (da un hacker/cracker).

cisco

Proprio per evitare che un evento del genere possa accadere, Cisco ci mette a disposizione una serie di funzioni che concorrono a formare la cosiddetta IOS resilient configuration. Esse ci consentono rispettivamente di salvare l’immagine dell’IOS all’interno di una memoria PCMCIA e lo startup-config in una locazione protetta del filesystem. Così facendo, lanciando ad esempio il comando:

Router# show flash

oppure

Router# dir flash:

non verrà mostrato il file *.bin che rappresenta l’immagine dell’IOS.

Inoltre, nel caso in cui lo startup-config venisse cancellato erroneamente digitando:

Router# erase startup-config

e successivamente:

Router# reload

La configurazione potrà essere comunque ripristinata lanciando i comandi:

Router(config)# secure boot-config restore flash:archived-config

e

Router#configure replace flash:archived-config

dove il primo serve ad estrarre lo startup-config archiviato (in modo sicuro) all’interno del filesystem, mentre il secondo è necessario per fare in modo che il running-config venga sostituito con il file di configurazione appena estratto.

Da notare che per abilitare le suddette funzioni occorre che il dispositivo sia dotato di una memoria PCMCIA (indispensabile per la messa in sicurezza dell’IOS) e che, una volta configurate, possono essere disabilitate solo ed esclusivamente tramite console.

Ma veniamo al sodo. I comandi da lanciare sono 2, ovvero:

Router(config)# secure boot-image

per l’IOS, e:

Router(config)# secure boot-config

per lo startup-config.

Infine, per essere certi che i suddetti comandi siano andati a buon fine, possiamo digitare:

Router# show secure bootset

il cui output sarà simile al seguente:

IOS image resilience version 12.4 activated at 02:00:30 UTC Sun Oct 17 2010
Secure archive flash:c181x-advipservicesk9-mz.124-24.T.bin type is image (elf) []
  file size is 23587052 bytes, run size is 23752654 bytes
  Runnable image, entry point 0x80012000, run from ram

IOS configuration resilience version 12.4 activated at 02:00:41 UTC Sun Oct 17 2010
Secure archive flash:.runcfg-20101017-020040.ar type is config
configuration archive size 1544 bytes

Fine del post, alla prossima.

Realizzare un server AAA mediante CentOS 6 e tac_plus

Premessa

Quando si ha a che fare con reti di grandi dimensioni (che contano centinaia e centinaia di dispositivi connessi tra di loro), occorre fare in modo che gli account utente (ed i relativi permessi) vengano gestiti in modo centralizzato. Tale funzione viene svolta dai cosiddetti server AAA, i quali, mediante l’uso di determinati protocolli (come RADIUS, DIAMETER o TACACS+), forniscono dei meccanismi per l’autenticazione dell’utente (Athentication), per la gestione dei relativi permessi (Authorization) e per la “registrazione” delle azioni  compiute dopo aver ottenuto accesso ai dispositivi (Accounting).

aaa

Un po’ di teoria

Come già detto in precedenza, i protocolli maggiormente utilizzati per le funzioni AAA sono RADIUS (anche nella variante più recente DIAMETER) e TACACS+.

Il primo è uno standard open, basato sul protocollo UDP, meno sicuro rispetto al TACACS+ (in quanto cifra solo ed esclusivamente il pacchetto che contiene le credenziali di autentica, lasciando il resto delle comunicazioni in plaintext) e che combina in un unico processo i meccanismi di autenticazione ed autorizzazione.

Il secondo, invece, è uno standard basato sul protocollo TCP (porta 49), proprietario (Cisco), più sicuro rispetto al RADIUS (cifra tutti i pacchetti) e che gestisce ciascuna funzione tipica dell’AAA in modo separato e distinto.

Dati i presupposti, la scelta del protocollo da utilizzare nel nostro ambiente ricade abbondantemente su TACACS+ (essendo inoltre di casa Cisco i dispositivi di rete che si intende gestire).

Installazione e configurazione del server AAA

Come si può banalmente evincere dal titolo, il server in questione è stato realizzato utilizzando una Linux box (CentOS 6) con a bordo il demone tac_plus.

Per prima cosa, occorre quindi installare il suddetto applicativo, aggiungendo il repository yum specifico (nux-misc.repo) alla repolist della nostra macchina:

[root@linuxbox ~]# cd /etc/yum.repos.d/
[root@linuxbox ~]# nano nux-misc.repo

il cui contenuto dovrà essere:

[nux-misc]
name=Nux Misc
baseurl=http://li.nux.ro/download/nux/misc/el6/x86_64/
enabled=0
gpgcheck=1
gpgkey=http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro

Fatto ciò possiamo procedere con l’installazione vera e propria:

[root@linuxbox ~]# yum --enablerepo=nux-misc install tac_plus

Una volta installato il pacchetto facciamo un backup della sua configurazione di default:

[root@linuxbox ~]# cp /etc/tac_plus.conf /etc/tac_plus.conf.bak

e focalizziamo la nostra attenzione sul file di configurazione che andremo a creare ex-novo:

[root@linuxbox ~]# nano /etc/tac_plus.conf

Il cui contenuto dovrà essere simile al seguente:

key = <passphrase tacacs+>

#ACL

acl = default   {
                permit = 192\.168\.0\.1
}

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
# *                      ACCOUNTING                       *
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 

accounting file = /var/log/tac_accounting.log

#

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# *                     AUTHENTICATION                    *
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

user = Pippo {
        default service = permit
        login = des 43v/eMDQqTT2o
        member = NOC
}

user = Pluto {
        login = des 44LWBaN31RmGg
        member = NOC

        #AUTHORIZATION ENTRIES
        cmd = show {
                permit .*
        }
        cmd = exit {
                permit .*
        }
}

group = NOC {
        acl = default
}

# End config file

Analizziamo il suddetto file. Esistono fondamentalmente due macro sezioni, ovvero authentication ed accounting.

Nella prima ho specificato i 2 utenti (con relativa password) che possono avere accesso ai dispositivi di rete, mentre nella seconda ho indicato il file di log in cui “registrare” tutti gli eventi associati all’accounting.

Da notare che la password degli utenti è in formato DES (cifrata), ed è stata ottenuta utilizzando il tool tac_pwd nel modo seguente:

[root@linuxbox ~]# tac_pwd <salt>

Inoltre, all’interno della sezione authentication, ho inserito, per l’utente Pluto, alcune restrizioni sui comandi che possono essere lanciati. Nella fattispecie, egli potrà utilizzare solo ed esclusivamente i comandi show (il permit = .* indica tutto ciò che viene dopo la keyword show) ed exit. Per quanto riguarda l’utente Pippo, essendoci un deny implicito per il servizio di authorization (quindi tutti i comandi non espressamente dichiarati vengono automaticamente inibiti), ho dovuto aggiungere la direttiva default service = permit.

Da notare che ho inserito anche un’opportuna ACL per fare in modo che solo i dispositivi autorizzati possano dialogare col suddetto demone (ACL coadiuvata da regole di firewalling ad hoc, in modo da rispettare il più possibile il modello defense in depth).

A configurazione ultimata, possiamo avviare il demone:

[root@linuxbox ~]# service tac_plus start

e fare in modo che venga avviato automaticamente dopo ogni reboot:

[root@linuxbox ~]# chkconfig tac_plus on

Come ultimo step relativo alla configurazione del server AAA, sarà necessario creare un’opportuna regola netfilter (utilizzando iptables) per consentire il traffico TACACS+ in ingresso:

-A INPUT -m state --state NEW -m tcp -p tcp -s 192.168.0.1/32 --dport 49 -j ACCEPT -m comment --comment "router"

 Configurazione dei dispositivi di rete

Per semplificare un po’ le cose utilizzerò come modello di riferimento la configurazione di un router 2811, anche se essa dovrebbe essere comunque molto simile (se non identica) per la stragrande maggioranza dei dispositivi marchiati Cisco.

Per prima cosa abilitiamo le funzionalità AAA:

Router(config)# aaa new-model

per poi soffermarci sull’autentica:

Router(config)# aaa authentication login default group tacacs+ local

e sulla definizione del server TACACS+ con relativa chiave:

Router(config)# tacacs-server host <ip>
Router(config)# tacacs-server key 0 <pass>

Occorre precisare che l’autenticazione è stata configurata in modo da prevedere un meccanismo di fallback, ovvero nel caso in cui il server AAA non fosse più raggiungibile, sarà comunque possibile loggarsi sul dispositivo utilizzando gli account utente definiti localmente.

Inoltre, nel caso in cui il suddetto server fosse raggiungibile dagli uffici periferici mediante dei tunnel VPN dedicati, occorrerà specificare nella loro configurazione l’interfaccia dalla quale esso puotrà essere contattato:

Router(config)# ip tacacs source-interface <int>

Successivamente possiamo procedere con la configurazione dell’authorization:

aaa authorization exec default group tacacs+ local
aaa authorization commands 1 default group tacacs+ local
aaa authorization commands 15 default group tacacs+ local

e dell’accounting:

Router(config)# aaa accounting system default start-stop group tacacs+
Router(config)# aaa accounting network default start-stop group tacacs+
Router(config)# aaa accounting exec default start-stop group tacacs+
Router(config)# aaa accounting commands 0 default start-stop group tacacs+
Router(config)# aaa accounting commands 15 default start-stop group tacacs+
Router(config)# aaa accounting session-duration ntp-adjusted

Prima di salvare la configurazione, testiamo il corretto funzionamento del meccanismo di autentica, digitando:

Router# test aaa group tacacs+ <user> <pass> legacy

il cui output dovrebbe essere:

Attempting authentication test to server-group tacacs+ using tacacs+
User was successfully authenticated.

Adesso si può finalmente procedere con il salvataggio della configurazione:

Router# copy run start

ed abbiamo finito.

Alla prossima.

CentOS 6 ed rsyslog: creare un sistema di log centralizzato per i dispositivi di rete

Scenario

Diversi uffici periferici (in gergo branch office), connessi all’ufficio centrale (main office) mediante dei tunnel IPSec site-to-site dedicati (classici link VPN utilizzati per creare una intranet con topologia a stella).

Problema

Creare un sistema di log centralizzato per tutti i dispositivi di rete, compresi i router degli uffici periferici.

Soluzione

Utilizzare una Linux box (CentOS 6) con a bordo il demone che funge da syslog server, ovvero rsyslog.

syslog

Configurazione della Linux box e del syslog server

Per prima cosa occorre fare in modo che la nostra Linux box sia in grado di ricevere correttamente (sulla porta UDP 514) i log inoltrati dai dispositivi di rete. Per fare ciò è sufficiente creare la seguente regola di netfilter (ultilizzando iptables):

-A INPUT -m state --state NEW -m udp -p udp -s 192.168.0.0/16 --dport 514 -j ACCEPT

ed aggiungerla all’interno del file /etc/sysconfig/iptables, per poi lanciare un:

[root@linuxbox ~]# service iptables restart

in modo da rendere la suddetta regola operativa (da notare che 192.168.0.0/16 è la subnet classe B che raggruppa tutte le /24 utilizzate dai branch office).

Una volta fatto ciò è necessario aggiungere la seguente direttiva all’interno del file di configurazione rsyslog, ovvero /etc/rsyslog.conf:

$template CiscoVPN,"/var/log/cisco/system-%HOSTNAME%.log"

*.* -?CiscoVPN

e creare la dir di target in cui verranno salvati i log, ovvero /var/log/cisco:

[root@linuxbox ~]# mkdir -p /var/log/cisco

A questo punto possiamo riavviare rsyslog in modo da rendere effettive le suddette modifiche:

[root@linuxbox ~]# service rsyslog restart

Configurazione dei dispositivi di rete

Per semplicità mi soffermerò solo ed esclusivamente nella configurazione dei router (Cisco) dei branch office. Tale operazione consiste in 2 fasi: la definizione di una sorgente SNTP affidabile ed identica per tutti i network device (in modo da poter effettuare un’eventuale correlazione tra gli eventi) e la configurazione del syslog server target.

Per configurare la sorgente SNTP è sufficiente lanciare il comando:

Router(config)# sntp server <IP del server SNTP>

Ad esempio, se volessimo utilizzare come server SNTP ntp1.inrim.it, dovremmo digitare:

Router(config)# sntp server 193.204.114.232

Per quanto riguarda la configurazione del target dei log, è sufficiente lanciare i seguenti comandi:

Router(config)# service timestamps log
Router(config)# logging source-interface Vlan1
Router(config)# logging <IP del syslog server>

Il primo comando serve a fare in modo che il timestamp dell’evento venga aggiunto automaticamente alla entry del log; il secondo comando specifica l’interfaccia dalla quale i log devono essere inviati (essendo in VPN, l’interfaccia di riferimento è quella della LAN, in questo caso la Vlan 1);  l’ultimo comando specifica molto banalmente l’indirizzo IP del syslog server.

Infine, controlliamo che i log vengano popolati in real time, lanciando il comando:

[root@linuxbox ~] #tail -f /var/log/system-<hostname>.log

dove <hostname> è l’hostname del dispositivo di rete di cui volete consultare il file di log.

Se tutto funziona a dovere possiamo dire di aver finalmente realizzato il nostro sistema di log centralizzato.

A presto.

CentOS 6 e contromisure agli attacchi DDoS: regole di firewalling basate sui netblock dei provider italiani

Scenario

Server Web Linux (basato su Apache) con CentOS 6 a bordo, dotato di 16 GB di RAM e 2 CPU con 4 core ciascuna. Totale assenza di firewall di frontend, ergo il filtraggio del traffico viene demandato direttamente al server in questione.

Problema

Da N giorni la suddetta macchina è vittima di attacchi di tipo DDoS, provenienti per lo più da IP stranieri (macchine zombie facenti parte di una botnet).

Soluzione

Creare delle regole netfilter ad hoc (mediante iptables), consentendo solo ed esclusivamente i netblock degli ISP italiani. Inoltre, per evitare che l’attaccante possa avvalersi di qualche proxy “aperto” made in Italy, sono stati bloccati ulteriori IP pubblici recuperati da un sito specifico. Infine, sono stati consentiti gli IP pubblici degli spider (aka crawler) utilizzati dai più importanti motori di ricerca (Google, Bing, Yahoo!), in modo tale da impedire che il sito Web hostato sul server venga penalizzato in termini di ranking.

Step 1: consentire gli IP italiani

Lo scrip bash (permit_ita.sh) che esegue tale operazione è il seguente:

#!/bin/bash

iptables -A INPUT -p tcp --dport 80 -j DROP
iptables -A INPUT -p tcp --dport 443 -j DROP

wget http://www.ipdeny.com/ipblocks/data/countries/it.zone -O ip_italiani.txt

while read line
do
    iptables -I INPUT -s $line -p tcp --dport 80 -j ACCEPT
    iptables -I INPUT -s $line -p tcp --dport 443 -j ACCEPT
done < ip_italiani.txt

iptables-save

Il suo funzionamento è banale: per prima cosa vengono create 2 regole netfilter per droppare tutto il traffico HTTP/HTTPS diretto al sito Web. Successivamente viene scaricato (mediante wget) il contenuto del sito http://www.ip-deny.com/ipblocks/data/countries/it.zone, in cui è presente l’elenco dei netblock italiani. Infine, vegnono consentiti i netblock in questione.

Step 2: bloccare i proxy made in Italy

A questo punto possiamo procedere con il blocco dei proxy “open” italiani. Per fare ciò possiamo utilizzare il seguente scrip bash (block_proxy.sh):

#!/bin/bash

wget --user-agent="Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092416 Firefox/3.0.3"  http://spys.ru/free-proxy-list/IT/ -O lista_proxy.txt

grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}" lista_proxy.txt | uniq > ip_proxy.txt

while read line
do
    iptables -I INPUT -s $line -p tcp --dport 80 -j DROP
    iptables -I INPUT -s $line -p tcp --dport 443 -j DROP
done < ip_proxy.txt

iptables-save

Il sito target (ovvero quello che contiene la lista dei proxy da bloccare) è http://spys.ru/free-proxy-list/IT/, il quale effettua un filtraggio dei client che possono accedervi utilizzando lo User Agent come discriminante (quindi non è possibile scaricarne il contenuto se non si effettua uno spoofing di tale parametro tramite wget e l’opzione –user-agent).

Inoltre, poichè il contenuto del sito non è una “lista piatta” di IP pubblici, è stato necessario filtrare il tutto utilizzando un’espressione regolare in grado di individuare i 4 ottetti tipici dell’IPv4.

Step 3: consentire gli spider dei motori di ricerca

Come ultima fase, occorre consentire gli IP degli spider, utilizzando tale scrip (permit_spider.sh):

#!/bin/bash

while read line
do
    iptables -I INPUT -s $line -p tcp --dport 80 -j ACCEPT -m comment --comment "crawler"
done < ip_spider.txt

iptables-save

Il contenuto del file ip_spider.txt potete ricavarlo da qui (Google), qui (Yahoo!) e qui (Bing ed altri).

A configurazione completata, possiamo saggiare il carico sul server (intento a droppare il traffico proveniente dalla botnet) utilizzando htop.

Se la macchina regge e le risorse hardware locali non sono allo stremo potremo finalmente dire di aver vinto.

Alla prossima.

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.

MRTG e Nagios: monitoraggio del throughput di rete

MRTG (Multi Router Traffic Grapher) rappresenta lo standard “de facto” per ciò che concerne il monitoraggio del throughput della nostra rete. Il suo funzionamento è basato sul polling SNMP, grazie al quale vengono raccolte le informazioni sul traffico che coinvolge le schede di rete monitorate, per poi procedere con la creazione di un grafico “ad hoc”, contenente le predette informazioni.

mrtg_logo

Installazione e configurazione di MRTG

La macchina che svolge le operazioni di monitoraggio è una linux box con a bordo CentOS 6. Per installare MRTG è dunque sufficiente digitare il comando:

[root@linuxbox ~]# yum install mrtg

Inoltre, sarà necessario installare anche i pacchetti net-snmp e net-snmp-utils (per effettuare il polling SNMP vero e proprio):

[root@linuxbox ~]# yum install net-snmp net-snmp-utils

Ad installazione completata passiamo alla configurazione di MRTG. Per prima cosa sarà necessario lanciare il comando:

[root@linuxbox ~]# cfgmaker --global 'WorkDir: /var/www/mrtg' --output /etc/mrtg/mrtg.cfg keypublic@iptarget

Esso ci consentirà di popolare in maniera automatica il file di configurazione /etc/mrtg/mrtg.cfg, grazie al quale, successivamente, verrà creata la pagina Web (con estensione *.html) contenente i grafici generati da MRTG. Inoltre, all’interno del file di configurazione mrtg.cfg, sarà opportuno abilitare le seguenti opzioni:

Options[_]: growright, bits

le quali consentiranno la tracciatura dei grafici da sinistra verso destra, utilizzando i bit come unità di misura (anzichè i byte).

Per creare la pagina Web contenente i grafici è necessario digitare il comando:

[root@linuxbox ~]# indexmaker --output=/var/www/mrtg/index.html /etc/mrtg/mrtg.cfg

A questo punto facciamo in modo che i dati relativi al traffico vengano aggiornati ogni 5 minuti, creando un’apposita regola mediante cron (editando il file /etc/cron.d/mrtg):

*/5 * * * * root LANG=C LC_ALL=C /usr/bin/mrtg /etc/mrtg/mrtg.cfg --lock-file /var/lock/mrtg/mrtg_l --confcache-file /var/lib/mrtg/mrtg.ok

L’ultimo step relativo alla configurazione di MRTG riguarda il settaggio delle credenziali (username/password) per l’accesso alla pagina index.html. Per fare ciò occorre creare il file mrtg.conf, all’interno della directory /etc/httpd/conf.d di Apache (il nostro server Web), il cui contenuto dovrà essere simile al seguente:

Alias /mrtg /var/www/mrtg

<Location /mrtg>
    Order deny,allow
    Allow from all
    AuthName "MRTG Access"
    AuthType Basic
    AuthUserFile /etc/mrtg/passwd
    Require valid-user
</Location>

Ora definiamo lo username e la password (che verrà salvata nel file /etc/mrtg/passwd in formato digest), utilizzando il comando:

[root@linuxbox ~]# htpasswd -c /etc/mrtg/passwd mrtguser

Infine, ricarichiamo la configurazione Apache digitando:

[root@linuxbox ~]# service httpd reload

e proviamo ad accedere ai grafici generati da MRTG, puntando a questa URL:

http://iplinuxbox/mrtg

Se la pagina è accessibile ed i grafici sono aggiornati, possiamo passare alla configurazione di Nagios.

Integrazione tra Nagios ed MRTG

Il plugin di Nagios che ci consente di integrare tale NMS con MRTG prende il nome di check_mrtgtraf. Esso può essere installato singolarmente, digitando:

[root@linuxbox ~]# yum install nagios-plugins-mrtgtraf

oppure installando tutti i plugin di Nagios:

[root@linuxbox ~]# yum install nagios-plugins-all

Ad installazione completata, possiamo definire il comando check_local_mrtgtraf (all’interno del file /etc/nagios/object/commands.cfg), il quale si avvarrà del plugin appena installato:

# 'check_local_mrtgtraf' command definition
define command{
        command_name    check_local_mrtgtraf
        command_line    $USER1$/check_mrtgtraf -F $ARG1$ -a $ARG2$ -w $ARG3$ -c $ARG4$ -e $ARG5$
        }

dove -F indica il file di log (generato da MRTG) che dovrà essere consulato; -a indica la modalità di analisi del traffico (MAX o AVG); -w la soglia di warning e -c la soglia critica.

Non ci rimane che definire il servizio (relativo ad uno specifico host) che dovrà avvalersi del suddetto comando:

define service{
        use                             local-service   ; Inherit values from a template
        host_name                       Router-cisco
        service_description             WAN Bandwidth Usage
        check_command                   check_local_mrtgtraf!/var/www/mrtg/router-cisco/192.168.3.1_16.log!AVG!100000000,200000000!110000000,120000000!10
        }

Ricarichiamo la configurazione di Nagios mediante il comando:

[root@linuxbox ~]# service nagios reload

ed abbiamo finito.

Alla prossima.

Centos 6 e snmptrapd: ricevere le trap SNMP sulla nostra linux box

Il protocollo SNMP, nativamente, ci mette a disposizione 2 modalità di funzionamento: quella classica, basata sul semplice polling, che utilizza la porta UDP 161, e quella “asincrona”, le cosiddette trap, che utilizzano la porta UDP 162.

Va da se che la seconda modalità è migliore rispetto alla prima, in quanto ci consente di ricevere un allarme quasi in tempo reale, dato che è proprio il dispositivo monitorato a generare l’evento (trap) ed a inoltrarcelo.

snmptrap

Ma vediamo ora come configurare la nostra linux box in modo da farle accettare (e loggare) le suddette trap.

Iptables

La prima cosa da fare consiste nel consentire il traffico UDP in ingresso, sulla porta 162:

iptables -I INPUT -p udp --dport 162 -j ACCEPT

Ovviamente tale regola iptables può essere ulteriormente affinata, specificando, ad esempio, l’interfaccia in ingresso (-i), l’IP sorgente (-s) e l’IP di destinazione (-d).

Configurazione di snmptrapd

Adesso occorre configurare il demone che si occupa della ricezione delle trap, ovvero snmptrapd.

Il suo file di configurazione è /etc/snmp/snmptrapd.conf, il cui contenuto dovrà essere simile al seguente:

authCommunity log,execute,net keypublic
format1 %l-%m-%y %h:%j:%k from %A: %b %P %N %W %v\n
format2 %l-%m-%y %h:%j:%k from %A: %b %P %N %W %v\n

La prima entry specifica la community string (keypublic) e le azioni che snmptrapd può effettuare alla ricezione delle trap, ovvero loggarle (log), eseguire un evento specifico tramite handler (execute) oppure inoltrarle ad un altro dispositivo connesso in rete (net).

Mediante le direttive format1 e format2 (utilizzare, rispettivamente, nell’ambito del protocollo SNMPv1 e v2c), specifichiamo il formato del file di log in cui verranno salvate le trap ricevute. In particolare, con:

%l-%m-%y %h:%j:%k

indichiamo il timestamp nel formato giorno-mese-anno ora:minuto:secondo.

Utilizzando invece:

from %A

siamo in grado di loggare il nome del dispositivo che ci ha inviato la trap, mentre con:

%b

ricaviamo l’indirizzo IP del suddetto dispositivo.

Infine, con:

 %P, %N, %W

abbiamo rispettivamente la community string utilizzata dalla trap, la stringa enterprise (che identifica univocamente il produttore del dispositivo) e la descrizione della trap. Ecco un esempio del contenuto del file di log popolato da snmptrapd:

23-7-2015 10:9:0 from 10.12.12.3: UDP: [10.12.12.3]:62741->[10.12.12.2] TRAP, SNMP v1, community keypublic VMWARE-CIMOM-MIB::vmwCimOm Enterprise Specific VMWARE-ENV-MIB::vmwEnvIndicationTime.0 = STRING: 2015-7-23,8:8:59.0

Occorre notare che le trap non vengono ricevute (e loggate) in formato numerico, in quanto sulla linux box sono presenti le MIB (scritte attraverso il linguaggio SMI) specifiche per i dispisitivi monitorati (in questo caso degli host VMWare). Solo a titolo informativo, le suddette MIB vanno salvate all’interno della directory /usr/share/snmp/mibs/.

 Opzioni di avvio

Una volta configurato, snmptrapd deve essere avviato utilizzando determinate opzioni, affinchè il processo di logging venga effettuato secondo le nostre necessità. Il file in cui specificare tali opzioni è /etc/sysconfig/snmptrapd, il cui contenutò dovrà essere simile al seguente:

OPTIONS="-A -m ALL -M /usr/share/snmp/mibs -Lf /var/log/snmptrapd.log -p /var/run/snmptrapd.pid"

dove l’opzione -A indica la modalità di scrittura del file di log (append); -m ALL indica la necessità di utilizzare tutte le MIB presenti sul sistema; -M serve a specificare il pathname delle MIB; -Lf indica il file di log ed infine -p punta al pathname del file *.pid (process ID) associato al demone in questione.

Rotazione del file di log

Naturalmente un file di log troppo grande risulta molto più difficile da consultare, ergo occorre definire delle regole di rotazione utilizzando lo strumento messo a disposizione dalla nostra linux box, ovvero logrotate. In particolare, il contenuto del file snmptrapd presente nella directory /etc/logrotate.d dovrà essere il seguente:

/var/log/snmptrapd.log {
    rotate 10
    missingok
    notifempty
    sharedscripts
    delaycompress
    copytruncate
    weekly
    postrotate
        /sbin/service snmtrapd restart > /dev/null 2>/dev/null || true
    endscript
}

Tra le suddette opzioni, quella più importante è certamente copytruncate, senza la quale, dopo ogni rotazione, il file di log non sarebbe in grado di registrare nuovi eventi.

Ora che è tutto configurato possiamo avviare il demone:

[root@linuxbox ~]# service snmptrapd start

e fare in modo che venga eseguito automaticamente dopo ogni boot:

[root@linuxbox ~]# chkconfig snmptrapd on

Invio tramite email delle trap di allarme

L’ultimo step consiste nel fare in modo che tutte le trap di allarme vengano inviate sulla nostra mailbox. Per fare ciò si può utilizzare swatch, il cui file di configurazione (/etc/swatch_snmp.conf) dovrà essere simile a questo:

#SNMP TRAP ALERT
watchfor  /Alert|alert/
     echo
     mail addresses=vostro.indirizzo\@email.it,subject=SWATCH LINUX-BOX: SNMP TRAP ALERT

Editiamo il file /etc/rc.local in modo da avviare automaticamente swatch ad ogni boot della macchina:

swatch -c /etc/swatch_snmp.conf -t /var/log/snmptrapd.log &

Lanciamo il comando:

[root@linuxbox ~]# swatch -c /etc/swatch_snmp.conf -t /var/log/snmptrapd.log &

ed abbiamo finito.

Alla prossima.

TCP Offload: conviene davvero abilitarlo?

Di recente, dopo svariati test effettuati in laboratorio, si è deciso di aggiornare i driver delle schede di rete installate su 2 macchine Windows Server 2003 R2 (in failover cluster) , passando dai driver Broadcom a quelli Intel (cosa molto più sensata dato che il produttore delle NIC è, per l’appunto, Intel).

intelVa detto che tale scelta è stata dettata anche dal fatto che con il software di gestione del teaming  messo a disposizione da Broadcom, l’unica modalità selezionabile era il load balancing, ovvero la possibilità di transmettere/ricevere il traffico di rete “un po’ da una scheda ed un po’ dall’altra”. Fin qui nulla di male, se non fosse per il fatto che,  in caso di fault di uno dei due switch o di una delle due schede del teaming, prima che il sistema riuscisse a riconvergere sull’unica NIC ancora funzionante, si è assistito ad un tempo di disservizio randomico, che poteva variare da qualche secondo a qualche minuto. Premesso che, a mio avviso, tale comportamento era strettamente legato alla durata della cache ARP dei sistemi coinvolti, una situazione del genere non era comunque tollerabile, soprattutto per dei sistemi di importanza critica e cruciale.

A differenza di quanto assistito per il software Broadcom, grazie al software Intel, configurando le schede in modalità switch failover, si è riusciti a ridurre notevolmente i tempi di riconvergenza, portandoli a circa un secondo (ed un solo pacchetto ICMP in request timeout). Tutto molto bello, a parte il fatto che dopo aver aggiornato i driver, il sistema ha iniziato a ricevere (ed inviare) i dati troppo lentamente.

Dopo aver analizzato innumerevoli tracciati Wireshark ed aver spulciato tutta la documentazione possibile ed immaginabile, sono arrivato alla conclusione che la causa della suddetta problematica era il TCP Offload (abilitato di default).

Cos’è il TCP Offload

Il TCP Offload è stato introdotto per ridurre l’overhead (leggasi carico aggiuntivo) dei server durante la gestione del traffico di rete (il quale è aumentato in modo esponenziale rispetto alle reti TCP/IP di un trentennio addietro). Nella fattispecie, grazie alla suddetta “feature”, il traffico viene gestito direttamente dall’hardware della NIC (senza quindi passare per la CPU). Per essere più precisi, vige la regola che per ogni byte di traffico di rete gestito dal server corrisponda un carico sulla CPU pari ad un HZ, quindi si può certamente intuire quanto il TCP offload possa portare (in alcuni casi) dei benefici a livello computazionale e prestazionale.

Solitamente tale configurazione è dunque migliorativa, salvo alcune eccezioni. Ad esempio, spesso accade che il TCP offload forgi dei segmenti TCP di dimensione superiore a 64 byte, i quali vengono incapsulati (layer 2) in frame di dimensione superiore ai 1500 byte (che rappresenta la MTU di default delle reti Ethernet e quindi quella supportata nativamente dalla stragrande maggioranza dei dispositivi di rete).

Cosa succede in questo caso? Ebbene, se gli switch non sono configurati a dovere, essi scarteranno (in modo trasparente, salvo previa connessione alla CLI se si tratta di dispositivi managed) i pacchetti con MTU > 1500 byte, riducendo drasticamente il throughput dei server.

In definitiva, nel caso in cui riscontraste una lentezza anomala in TX/RX da parte delle vostre macchine, vi consiglio, come primo step, di disabilitare tale opzione.

Alla prossima.

Nagios: script bash + expect per monitorare il numero di NAT translation sui router Cisco

Dopo aver cercato a lungo un OID SNMP che potesse restituirmi on-the-fly il numero di NAT translation attive sul mio router Cisco, sono arrivato alla conclusione che il modo più semplice per ricavare tale informazione consiste nel creare uno scrip bash + expect da dare in pasto a Nagios.

Nagios_logo_blackPer prima cosa, dunque, mi sono soffermato sulla creazione dello scrip expect, in modo da poter interrogare il router oggetto di monitoraggio, lanciando un comando specifico, che è il seguente:

Router# show ip nat statistics

Ed ecco lo scrip expect vero e proprio:

#!/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 "show ip nat statistics\r"
expect "#"
send "exit\r"
expect eof

Esso riceve come parametri l’IP del dispositivo, la password vty e la password ena.
Dopo averlo chiamato get_nat_num (ed averlo reso eseguibile con chmod +x get_nat_num), mi sono soffermato sulla creazione dello scrip bash, che è il seguente:

#!/bin/bash

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

usage="check_nat_translations <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_nat_num $1 $2 $3 | grep "Total active translations"  | awk '{print $4}'`

                                        fi

                                        if [ -n "$output" ];then

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

                                                        echo "CRITICAL: total number of active NAT translations is $output | nat_translations=$output;$warning;$critical";
                                                        exit 2;

                                                elif [ "$output" -lt "$critical"  -a  "$output" -ge "$warning" ];then

                                                        echo "WARNING: total number of active NAT translations is $output | nat_translations=$output;$warning;$critical";
                                                        exit 1;

                                                else

                                                        echo "OK: total number of active NAT translations is $output | nat_translations=$output;$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

Esso accetta in ingresso 5 parametri: i primi 3 da passare allo scrip get_nat_num, gli ultimi 2 da utilizzare come soglie per Nagios (una warning ed una critical).

Rendiamo eseguibile anche questo scrip (chmod +x check_nat_translations) e soffermiamoci sulla configurazione di Nagios.

Come primo step occorre creare il comando che utilizza i plugin appena creati:

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

Successivamente è necessario creare un servizio (da inserire nel file di configurazione relativo ad un host determinato), che si avvalga del comando creato in precedenza:

define service{
 use                             local-service         ; Name of service template to use
 host_name                       cisco
 service_descripion             NAT Translations Number
 check_command                   check_nat_translations!password1!password2!40000!50000
 }

Salviamo la configurazione, riavviamo Nagios, ed il gioco è fatto.

Alla prossima.

Configurare una VPN IPsec site-to-site tra un router Cisco 2811 ed un router Cisco 877W

Affinchè si possa realizzare un canale di comunicazione “sicuro” tra due o più filiali, sfruttando, ad esempio, una normale linea ADSL, è necessario affidarsi ad una tecnologia VPN che supporti tale funzionalità. Lo standard “de facto” per i collegamenti Site-to-Site è rappresentato dal protocollo IPsec.

Adesso vedremo come configurare tale tipologia di VPN, utilizzando come piattaforme hardware un router Cisco 2811 (main office) ed un router Cisco 877W (branch office).

Lo schema di rete si può riassumere come segue:

vpn-ipsecConfigurazione del router Cisco 2811 (Main Office)

La prima cosa da fare è creare la policy ISAKMP per gestire le Security Associations (in gergo dette semplicemente SA), ovvero le due entità che vogliono instaurare il tunnel VPN.

R1(config)crypto isakmp policy 1
R1(config-isakmp)# encr 3des
R1(config-isakmp)# hash md5
R1(config-isakmp)# authentication pre-share
R1(config-isakmp)# group 2
R1(config-isakmp)# lifetime 86400

In particolare, sto definendo alcuni parametri relativi alla fase 1 IKE (in realtà ISAKMP è solo uno dei 3 protocolli definiti nella suite IKE), ovvero:

1) il tipo di cifratura simmetrica da utilizzare (3des);

2) l’algoritmo di hashing per l’HMAC (md5), utilizzato per garantire l’integrità dei pacchetti scambiati tra le parti;

3) il tipo di autentica (tramite chiave condivisa – pre-shared);

4) il gruppo Diffie-Helman da utilizzare (l’algoritmo in questione definisce un metodo “sicuro” per lo scambio delle chiavi tra le parti);

5) la durata del tunnel IPSec (in secondi).

Ora si può procedere con la definizione della chiave condivisa:

R1(config)# crypto isakmp key cisco address 2.2.2.3

A questo punto possiamo configurare la fase 2 IKE, impostando l’apposito transform set:

R1(config)# crypto ipsec transform-set TS esp-3des esp-md5-hmac

Esso si occupa di cifrare i dati trasmessi tra le due parti dopo l’instaurazione del tunnel.

Definiamo adesso l’ACL che si occuperà di indentificare il traffico VPN (detto, in gergo, interesting traffic):

R1(config)# ip access-list extended VPN-TRAFFIC
R1(config-ext-nacl)# permit ip 192.168.1.0 0.0.0.255 192.168.2.0 0.0.0.255

A questo punto sarà possibile definire la crypto map:

R1(config)# crypto map CMAP 6 ipsec-isakmp 
R1(config-crypto-map)# set peer 2.2.2.3
R1(config-crypto-map)# set transform-set TS
R1(config-crypto-map)# match address VPN-TRAFFIC

Inoltre, dobbiamo evitare che il traffico LAN-to-LAN venga nattato. E’ possibile fare ciò definendo un’ACL ad hoc:

R1(config)# access-list 100 remark --NO-NAT--
R1(config)# access-list 100 deny ip 192.168.1.0 0.0.0.255 192.168.2.0 0.0.0.255
R1(config)# access-list 100 permit ip 192.168.1.0 0.0.0.255 any
R1(config)# access-list 100 remark

associandola, successivamente, al processo di NAT vero e proprio:

R1(config)# ip nat inside source list 100 interface fastethernet0/0 overload

Come ultimo step dobbiamo associare la crypto MAP precedentemente definita all’interfaccia fa0/0 (Internet):

R1(config)# int fa0/0
R1(config-if)# crypto map CMAP

Configurazione del router Cisco 877W (Branch Office)

La configurazione del Branch Office è del tutto speculare a quella del Main office. L’unica stostaziale differenza sta nell’interfaccia esposta ad Internet: per il main office è la fa0/0 mentre per il branch office è la dia1 (protocollo PPPoE).

IKE fase 1:

R2(config)#  crypto isakmp policy 1
R2(config-isakmp)# encr 3des
R2(config-isakmp)# hash md5
R2(config-isakmp)# authentication pre-share
R2(config-isakmp)# group 2
R2(config-isakmp)# lifetime 86400

Pre-shared key:

R2(config)# crypto isakmp key cisco address 2.2.2.2

IKE fase 2 (transform set):

R2(config)# crypto ipsec transform-set TS esp-3des esp-md5-hmac

 ACL per il traffico LAN-to-LAN:

R2(config)# ip access-list extended VPN-TRAFFIC
R2(config-ext-nacl)# permit ip 192.168.2.0 0.0.0.255 192.168.1.0 0.0.0.255

 Crypto map:

R2(config)# crypto map CMAP 6 ipsec-isakmp 
R2(config-crypto-map)# set peer 2.2.2.2
R2(config-crypto-map)# set transform-set TS
R2(config-crypto-map)# match address VPN-TRAFFIC

No-NAT:

R2(config)# access-list 100 remark --NO-NAT--
R2(config)# access-list 100 deny ip 192.168.2.0 0.0.0.255 192.168.1.0 0.0.0.255
R2(config)# access-list 100 permit ip 192.168.2.0 0.0.0.255 any
R2(config)# access-list 100 remark
R2(config)# ip nat inside source list 100 int dia1 overload

Binding crypto map/interfaccia:

R2(config)# int dia1
R2(config-if)# crypto map CMAP
R2(config-if)# crypto ipsec df-bit clear

L’ultimo comando relativo alla configurazione dell’interfaccia dia1 ci mette al riparo da eventuali problemi dovuti ad un MTU mismatch (ad esempio, il router Cisco 2811 utilizza una MTU pari a 1500 byte mentre il router Cisco 877W, essendo configurato per un accesso ad Internet di tipo PPPoE, usa una MTU pari a 1492 byte).

Test e troubleshooting

Per testare l’effettivo funzionamento del tunnel VPN appena configurato è sufficiente, in primo luogo, lanciare un semplice ping verso la LAN del peer, avendo cura di definire come interfaccia sorgente quella esposta sulla rete privata:

R1(config)ping 192.168.2.1 source fa0/1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.2.1, timeout is 2 seconds:
Packet sent with a source address of 192.168.1.1
.!!!!
Success rate is 80 percent (4/5), round-trip min/avg/max = 41/44/46 m

Il primo ping ha restituito un timeout poichè il tunnel VPN viene tirato su solo on-demand, ovvero dopo aver appurato la presenza di traffico LAN-to-LAN, per poi rimanere attivo fino al timeout definito nella policy ISAKMP (86400 secondi).

Altri comandi utili per verificare lo stato del tunnel VPN sono i seguenti:

show crypto session
show crypto isakmp sa
show crypto ipsec sa
debug crypto isakmp
debug crypto ipsec

E’ tutto. Alla prossima.