ip sla - DocShare.tips

Transcript

ip sla - DocShare.tips
Capitolo di esempio tratto dal libro
“Router e Internet” di Gianrico Fichera e
Maurizio Intravaia
Capitolo VIII
Monitoraggio, IP SLA e EEM
Il materiale in questo libro non e’ sponsorizzato o sottoscritto da
Cisco Systems, Inc. Cisco e’ un trademark di Cisco Systems, Inc.
negli Stati Uniti e in altri stati. L’autore di questo libro non si assume
nessuna responsabilita’ e non da nessuna garanzia riguardante
l’accuratezza e la completezza delle informazioni presenti nonche’ da
conseguenze sull’uso delle informazioni presenti in questo libro.
Copyright 2011 Gianrico Fichera
Nessuna parte di questa pubblicazione puo' essere riprodotta o
trasmessa, in qualsiasi forma o con qualsiasi mezzo, elettronico,
meccanico, fotocopie, registrazione, senza il consenso dell'autore.
This material is not sponsored by, endorsed by, or affiliated
with Cisco Systems, Inc., Cisco, Cisco Systems, and the Cisco
Systems logo are trademarks or registered trade marks of
Cisco Systems, Inc. or its affiliates. All other trademarks are
trademarks of their respective owners.
169
Cisco IP Service Level Agreements (IP SLA)
Per Service Level Agreement (SLA) si intende un
contratto siglato tra un fornitore di servizi di
connettivita' (network provider o ISP) ed un cliente
dove ci si impegna a fornire un servizio con delle
specifiche ben definite. Ad esempio una continuita'
di servizio del 99% con una latenza massima ben
precisa, con un servizio di assistenza con risposta
garantita entro un certo tempo dalla chiamata.
L'ISP per poter garantire questi servizi deve
configurare i circuiti dati opportunamente. In caso
di reti provviste di un buon supporto alla qualita' del
servizio, come le reti ATM o Frame-Relay o le piu'
moderne MPLS, e' possibile far cio' utilizzando le
funzionalita' dei protocolli. In caso di reti sprovviste
di tali protocolli ma basate solo sul TCP/IP
(Internet) non e' altrettanto semplice. Se ci fossero
a disposizione una serie di comandi con cui il router
potesse automaticamente verificare la rispondenza
di un circuito TCP/IP ai valori contrattualizzati,
intervenendo di conseguenza quanto piu' automaticamente possibile, il network provider potrebbe
utilizzare in modo piu' efficiente la propria rete e
aumentarne la produttivita'. Questo e' di fatto
possibile con la funzionalita' Cisco IP SLA,
disponibile su tutte le piattaforme hardware IOS
all'incirca della versione 12.2T (Catalyst 65XX a
partire dalla 12.2(33)SXI1 per il comando "ip sla").
Abbiamo pertanto a disposizione una nuova
famiglia di comandi pensata principalmente per
consentire misure sulle performance della rete in
170
tempo reale ed intervenire automaticamente con
delle azioni in conseguenza al verificarsi di determinati eventi. Quindi si ha la possibilita' di monitorare
un servizio Internet, come la raggiungibilita' di un
indirizzo IP, oppure la raggiungibilita' di un servizio
web, o lo stato di una interfaccia, o la latenza e
anche di eseguire delle azioni in conseguenza
all'attivita' monitorata. Il numero di attivita'
monitorabili dipende dalla versione di IOS. E'
interessante notare che le performance vengono
monitorate attivamente, ovvero con la generazione
di traffico. E' anche possibile configurare dei
threshold per cui al superare di determinate soglie il
router invia una trap SNMP. In alternativa da CLI si
possono verificare gli SLA.
La quantita' di servizi e funzionalita' monitorabili
e' davvero ampia. Con qualche esempio si potra'
capirne il principio di funzionamento.
Per alcune funzionalita' di monitoraggio e' necessario configurare un router mittente e uno
ricevente, quest'ultimo in modalita' "IP SLA
responder" che replica ai pacchetti di monitoraggio
inviati dal primo, in modo da verificare alcuni
parametri di circuito. Con il comando "ip sla
responder" (oppure "ip sla monitor responder") e'
possibile attivare in un secondo router Cisco un
risponditore automatico per alcuni tipi di richieste
inviate da una configurazione "ip sla" di un primo
router. Ad esempio se si utilizza il monitoraggio
dell'UDP Jitter (udp-jitter), che poi monitorizza
anche il packet-loss e altri parametri, e' necessario
un risponditore all'altro capo della tratta da
171
monitorare. Questo e' estremamente utile per la
VoIP perche' la qualita' del link e' fondamentale per
la qualita' della voce.
Configurazione IP SLA
In questi esempi ci limiteremo a delle
configurazioni di base. Una volta capito il principio
di funzionamento sara' possibile preparare delle
configurazioni piu' specifiche. Supponiamo di voler
monitorare la raggiungibilita' di un indirizzo IP.
La configurazione di uno SLA viene effettuata con
il comando "ip sla {NUM}". Dopo aver preparato il
proprio SLA lo si attiva utilizzando il comando "ip
sla schedule". Una volta attivo non e' piu'
modificabile. Se necessario dovremo cancellarlo
dalla configurazione e ricrearlo.
giarout(config)#ip sla 12
giarout(config-ip-sla)#?
IP SLAs entry configuration commands:
dhcp
DHCP Operation
dns
DNS Query Operation
ethernet
Ethernet Operations
exit
Exit Operation Configuration
frame-relay Frame-relay Operation
ftp
FTP Operation
http
HTTP Operation
icmp-echo
ICMP Echo Operation
icmp-jitter ICMP Jitter Operation
mpls
MPLS Operation
path-echo
Path Discovered ICMP Echo Operation
path-jitter Path Discovered ICMP Jitter Operation
tcp-connect TCP Connect Operation
udp-echo
UDP Echo Operation
udp-jitter UDP Jitter Operation
voip
Voice Over IP Operation
Figura 105 - Comando "ip sla"
172
Per verificare le possibilita' di monitoraggio
offerte dall'IOS del nostro router possiamo aiutarci
con l'help di linea del CLI, mostrato in figura 105.
Supponiamo di voler creare uno SLA che
monitorizzi un circuito utilizzando il protocollo ICMP
in modo da accertarsi che non si superi un tempo di
latenza pari a 20ms. Il test viene effettuato ogni 70
secondi. Nel caso in cui per 5 volte consecutive il
test fallisce si genera una trap e si genera un
trigger. Quest'ultimo ha la funzione di fare partire
un secondo sla, il numero "11" che non e' riportato
nell'esempio e che effettuera' dei test aggiuntivi.
ip sla 10
icmp-echo 192.168.30.1 source-interface GigabitEthernet0/1
timeout 20
frequency 70
ip sla schedule 10 life forever start-time now
ip sla reaction-configuration 10 react connectionLoss thresholdtype consecutive 5 action-type trapAndTrigger
ip sla reaction-trigger 10 11
Figura 106 - Configurazione di base 'ip sla'
Con il comando "show ip sla configuration
{NUM}" possiamo verificare che la configurazione
dello sla 10 sia stata recepita correttamente. In
figura 107 e’ mostrata la corretta sintassi e l’output.
Verifiche SLA
Relativamente all'esempio del paragrafo preceden173
te vediamo come verificare che lo SLA sia correttamente funzionante e come vederne le statistiche.
Come si vede dalla figura 108 dal momento
dell'avvio ci sono stati 4 successi e 1 fallimento,
non sufficiente per l’invio di una trap e all'avvio
dello sla "11".
giatisc#show ip sla configuration 10
IP SLAs, Infrastructure Engine-II.
Entry number: 10
Owner:
Tag:
Type of operation to perform: icmp-echo
Target address/Source interface:
192.168.30.1/GigabitEthernet0/1
Type Of Service parameter: 0x0
Request size (ARR data portion): 28
Operation timeout (milliseconds): 20
Verify data: No
Vrf Name:
Schedule:
Operation frequency (seconds): 70 (not considered if
randomly scheduled)
Next Scheduled Start Time: Start Time already passed
Group Scheduled : FALSE
Randomly Scheduled : FALSE
Life (seconds): Forever
Entry Ageout (seconds): never
Recurring (Starting Everyday): FALSE
Status of entry (SNMP RowStatus): Active
Threshold (milliseconds): 5000 (not considered if react
RTT is configured)
Distribution Statistics:
Number of statistic hours kept: 2
Number of statistic distribution buckets kept: 1
Statistic distribution interval (milliseconds): 20
History Statistics:
Number of history Lives kept: 0
Number of history Buckets kept: 15
History Filter Type: None
Enhanced History:
Figura 107 - Comando 'show IP sla configuration'
174
giarout#show ip sla statistics 10
IPSLAs Latest Operation Statistics
IPSLA operation id: 10
Type of operation: icmp-echo
Latest RTT: 1 milliseconds
Latest operation start time: *14:18:43.961 UTC Fri Sep 11 2009
Latest operation return code: OK
Number of successes: 4
Number of failures: 1
Operation time to live: Forever
Figura 108 - Comando 'show ip sla statistics'
giarout#show ip sla reaction-configuration 10
Entry number: 10
Index: 1
Reaction: connectionLoss
Threshold Type: Consecutive
Threshold CountX: 5
Threshold CountY: 5
Action Type: Trap and trigger
Figura 109 - Comando 'show ip sla reactionconfiguration'
giarout#show ip sla reactiontrigger 10
Entry number: 10
Target Entry Number: 11
Status of Entry (SNMP RowStatus): active
Operational State: pending
Figura 110 - Comando 'show ip sla reactiontrigger'
Esempio di monitoraggio "ftp"
Modifichiamo l'esempio precedente con i seguenti
175
comandi monitoriamo
servizio ftp:
la
raggiungibilita'
di
un
ip sla 10
ftp get ftp://anonymous:test@@ftp.gianrico.com/
mode active
ip sla schedule 10 life forever start-time now
Figura 111 - Monitoraggio ftp con 'ip sla'
Il comando "track"
Il comando "track" ha lo scopo di monitorare un
evento e di permettere delle azioni in conseguenza
al suo verificarsi. Il comando track viene utilizzato
per molti scopi, ad esempio per monitorare lo stato
delle interfacce di un router. Questo comando viene
utilizzato anche con il comando "ip sla". Questo
permette delle azioni diverse rispetto la generazione di trap oppure trigger in conseguenza al
superamento di un threshold. Il comando e' "track
ip sla". In alcune versioni di IOS potrebbe essere
assente e in tal caso va utilizzata la variante "track
rtr". Questo comando e' stato introdotto con IOS
12.3(4)T.
Comando "track" senza "ip sla"
Vediamo come utilizzare il comando track con
degli esempi concreti. Questo comando e'
storicamente gia' presente in IOS prima dell'
introduzione degli "ip sla". Un campo di applicazione
e' nel monitoraggio delle interfacce. Ad esempio
176
possiamo monitorare lo stato di una interfaccia ATM
e cancellare una riga di routing nel caso in cui la
linea vada nello stato di protocollo down.
track 10 interface ATM0/3/0 line-protocol
delay down 5 up 30
ip route 18.181.0.0 255.255.255.0 dialer0 track 10 (1)
Figura 112 - Comando 'track' –
Allora se il protocollo dell'interfaccia ATM0/3/0
permane nello stato di down per oltre 5 secondi la
riga di routing (1) viene tolta dalla tabella di
routing.
Con i comandi "show track" e "show track
brief" si puo' verificare lo stato del monitoring:
gia-gw#show track 10
Track 10
Interface ATM0/3/0 line-protocol
Line protocol is Up
1 change, last change 00:06:27
Delay up 30 secs, down 5 secs
Tracked by:
STATIC-IP-ROUTING 0
gia-gw#show track brief
Track
Object
10
interface ATM0/3/0
Parameter
line-protocol
Value Last Change
Up
00:07:07
Figura 113 - Comando 'show track'
Con il comando "debug track" e' possibile fare
il debugging degli eventi. Ecco cosa succede quando
il protocollo dell'interfaccia Atm0/3/0 passa nello
stato di down:
177
000917: Jan 20 16:09:43.646: Track: 10 Down change delayed
for 5 secs
000923: Jan 20 16:09:48.646: Track: 10 Down change delay
expired
000924: Jan 20 16:09:48.646: Track: 10 Change #4 interface
ATM0/3/0, line-protocol Up->Down
Figura 114 - Debug: track transizione down su
interfaccia
Ed ecco cosa accade quando il protocollo torna
nello stato di up:
000934: Jan 20 16:12:29.079: Track: 10 Up change delay
expired
000935: Jan 20 16:12:29.079: Track: 10 Change #5 interface
ATM0/3/0, line-protocol Down->Up
Figura 115 - Debug: track transizione up su interfaccia
Con il comando "show ip route track-table" si
possono vedere quali sono le righe di routing
monitorate:
gia-gw#show ip route track-table
ip route 18.181.0.0 255.255.255.0 Dialer1 track
10 state is [up]
Figura 116 - Comando 'show ip route track-table'
178
Esempio "track" con "ip sla"
Presentiamo adesso un esempio sulle nuove
funzionalita' del comando track. Si osservi la
configurazione in figura.
ip name-server 192.168.30.30
ip domain-lookup
ip sla 10
http get http://www.itesys.it
frequency 100
ip sla schedule 10 life forever start-time now
track 50 ip sla 10
versioni
!oppure "track 50 rtr 10" in vecchie
ip route 18.181.0.31 255.255.255.255 Serial0/0/0.1 track
50 (2)
Figura 117 - Configurazione 'ip sla' con 'track'
Anche se dal punto di vista pratico la
configurazione puo' non avere molta utilita', dal
punto di vista didattico e' molto interessante. Se il
sito web http://www.itesys.it diventa irraggiungibile
la riga di routing (2) viene tolta dalla tabella di
routing. Con il comando "debug ip sla trace" si
puo' vedere lo stato del tracking come si vede in
figura 118.
Nel caso in cui la risoluzione del nome fallisca,
oppure l'indirizzo IP del sito web diventa irraggiungibile, oppure il server web non risponde alla porta
80 per il sito web indicato, la riga di routing (2)
viene tolta dalla tabella di routing.
179
*Jan 20 16:26:16.532: IP SLAs(10)
saaSchedulerEventWakeup
*Jan 20 16:26:16.532: IP SLAs(10)
operation
*Jan 20 16:26:16.532: IP SLAs(10)
http operation
*Jan 20 16:26:16.532: IP SLAs(10)
dns operation
*Jan 20 16:26:16.532: IP SLAs(10)
- www.itesys.it
*Jan 20 16:26:16.532: IP SLAs(10)
server - 151.99.125.2
*Jan 20 16:26:16.532: IP SLAs(10)
target queried = www.itesys.it
*Jan 20 16:26:16.616: IP SLAs(10)
return code - no error
*Jan 20 16:26:16.616: IP SLAs(10)
Address 82.85.14.71
*Jan 20 16:26:16.616: IP SLAs(10)
*Jan 20 16:26:16.760: IP SLAs(10)
18 bytes
*Jan 20 16:26:16.760: IP SLAs(10)
connection - connected
*Jan 20 16:26:16.948: IP SLAs(10)
first byte: 328 ms
*Jan 20 16:26:16.948: IP SLAs(10)
*Jan 20 16:26:16.948: IP SLAs(10)
Scheduler:
Scheduler: Starting an
http operation: Starting
dns operation: Starting
dns operation: Query name
dns operation: Query name
dns operation: actual
dns operation: Query
dns operation: received IP
dns operation: RTT=87
http operation: Sent 18 of
http operation: Wait
http operation: Time to
http operation: RTT=417
Scheduler: Updating result
Figura 118 - Comando 'debug IP sla trace'
E' possibile creare delle condizioni complesse con
l'uso di 'and' oppure 'or'. Vediamone un esempio.
track 111 list boolean and
object 10
object 20
Figura 119 - Comando 'object' con 'track'
Nota 1: spesso i server web rispondono comunque
nel caso in cui un singolo sito web non sia funzionante, magari con messaggi del tipo "service
180
unavailable". In questo caso per il router il sito web
e' funzionante. Quindi il comando "http get"
dell'esempio e' valido per verificare la raggiungibilita' TCP/IP di un server ma non per monitorare
lo stato di un singolo sito web che va oltre lo scopo
dei servizi di IOS;
Nota 2: nelle prime versioni di IOS si puo' trovare
il comando "rtr" invece di "ip sla". Nelle versioni
dalla 12.4(20)T si ha "track ... sla..." invece di
"track ... rtr..."
Nota 3: Nel caso si utilizzi il 'track' con 'rtr'
osservate che non si puo' utilizzare la parola chiave
"consecutive" in "ip sla react configuration". Per
fare in modo tale da scatenare un evento dopo un
certo numero di ping falliti bisogna utilizzare un
"delay" sufficientemente lungo in 'track' e dei valori
di 'frequency' e 'timeout' sufficientemente corti in
'ip sla' in modo da farci cadere il numero di
pacchetti icmp voluti.
Comando “track” e floating static route
Per "floating static route" intendiamo delle
righe di routing statico che hanno una distanza
amministrativa superiore al normale. Possono
essere utilizzate come righe di backup o "backdoor"
da utilizzare nel caso in cui una route statica a
priorita' maggiore venga cancellata dalla RIB. Se
un'interfaccia fisica va nello stato di down le righe
statiche che la referenziano come next-hop
vengono tolte dalla RIB dando spazio ad eventuali
altri righe provenienti da algoritmi di routing
181
dinamico oppure, appunto, righe statiche con AD
maggiore. Il limite nell'utilizzo di questo sistema sta
nel fatto che in molte tipologie di guasto le
interfacce rimangono nello stato di UP senza pero'
consentire il transito di dati, ma vedremo nei
paragrafi successivi come si puo' trovare rimedio a
casi del genere. In tali casi le righe di route
rimangono in RIB. In tutti questi casi questa forma
di backup non funziona. Segue in figura un esempio
di floating static route.
ip route 0.0.0.0 0.0.0.0 192.168.10.1
ip route 0.0.0.0 0.0.0.0 192.168.20.2 200
Figura 120 - 'ip route' con 'track'
In circostanze normali la route di default utilizzata e' la prima e il gateway della rete e' l'indirizzo
IP 192.168.10.1. Se questa riga di routing viene
cancellata dalla RIB, cosa che avviene solo nei casi
sopra indicati, il gateway della rete diventera'
l'indirizzo IP 192.168.10.2. Se affianchiamo le
floating route con il track e l'ip sla possiamo
realizzare interessanti configurazioni di backup dove
piuttosto che monitorare lo stato di una interfaccia
monitoriamo l'effettiva sua capacita' di trasmettere
dati. E' possibile utilizzare il comando track insieme
alle floating static route per potenziarne il
funzionamento, come in figura.
ip route 0.0.0.0 0.0.0.0 192.168.10.1 track 223
ip route 0.0.0.0 0.0.0.0 192.168.20.2 200
Figura 121 - 'ip route' con 'track'
182
Il bilanciamento di carico con
interfacce di tipo dialer e backup
Nel caso di collegamenti WAN, come ad esempio
ADSL, le interfacce coinvolte sono spesso di tipo
dialer. In questo caso si potrebbe bilanciare il
traffico in uscita tra i due circuiti, ad esempio se le
due ADSL sono con lo stesso operatore, adottando
la semplice configurazione in figura.
ip route 0.0.0.0 0.0.0.0 dialer0
ip route 0.0.0.0 0.0.0.0 dialer1
Figura 122 - Statiche e bilanciamento di carico in
interfacce Dialer
Anche in tale caso vale quanto detto in
precedenza tuttavia le interfacce di tipo dialer
hanno una particolarita' che e' bene conoscere. Puo'
accadere che entrambe le righe di routing restino in
tabella di routing anche se una delle due interfacce
non e' funzionante. Questo perche' le interfacce
dialer sono sempre nello stato di "up". Semmai
l'interfaccia "virtual-access" associata puo' essere
presente o meno a seconda dello stato del circuito
associato.
Se una riga di routing relativa ad un
collegamento non funzionante rimane nella tabella
di routing questo determina una perdita di
pacchetti. Nel caso di un bilanciamento di carico per
destinazione circa il 50% delle connessioni fallira'.
183
La soluzione e' abbastanza articolata e implica
l'utilizzo del comando "track" che crea un processo
di monitoraggio automatico in grado di determinare
se una interfaccia dialer e' funzionante o meno. Se
e' vero che una interfaccia dialer puo' restare
sempre nello stato di UP e' anche vero che, se un
collamento ADSL non funziona l'interfaccia sara'
sprovvista di indirizzo IP in quando il provider ISP
non e' stato in grado di assegnarlo. Questo e' vero
quando l'IP viene assegnato dal provider tramite
negoziazione del PPP.
track 10 interface Dialer0 ip routing
delay down 5 up 30
track 11 interface Dialer1 ip routing
delay down 5 up 30
ip route 0.0.0.0 0.0.0.0 Dialer0 track 10
ip route 0.0.0.0 0.0.0.0 Dialer1 track 11
!
1841-gia#sh track 10
Track 10
Interface Dialer0 IP routing
IP routing is Down (no IP addr)
1 change, last change 00:43:32
Delay up 30 secs, down 5 secs
Tracked by:
STATIC-IP-ROUTING 0
1841-gia#
1841-gia#sh track 11
Track 11
Interface Dialer1 IP routing
IP routing is Up
1 change, last change 00:43:33
Delay up 30 secs, down 5 secs
Tracked by:
STATIC-IP-ROUTING 0
Figura 123 - Dialer, load-balancing e comando track -
184
Il comando "track", come abbiamo gia’ visto, e'
in grado di monitorare alcuni stati di un router.
Interessa nel nostro caso perche' e' in grado di
verificare la capacita' di una interfaccia di fare
"routing", il che e' possibile solo se questo ha un
indirizzo IP. Questo tracciamento si aggancia alle
righe di routing statico che verranno eliminate
temporaneamente in caso di mancanza dei
prerequisiti imposti. Nell'esempio in figura 123, nel
caso in cui l'interfaccia dialer non sia in grado di
fare routing per piu' di 5 secondi, viene eliminata la
statica in corrispondenza del track. Se l'interfaccia
torna attiva dopo un disservizio si attenderanno 30
secondi per essere sicuri che non si tratti di un flap.
Con il comando "show track" si puo' verificare il
processo di monitoraggio.
In questo esempio monitoriamo non lo stato del
protocollo in una interfaccia (up o down), ma il fatto
che questa abbia o meno un indirizzo IP. Nel caso
delle interfacce di tipo dialer, con negoziazione PPP
dell'indirizzo IP, l'assenza di indirizzo IP implica
assenza di collegamento.
Cisco ASA, "track" & "ip sla"
In questo libro non trattiamo i firewall cisco della
serie ASA tuttavia molte delle funzionalita' dei
paragrafi precedenti, seppur con alcune differenze,
sono anche disponibili sui firewall Cisco ASA e PIX
7.X. Nell'esempio in figura si ha un Cisco ASA in
grado di verificare lo stato di efficenza di un
185
gateway e di smistare il traffico su un secondo
gateway in caso di fault.
sla monitor 123
type echo protocol ipIcmpEcho 18.87.179.129 interface
outside
num-packets 5
frequency 5
sla monitor schedule 123 life forever start-time now
track 1 rtr 123 reachability
route outside 0.0.0.0 0.0.0.0 18.87.157.93 1 track 1
route outside 0.0.0.0 0.0.0.0 18.87.157.90 100
Figura 124 - Cisco ASA: comandi 'sla monitor' e 'track'
Nell'esempio si verifica la raggiungibilita' ICMP
dell'indirizzo
IP
18.87.179.129,
attraverso
l'interfaccia outside. Il monitoraggio e' continuo "life
forever" ed e' attivo sempre. Nel caso di mancanza
di raggiungibilita' il comando track elimina la prima
riga di default che attiva, secondo le regole del
floating static route, la seconda. Con i comandi
"show ip sla statistics",
"show ip sla
configuration", "show track" e' possibile
monitorare lo stato.
Cisco EEM - Embedded Event
Manager Cisco IOS Embedded Event Manager (EEM) e' un
potente modulo software di Cisco IOS che permette
di automatizzare azioni in un router IOS scrivendo
delle policy. Per policy si intendono degli applet
186
oppure degli script realizzati utilizzando il linguaggio
di programmazione TCL. Puo' essere immaginato
come un'evoluzione di "IP SLA" ma in realta' lo
affianca e le due funzionalita' si possono integrare.
Infatti gli eventi generati dagli IP SLA possono
integrarsi con EEM. EEM e' disponibile nella versione
1.0 a partire dalla versione di IOS 12.0(26)S ma e'
consigliabile utilizzarlo a partire da IOS 12.3(4)T.
Event Manager permette di generare script di
monitoraggio utilizzando gli stessi comandi di IOS
oppure utilizzando il linguaggio TCL. L'introduzione
di un linguaggio di programmazione come il TCL
consente una grande flessibilita'.
EEM evolve di continuo e nel momento della
stesura di questo libro e' alla versione 3.2 presente
a partire da IOS 12.4(22)T. EEM 3.1 e' stato
introdotto con IOS 15.0 con TCL 8.3.4. A seconda
della release presente in IOS, che partono dalla 1.0,
le funzionalita' a disposizione possono variare. Con
il "Cisco Feature Navigator", strumento disponibile
nel sito web Cisco, e' possibile consultare le
funzionalita' a disposizione in ogni release di IOS.
Per conoscere quale versione di EEM e' attiva in
IOS potete utilizzare il comando "show event
manager version" come in figura 125. Osservate
la presenza di una lista di processi chiamati event
detectors. La lista, riportata parzialmente in
figura, rappresenta l'elenco di processi che
monitorizzano lo stato di IOS.
187
giahouse#show event manager version
Embedded Event Manager Version 3.20
Component Versions:
eem: (v320_rel1)1.0.1
eem-gold: (v320_rel1)1.0.0
eem-call-home: (v320_rel1)1.0.0
Event Detectors:
Name
Version Node
Type
application
01.00
node0/0 RP
neighbor-discovery 01.00
node0/0 RP
...
routing
02.00
node0/0 RP
syslog
01.00
node0/0 RP
cli
01.00
node0/0 RP
track
01.00
node0/0 RP
...
Figura 125 - Cisco EEM: comando "show event
manager"
Con le nuove release di EEM vengono introdotti
spesso nuovi event detectors che permettono un
monitoraggio sempre piu' completo. Per fare un
esempio il 'syslog' event detector, mostrato in
figura, intercetta tutti i messaggi syslog di sistema.
Per interderci quelli che vengono mostrati in
console. E' allora possibile da uno script EEM agire
in corrispondenza di determinati messaggi di
syslog. Lo stesso discorso si puo' ripetere per gli
altri event detector. Ad esempio l'event detector
"cli" permette di pubblicare un evento che esegue
dei comandi CLI, permettendo di modificare la
configurazione del router.
Notiamo anche la presenza dell'event detector
"track". Questo e' molto interessante perche' e'
legato al monitoraggio del processo associato ai
comandi "track". Poter intercettare gli eventi
188
generati dal comando track ci permette di
estenderne le potenzialita' come vedremo in un
esempio nei paragrafi successivi.
Configurazione di EEM
utilizzando gli applet
Non e' sempre necessario creare policy in TCL per
la gestione degli eventi. Se non dovete gestire degli
eventi complessi si possono creare degli applet
senza TCL. Con il comando "event manager
applet" (Dalla versione 12.4 nella serie 1800, dalla
versione 12.2 nei catalyst, dalla serie 800 da IOS
15.0) usato insieme al comando "ip sla reactionconfiguration" e' possibile in conseguenza a degli
eventi, definire delle azioni, utilizzando i comandi
IOS come linguaggio di script. Piuttosto che
elencare una serie di comandi e relativa sintassi
guardiamo subito un esempio in figura che e'
autoesplicativo.
event manager applet mioapplet
event syslog pattern "Interface Ethernet 0/0, changed
status to down"
action 1.0 cli command "enable"
action 2.0 cli command "conf t"
action 3.0 cli command "ip route 10.10.10.0 255.255.255.0
1.1.1.1"
action 4.0 mail server "192.85.14.73" to
"[email protected]" from "ciscorouter26" subject
"interfaccia down" body "attivato routing secondario"
Figura 126 - Cisco EEM: invio email in caso di evento
189
Nel sorprendente script in figura il sistema
monitorizza i messaggi di log della console di un
router. Se compare esattamente il messaggio
indicato tra doppi apici si attiva un trigger da cui
conseguono delle azioni (action). Questo determina
l'esecuzione in sequenza di tre comandi IOS con lo
scopo di attivare un collegamento di backup e
quindi di inviare una email per segnalare
all'amministratore di sistema l'evento (EEM V.2.1
per l'invio di email da applet). L'esempio e'
veramente illuminante. Infatti potete osservare
come il router si riconfiguri in autonomia in
conseguenza ad un evento. E' una possibilita'
considerevole. Le righe sono numerate. Questo ci
consente in un secondo tempo di aggiungere righe,
ma fate molta attenzione che le righe sono
interpretate alfabeticamente ovvero 10.0 viene
prima di 2.0!!!
Con il comando "event manager run" si
possono testare gli applet. Tuttavia prima bisogna
accertarsi che vi sia la riga "event none" nell'applet
altrimenti si ottiene il messaggio di errore in figura.
giahouse#event manager run mioapplet
EEM policy mioapplet not registered with event none Event
Detector
Figura 127 - Cisco EEM: invio email in caso di evento
Nel caso il cui l'applet utilizzi l'event syslog si
puo' inviare manualmente un messaggio al syslog
in modo da forzare l'avvio dello script in modo da
testarlo. Per fare questo da console utilizzare il
190
comando "send log {messaggio}". In questo modo
possiamo testare rapidamente gli applet. Per
stabilire se un applet e' stato eseguito si puo'
utilizzare il comando "show event manager
history events" che mostra lo storico dell' esecuzione degli applet. Affinche' una policy sia
utilizzabile questa dev'essere registrata. Per gli
applet la registrazione e' automatica a differenza di
quanto avviene per gli script TCL. Per vedere quali
policy sono registrate si utilizza il comando "show
event manager policy registered". Nel caso
dell'applet dell'esempio precedente si avra' l'output
mostrato in figura.
giahouse#show event manager policy registered
No. Class Type Event Trap Time Registered
Secu Name
1
applet user syslog Off Thu Dec 30 15:01:09 none mioapplet
pattern {Interface Ethernet 0/0, changed status to down}
maxrun 20.000
action 1.0 cli command "enable"
action 1.1 cli command "conf t"
action 1.2 cli command "ip route 10.10.10.0 255.255.255.0
1.1.1.1"
action 1.3 mail server "192.85.14.73" to
"[email protected]" from "cisco" subject "interfaccia down"
body "attivato routing secondario"
Figura 128 - Cisco EEM: invio email in caso di evento
Presentiamo un nuovo esempio in cui mostriamo
come gestire un evento relativo alla irraggiungibilita' di un indirizzo IP tramite ICMP. Questo
esempio e' molto utile perche' ci mostra come
integrare le funzionalita' di "IP SLA" con "EEM".
Nell'evento rileviamo l'irraggiungibilita' di un host
utilizzando le funzionalita' offerta da "IP SLA". In
caso di irraggiungibilita' EEM intercetta l'evento e
con un applet cambia la route di default. Questo
puo' essere estremamente utile per rilevare
191
correttamente un disservizio in un collegamento
Internet quindi questo applet e' di larga applicabilita'.
catalyst_backup#sh run | section sla
ip sla 10
icmp-echo 10.11.12.13 source-ip 10.11.12.14
timeout 100
ip sla schedule 10 life forever start-time now
track 1 ip sla 10 reachability
catalyst_backup#sh run | section event
event manager applet pingfailed
event track 1 state down
<-- 12.4(2)T in
IOS almeno
action 1.0 syslog msg " ping failed "
action 1.1 cli command "enable"
action 1.2 cli command "conf term"
action 2.0 cli command "ip route 0.0.0.0 0.0.0.0
192.168.30.145"
action 3.0 cli command "exit"
Figura 129 - Cisco EEM: riconfigurazione automatica in
caso di ICMP timeout
Combinando le funzionalita' di EEM, SLA e
TRACK possiamo anche creare eventi combinati
tramite funzioni booleane. Nell'esempio in figura
130 monitoriamo due collegamenti e solo nel caso
in cui entrambi siano DOWN si genera un evento.
Si noti che "AND" e "OR" del comando track
sono booleani. Ovvero ci vuole un OR per generare
un evento nel caso di contemporaneita' di due
FAIL. Una conseguenza di quanto spiegato e' che
possiamo anche riavviare il router in caso di eventi
straordinari. La sintassi e' nell'esempio che segue.
192
catalyst_backup#show run | section sla
ip sla 10
icmp-echo 10.11.12.13 source-ip 10.11.12.14
timeout 100
frequency 20
ip sla schedule 10 life forever start-time now
ip sla 11
icmp-echo 10.11.12.17 source-ip 10.11.12.18
timeout 100
frequency 20
ip sla schedule 11 life forever start-time now
track 111 ip sla 10 reachability
track 112 ip sla 11 reachability
catalyst_backup#show run | section track
track 1 list boolean or
object 111
object 112
track 111 ip sla 10 reachability
track 112 ip sla 11 reachability
catalyst_backup#show run | section event
event manager applet pingfailed
event track 1 state down
<-- 12.4(2)T IOS almeno
action 1.0 syslog msg " ping failed "
action 1.1 cli command "enable"
action 1.2 cli command "conf term"
action 2.0 cli command "ip route 0.0.0.0 0.0.0.0
19.16.4.1"
action 4.0 cli command "exit"
action 5.0 mail server "112.112.12.12" to
"[email protected]" from "[email protected]"
subject "corpo del messaggio" body "messaggio di test"
catalyst_backup#show track 1
Track 1
List boolean and
Boolean OR is Up
6 changes, last change 00:10:14
object 111 Up
object 112 Up
Tracked by:
EEM applet pingfailed
catalyst_backup#
Figura 130 - Cisco EEM: auto-riconfigurazione e email in
caso di DOWN
193
event manager applet ErroreGrave
event track 100 state down
action 1.0 syslog msg "Errore grave, riavvio il router"
action 2.0 reload
Figura 131 - Cisco EEM: invio messaggi al syslog e
riavvio sistema
Esempio sull'uso di EEM per
gestire la ridondanza
Nei piccoli uffici o comunque nelle strutture di
rete piu' semplici gestire la ridondanza degli accessi
ad Internet e' spesso problematico. Infatti non
possiamo fare affidamento agli algoritmi di routing
dinamico e per i collegamenti di fascia bassa
difficilmente gli ISP mettono a disposizione delle
offerte per il load-balancing o per il backup
automatico dei circuiti. Magari abbiamo due circuiti
ADSL con due operatori differenti e con
indirizzamento IP differente e questo spesso
impedisce anche un semplice load-balancing in
uscita in quanto non si possono usare gli indirizzi IP
di un ADSL con uno differente. Prima dell'avvento di
"IP SLA" e "EEM" il massimo che si poteva fare era
di rilevare con il "track" una interfaccia nello stato
di down e cambiare il routing di conseguenza, come
abbiamo visto nei paragrafi precedenti. In caso di
utilizzo del NAT la situazione si complicava
ulteriormente.
Nell'esempio che segue consideriamo una
configurazione piu' complessa e quindi piu' istruttiva con la presenza di due circuiti HDSL che
194
vogliamo in load-balancing con NAT e un terzo
circuito ADSL. L'ADSL viene utilizzato per traffico di
tipo VoIP, riconosciuta in base all'ip mittente. Se
l'ADSL non funziona vogliamo che la VoIP passi
automaticamente sull'HDSL. Viceversa se le HDSL
vanno entrambe giu' i dati devono transitare
sull'ADSL. Possiamo supporre che i collegamenti
siano anche con operatori differenti.
...
ip sla 3 icmp-echo AA.AA.AA.AA source-interface
Serial0/0/0.1
timeout 1500
frequency 8
ip sla schedule 3 life forever start-time now
!
ip sla 4
icmp-echo BB.BB.BB.BB source-interface Serial0/0/1.1
timeout 1500
frequency 8
ip sla schedule 4 life forever start-time now
!
track 10 rtr 3 reachability
delay down 40 up 40
!
track 11 rtr 4 reachability
delay down 40 up 40
!
track 12 interface Dialer1 IP routing
delay down 5 up 30
!
track 13 list boolean or
object 10
object 11
!
!
!
interface FastEthernet0/0
description --- interfaccia clienti con load-sharing --ip address FF.FF.FF.FF 255.255.255.0
ip policy route-map private
ip nat inside
!
interface FastEthernet0/1
description --- interfaccia server e clienti con nat
statico --IP address EE.EE.EE.EE 255.255.255.0
IP policy route-map private
195
!
interface Serial0/0/0
no IP address
encapsulation frame-relay IETF
load-interval 30
frame-relay lmi-type cisco
!
interface Serial0/0/0.1 point-to-point
bandwidth 2048
IP address CC.CC.CC.CC 255.255.255.252
IP nat outside
frame-relay interface-dlci 50 IETF
!
interface Serial0/0/1
no IP address
encapsulation frame-relay IETF
load-interval 30
frame-relay lmi-type cisco
!
interface Serial0/0/1.1 point-to-point
bandwidth 2048
IP address DD.DD.DD.DD 255.255.255.252
IP nat outside
frame-relay interface-dlci 50 IETF
!
interface ATM0/1/0
no IP address
IP nat outside
no atm ilmi-keepalive
dsl operating-mode auto
pvc 8/35
encapsulation aal5mux ppp dialer
dialer pool-member 1
!
!
interface Dialer1
ip address negotiated
ip nat outside
... configurazione ADSL...
!
ip route 0.0.0.0 0.0.0.0 Serial0/0/0.1 track 10
ip route 0.0.0.0 0.0.0.0 Serial0/0/1.1 track 11
ip route 0.0.0.0 0.0.0.0 Dialer1 200
!
ip nat inside source route-map adslvoip interface Dialer1
overload
ip nat inside source route-map uscitaload1 interface
Serial0/0/0.1 overload
ip nat inside source route-map uscitaload2 interface
Serial0/0/1.1 overload
!
access-list 10 remark -- classi di IP sorgenti per HDSL --
196
access-list 10 permit ...
access-list 20 remark -- classi di IP sorgenti per ADSL -access-list 20 permit ...
access-list 30 remark -- classi di IP sorgenti per secondo
HDSL-access-list 30 permit ...
!!! Con queste route map il NAT utilizza i tre
collegamenti in base al mittente
!route-map adslvoip permit 15
match IP address 20
set interface Dialer1
!
route-map uscitaload2 permit 20
match IP address 102
match interface Serial0/0/1.1
!
route-map uscitaload1 permit 10
match IP address 102
match interface Serial0/0/0.1
!!! Con queste route map i mittenti con IP pubblico escono
dalla connettivita' associata
route-map private permit 10
description --- HDSL --match IP address 10
set IP next-hop ...
!
route-map private permit 20
description --- ADSL --match IP address 20
set interface Dialer1
!
route-map private permit 30
description --- HDSL --match IP address 30
set IP next-hop ...
!
!
...
!
! EEM riconfigura il router in base al disservizio sul
circuito segnalato dagli eventi
! generati dal comando track
!
event manager applet ADSLDOWN
event track 12 state down
action 1.0 cli command "enable"
action 1.1 cli command "conf t"
action 1.5 cli command "no access-list 40"
action 1.6 cli command "access-list 102 permit IP ..."
action 1.8 cli command "exit"
event manager applet ADSLUP
event track 12 state up
197
action 1.0 cli command "enable"
action 1.1 cli command "conf t"
action 1.5 cli command "access-list 40 permit ..."
action 1.6 cli command "no access-list 102"
action 1.7 cli command "access-list 102 permit IP ..."
action 1.8 cli command "access-list 102 permit IP ..."
action 1.9 cli command "exit"
event manager applet DUEHDSLDOWN
event track 13 state down
action 1.0 cli command "enable"
action 1.1 cli command "conf t"
action 1.2 cli command "access-list 40 permit ..."
action 1.3 cli command "exit"
event manager applet DUEHDSLUP
event track 13 state up
action 1.0 cli command "enable"
action 1.1 cli command "conf t"
action 1.5 cli command "no access-list 40"
action 1.6 cli command "access-list 40 permit ..."
action 1.8 cli command "exit"
!
end
gianricotest# sh track
Track 10
Response Time Reporter 3 reachability
Reachability is Up
1 change, last change 04:15:47
Delay up 40 secs, down 40 secs
Latest operation return code: OK
Latest RTT (millisecs) 19
Tracked by:
STATIC-IP-ROUTING 0
Track 11
Response Time Reporter 4 reachability
Reachability is Up
7 changes, last change 03:37:58
Delay up 40 secs, down 40 secs
Latest operation return code: OK
Latest RTT (millisecs) 76
Tracked by:
STATIC-IP-ROUTING 0
Track 12
Interface Dialer1 IP routing
IP routing is Up
10 changes, last change 06:31:19
Delay up 30 secs, down 5 secs
Tracked by:
EEM applet ADSLUP
EEM applet ADSLDOWN
Track 13
List boolean and
198
Boolean OR is Up
8 changes, last change 03:37:58
object 10 Up
object 11 Up
Tracked by:
EEM applet DUEHDSLUP
EEM applet DUEHDSLDOWN
gianricotest#show IP sla statistics
Round Trip Time (RTT) for
Index 3
Latest RTT: 15 milliseconds
Latest operation start time: *20:25:48.344 UTC Fri Jan 8
2010
Latest operation return code: OK
Number of successes: 288
Number of failures: 0
Operation time to live: Forever
Round Trip Time (RTT) for
Index 4
Latest RTT: 648 milliseconds
Latest operation start time: *20:25:45.400 UTC Fri Jan 8
2010
Latest operation return code: OK
Number of successes: 290
Number of failures: 0
Operation time to live: Forever
gianricotest#show event manager history events
No. Time of Event
Event Type
Name
1
Fri Jan 8 08:45:57 2010 track
applet: ADSLDOWN
2
Fri Jan 8 08:47:25 2010 track
applet: ADSLUP
3
Fri Jan 8 13:53:37 2010 track
applet: ADSLDOWN
4
Fri Jan 8 13:54:28 2010 track
applet: ADSLUP
5
Fri Jan 8 16:18:33 2010 track
applet: DUEHDSLDOWN
6
Fri Jan 8 16:22:43 2010 track
applet: DUEHDSLUP
7
Fri Jan 8 16:24:08 2010 track
applet: DUEHDSLDOWN
8
Fri Jan 8 16:28:43 2010 track
applet: DUEHDSLUP
9
Fri Jan 8 16:40:03 2010 track
applet: DUEHDSLDOWN
10
Fri Jan 8 16:47:48 2010 track
applet: DUEHDSLUP
gianricotest#show ip route track-table
ip route 0.0.0.0 0.0.0.0 Serial0/0/0.1 track 10 state is
[up]
ip route 0.0.0.0 0.0.0.0 Serial0/0/1.1 track 11 state is
[up]
Figura 132 - Esempio di configurazione EEM + SLA
199
EEM e gli script TCL preinstallati
L'utilizzo di script in TCL e' un'alternativa
all'utilizzo degli applet. E' ovvio che le potenzialita'
sono di molto superiori rispetto gli applet. Tuttavia
bisogna apprendere il TCL e questo richiede del
tempo. Fortunatamente ci sono molti script TCL gia'
pronti e utilizzabili. Cisco fornisce degli script TCL di
esempio gia' preinstallati nel router. Gli script TCL
forniti da Cisco operano in 'full TCL mode' mentre
quelli scritti da un utente in 'safe TCL mode', una
versione di TCL priva di alcuni comandi che, se
utilizzati, potrebbero compromettere il buon
funzionamento del sistema.
Gli script TCL vengono chiamati da Cisco policy.
Router diversi con diverse versioni di IOS hanno file
di esempio differenti. Quindi cio' che vedrete nelle
figure a seguire potrebbe non combaciare con
quanto presente nel vostro router. Con il comando
"show event manager policy available" possiamo vedere quali policy sono installate nel nostro
router.
giahouse#show event manager
No. Type Time Created Name
1 system Mon Feb 7 07:28:15
2 system Mon Feb 7 07:28:15
3 system Mon Feb 7 07:28:15
4 system Mon Feb 7 07:28:15
5 system Mon Feb 7 07:28:15
6 system Mon Feb 7 07:28:15
7 system Mon Feb 7 07:28:15
policy available
2036
2036
2036
2036
2036
2036
2036
ap_perf_test_base_cpu.tcl
cl_show_eem_tech.tcl
no_perf_test_init.tcl
sl_intf_down.tcl
tm_cli_cmd.tcl
tm_crash_reporter.tcl
tm_fsys_usage.tcl
Figura 133 - Cisco EEM: script TCL preinstallati
200
Senza scendere nel dettaglio, che uscirebbe dagli
scopi di questo libro, osserviamo le policy di nome
"sl_intf_down.tcl" e "tm_cli_cmd.tcl".
Con il comando "show event manager policy
available detailed {nomepolicy}" e' possibile
vedere il sorgente TCL di una policy. Cio' che ci puo'
interessare sono le righe iniziali che spiegano le
funzionalita' dello script e le variabili che utilizza.
Come esempio vediamo una parte dello script
"tm_cli_cmd.tcl" fornito da Cisco in ogni IOS con
EEM. Questo script lo trovate in ogni router con
EEM ed e’ copyright Cisco System.
ite-7204#show event manager policy available detailed
tm_cli_cmd.tcl ::cisco::eem::event_register_timer cron
name crontimer2 cron_entry $_cron_entry maxrun 240
#---------------------------------# EEM policy that will periodically execute a cli command
# and email the results to a user.
#
# July 2005, Cisco EEM team
#
# Copyright (c) 2005-2006 by cisco Systems, Inc.
# All rights reserved.
#---------------------------------### The following EEM environment variables are used:
###
### _cron_entry (mandatory)
###
-A CRON specification that determines
###
when the policy will run. See the
###
IOS Embedded Event Manager
###
documentation for more information
###
on how to specify a cron entry.
### Example: _cron_entry
0-59/1 0-23/1 * * 0-7
###
### _log_file (mandatory without _email_....)
###
- A filename to append the output to.
###
If this variable is defined, the
###
output is appended to the specified
###
file with a timestamp added.
### Example: _log_file
disk0:/my_file.log
###
### _email_server (mandatory without _log_file)
201
###
- A Simple Mail Transfer Protocol (SMTP)
###
mail server used to send e-mail.
### Example: _email_server
mailserver.customer.com
###
### _email_from (mandatory without _log_file)
###
- The address from which e-mail is sent.
### Example: _email_from
[email protected]
###
### _email_to (mandatory without _log_file)
###
- The address to which e-mail is sent.
### Example: _email_to
[email protected]
###
### _email_cc (optional)- The address to which the e-mail
###
must be copied.
### Example: _email_cc
[email protected]
###
### _show_cmd (mandatory) - The CLI command to be executed
###
when the policy is run.
### Example: _show_cmd
show version
###
# check if all the env variables we need exist
# If any of them doesn't exist, print out an error msg and
quit
if {![info exists _log_file]} {
if {![info exists _email_server]} {
set result \
"Policy cannot be run: variable _log_file
or _email_server has not been set"
error $result $errorInfo
}
if {![info exists _email_from]} {
set result \
"Policy cannot be run: variable _log_file
or _email_from has not been set"
error $result $errorInfo
}
if {![info exists _email_to]} {
set result \
"Policy cannot be run: variabl _log_file
ore _email_to has not been set"
error $result $errorInfo
}
if {![info exists _email_cc]} {
#_email_cc is an option, must set to empty string
if not set.
set _email_cc ""
}
}if {![info exists _show_cmd]} {
set result \
"Policy cannot be run: variable _show_cmd has not been
set"
error $result $errorInfo
202
}
namespace import ::cisco::eem::*
namespace import ::cisco::lib::*
…snip…
# 1. execute the command
if [catch {cli_open} result] {
error $result $errorInfo
} else {
array set cli1 $result
}
if [catch {cli_exec $cli1(fd) "en"} result] {
error $result $errorInfo
}
# save exact execution time for command
set time_now [clock seconds]
# execute command
if [catch {cli_exec $cli1(fd) $_show_cmd} result] {
error $result $errorInfo
} else {
set cmd_output $result
# format output: remove trailing router prompt
set prompt [format
"(.*\n)(%s)(\\(config\[^\n\]*\\))?(#|>)" $routername]
if [regexp "[set prompt]" $result dummy cmd_output] {
# do nothing, match will be in $cmd_output
} else {
# did not match router prompt so use original output
set cmd_output $result
}
}
if [catch {cli_close $cli1(fd) $cli1(tty_id)} result] {
error $result $errorInfo
}
# 2. log the success of the CLI command
set msg [format "Command \"%s\" executed successfully"
$_show_cmd]
action_syslog priority info msg $msg
if {$_cerrno != 0} {
set result [format "component=%s; subsys err=%s; posix
err=%s;\n%s" \
$_cerr_sub_num $_cerr_sub_err $_cerr_posix_err
$_cerr_str]
error $result
}
# 3. if _log_file is defined, then attach it to the file
if {[info exists _log_file]} {
# attach output to file
if [catch {open $_log_file a+} result] {
error $result
}
set fileD $result
# save timestamp of command execution
203
# (Format = 00:53:44 PDT Mon May 02 2005)
set time_now [clock format $time_now -format "%T %Z %a
%b %d %Y"]
puts $fileD "%%% Timestamp = $time_now"
puts $fileD $cmd_output
close $fileD
}
# 4. if _email_server is defined send the email out
if {[info exists _email_server]} {
if {[string match "" $routername]} {
error "Host name is not configured"
}
if [catch {smtp_subst [file join $tcl_library
email_template_cmd.tm]} \
result] {
error $result $errorInfo
}
if [catch {smtp_send_email $result} result] { error
$result $errorInfo }
}
Figura 134 - Cisco EEM: tm_cli_cmd.tcl
Come si evince dai commenti questa policy
esegue periodicamente un comando CLI e ne invia i
risultati via email oppure li memorizza in un file.
Vediamo come utilizzarla nel caso piu' semplice.
Dobbiamo innanzitutto inizializzare le variabili
"_cron_entry" e "_log_file" e "_show_cmd" con dei
valori.
Per inizializzare le variabili bisogna utilizzare il
comando
"event
manager
environment
{variabile} {valore}". Con il comando "show
event manager environment all" e' possibile
verificare i valori di tutte le variabili inserite. Il cron
si aspetta nell'ordine: minuti, ore, giorno del mese,
mese, giorno della settimana. Per la ripetizione si
usa lo "/" e per gli intervalli il "-". Per eseguire lo
script ogni 10 minuti inseriamo "*/10 * * * *".
204
Con il comando "event manager policy
{nomepolicy} type system" registriamo la policy
che cosi' viene resa utilizzabile dal sistema. Se si
vuole attivare il debug per EEM utilizzare il
comando "debug event manager all".
Nella figura che segue vediamo un esempio di
applicazione. Inizializziamo le variabili per far
eseguire il comando "show run" e per inserirne
l'output nel file di nome "test.log".
GIA-7204(config)#event manager environment _cron_entry
*/10 * * * *
GIA-7204(config)#event manager policy tm_cli_cmd.tcl type
system
GIA-7204(config)#event manager environment _log_file
flash:/test.log
giahouse#show event manager environment all
No. Name
Value
1
_log_file
flash:/test.log
2 _ show_cmd
show run
3
_cron_entry
0-59/5 * * * 4
...
GIA-7204#show event manager policy registered
No. Class
Type
Event Type
Trap Time
Registered
Secu Name
1
script
system timer cron
Off
Sat Dec
26 13:20:42 2009 none tm_cli_cmd.tcl
name {crontimer2} cron entry {*/10 * * * *}
nice 0 queue-priority normal maxrun 240.000 scheduler
rp_primary
Figura 135 - Cisco EEM: registrazione delle policy
Riprenderemo la spiegazione di questo codice
Cisco piu’ avanti. Presentiamo adesso l'altra policy
fornita da Cisco che abbiamo attenzionato. Il suo
nome e' sl_intf_down.tcl e monitorizza il syslog di
sistema inviando una email nel caso in cui appaia
205
un messaggio che fa match con una espressione
regolare indicata dall'utente. E' molto utile per
monitorare lo stato delle interfacce.
Le policy che abbiamo visto sinora sono di
sistema ovvero fornite da Cisco. Non e' possibile
modificare queste policy. Quello che si puo' fare e'
duplicarne il contenuto e quindi editarlo a
piacimento.
EEM e gli script TCL creati dall'utente
La prima cosa da fare quando si vogliono scrivere
script TCL e' definire nel router la directory dove
questi verranno posizionati. Nella shell di Cisco sono
ormai presenti molti comandi simili a quelli della
shell di Linux. Ad esempio si possono utilizzare i
comandi "mkdir" "rmdir" per creare o rimuovere
una directory. E' possibile utilizzare "more" per
visualizzare su schermo un file di testo. E' anche
possibile utilizzare "dir" e "cd". Per creare una
directory, nel caso in cui il nostro dispositivo di
memorizzazione e' "flash:", procediamo come
indicato in figura.
giahouse#mkdir flash:
Create directory filename []? mieitcl
Created dir flash:mieitcl
Figura 136 - Creazione directory con il comando 'mkdir'
E' ora necessario impostare questa directory per
l'uso con TCL con i comandi in figura.
206
giahouse(config)#event manager directory user library
flash:/mieitcl
giahouse(config)#event manager directory user policy
flash:/mieitcl
giahouse(config)#exit
giahouse#show event manager directory user library
flash:/mieitcl
giahouse#
giahouse#show event manager directory user policy
flash:/mieitcl
giahouse#
Figura 137 - Cisco EEM: registrazione directory per gli
script
Adesso siamo pronti per la realizzazione dei
nostri script TCL. I nomi devono seguire le
convenzioni Cisco. Ci limitiamo per adesso alla piu'
banale, ovvero tutti i file devono terminare con
".tcl".
Minicorso di TCL
Ovviamente non si puo' apprendere un linguaggio
di programmazione in poche pagine. Per imparare il
TCL si rimanda ad un testo specifico. Questo
paragrafo e' una buona traccia per comprenderne la
filosofia e i comandi principali.
Per poter inserire comandi TCL si deve entrare
nella shell TCL di IOS. Si entra nella shell comandi
TCL con il comando "tclsh". Con il comando "tclsh
{pathfile}" si esegue uno script TCL che puo'
207
trovarsi nel router oppure in una location esterna
(piu' avanti scenderemo nel dettaglio).
Nella shell tclsh potete inserire direttamente
comandi TCL e vederne subito i risultati in quanto si
tratta di un linguaggio interpretato. Per eseguire dei
programmi completi TCL bisogna scriverli nel
proprio PC in quanto Cisco non ha un editor di testo
embedded nel sistema operativo. Questo non
complica le cose in quanto e' possibile eseguire in
tempo reale dei programmi TCL che sono esterni al
router e solo successivamente, dopo aver
completato tutti i test, e' possibile trasferire
all'interno del router. E' possibile selezionare come
"pathfile" del comando tclsh una destinazione
comprendente una delle seguenti parole chiave:
TFTP, FTP, TCP, SCP, HTTP, HTTPS. Per eseguire
uno script gia' presente nel router bastera' digitare
"tclsh {script.tcl}".
Anche se TCL e' un linguaggio interpretato e'
possibile caricare nel router degli script precompilati
oppure compilati. Questo e' utile ai fini della
sicurezza in quanto un codice precompilato non e'
facilmente consultabile. E' disponibile gratuitamente
un compilatore TCL presso l'URL http://tclpro.
sourceforge.net. Per conoscere quale versione di
TCL e' installata e i comandi disponibili si eseguono
i comandi nella figura che segue.
208
giahouse(tcl)#info patchlevel
8.3.4
giahouse(tcl)#info commands
tell socket subst open eof pwd glob list exec pid
snmp_getone time eval lrange tcl_trace fblocked lsearch
gets case lappend proc break variable llength return
linsert snmp_getid error catch clock info split array if
log_user fconfigure concat join lreplace snmp_setany
source fcopy global switch snmp_getbulk update close cd
for file append format udp_open read package set binary
namespace scan verify_signature seek while flush after
vwait snmp_getnext typeahead uplevel continue hostname
ios_config foreach rename fileevent regexp upvar unset
encoding expr load regsub interp history puts incr lindex
lsort udp_peek string
Figura 138 - Cisco TCL - versione installata e comandi
disponibili -
Variabili TCL e I/O di base
TCL supporta sia tipi di dati numerici che
stringhe. I tipi di dati stringa utilizzano i doppi apici
e non hanno limitazione in lunghezza (questa non e'
una considerazione secondaria in quanto in un tipo
stringa spesso inseriremo l'output di comandi di IOS
che puo' essere piuttosto lungo). Con il comando
"set" si assegnano dei valori alle variabili mentre
con il comando "puts" si visualizza sullo schermo
un messaggio oppure il valore di una variabile. Con
il comando "expr" si utilizzano i valori delle variabili
che possono essere elaborati, ad esempio con
operazioni aritmetiche in caso di valori numerici.
Esistono anche gli array che si definiscono
utilizzando le parentesi tonde. Poi vi sono varie
funzioni di elaborazione delle stringhe, come
"match" o "lenght" che ci permettono di trovare
209
una sottostringa oppure determinare la lunghezza.
La figura mostra un’applicazione di quanto detto.
giahouse(tcl)#set miavar1 5
5
giahouse(tcl)#set miavar2 6
6
giahouse(tcl)#puts $miavar1
5
giahouse(tcl)#info exists miavar2
1
giahouse(tcl)#puts $miavar1+$miavar2
5+6
giahouse(tcl)#expr {$miavar1+$miavar2}
11
giahouse(tcl)#puts [expr {$miavar1+$miavar2}]
11
giahouse(tcl)#puts "ciao [expr {$miavar1+$miavar2}]"
ciao 11
giahouse(tcl)#puts "Prima riga \nSeconda riga"
Prima riga
Seconda riga
giahouse(tcl)#puts "\t Colonna 1 \t Colonna2"
Colonna 1
Colonna2
giahouse(tcl)#set b(1) 1
1
giahouse(tcl)#set b(2) 2
2
giahouse(tcl)#set b(3) 3
3
giahouse(tcl)#set miafrase "casa cisco router internet"
casa cisco router internet
giahouse(tcl)#string match cisco $miafrase
0
giahouse(tcl)#string match *cisco* $miafrase
1
giahouse(tcl)#string match *cisbo* $miafrase
0
giahouse(tcl)#string length $miafrase
26
Figura 139 - Cisco TCL - Variabili -
I commenti si inseriscono con "#" a inizio riga.
210
File
La gestione dei file ci permette di creare dei file
di testo inserendone o leggendone dei valori. Se
non indicato altrimenti questi file vengono inseriti
nel device di default che in genere e' "flash:". Un
file si crea o si apre con il comando "open"
indicando per la lettura la lettera "w" oppure per la
scrittura la lettera "r". Con il comando "puts" e'
possibile inserire dati e con "close" chiudere il file.
Segue un esempio.
giahouse(tcl)#set miofile [ open "filetesto1" w]
file0
giahouse(tcl)#puts $miofile "prova"
giahouse(tcl)#close $miofile
giahouse(tcl)#more flash:/filetesto1
prova
giahouse(tcl)#set miofile [ open "filetesto1" r]
file0
giahouse(tcl)#gets $miofile
prova
giahouse(tcl)#close $miofile
Figura 140 - Cisco TCL - Gestione file -
Espressioni regolari
Dovete imparare bene l'utilizzo delle espressioni
regolari se volete poter scrivere degli script utili con
IOS. Infatti molto spesso uno script legge l'output
di comandi di IOS alla ricerca di dati o valori ben
precisi. Per fare questo si utilizzano le espressioni
regolari. Nella figura che segue, assegnata una
stringa di testo estraiamo alcuni valori utilizzando
delle espressioni regolari. Si utilizza il comando
211
"regexp" che si aspetta in input la stringa su cui
effettuare la ricerca e poi una seconda variabile in
cui memorizzare il risultato. Il comando restituisce
anche l'esito dell'operazione ovvero "1" nel caso in
cui abbia trovato un match, "0" in caso contrario.
Con ".*" si intende una qualsiasi sequenza di testo
o numeri, con "[0-9]" si intende una singola cifra,
con "[0-9]+" si intende una sequenza di cifre. Il
valore "\" indica di non interpretare il carattere
successivo, nel caso in cui si crei un'ambiguita'
perche' quel carattere e' anche un comando di
espressione regolare.
giahouse(tcl)#set stringa "L'indirizzo IP e'
192.168.30.10"
L'indirizzo IP e' 192.168.30.10
giahouse(tcl)#regexp {IP.*} $stringa risultato
1
giahouse(tcl)#puts $risultato
IP e' 192.168.30.10
giahouse(tcl)#set ris [regexp {[0-9]} $stringa risultato]
1
giahouse(tcl)#puts $risultato
1
giahouse(tcl)#set ris [regexp {[0-9]+} $stringa risultato]
1
giahouse(tcl)#puts $risultato
192
giahouse(tcl)#regexp {[0-9]+\.[0-9]+} $stringa risultato
1
giahouse(tcl)#puts $risultato
192.168
Figura 141 - Cisco TCL - Espressioni regolari -
Gestione errori
Con il comando "catch" possiamo intercettare le
condizioni di errore. Nell'esempio che segue
212
inseriamo
nella
variabile
"risultato"
la
configurazione del router. In una ipotesi di errore
questo viene catturato e inserito nella variabile
"errore" e quindi puo' essere gestito all'interno del
codice.
giahouse(tcl)#if {[ catch {set risultato [exec
{show run}]} errore]} { puts "Errore: $e" }
Figura 142 - Cisco TCL - Comando 'catch' -
Se invece di "show run" avessimo utilizzato un
comando non presente nella versione di IOS in uso
oppure un comando improprio avremmo potuto
gestire l’errore. Se riprendiamo il file TCL di
esempio tm_cli_cmd.tcl presentato nei paragrafi
precedenti osserviamo l'utilizzo del comando
"catch" ad ogni esecuzione di un comando per
intercettare una condizione di errore.
Procedure
Come in tutti i linguaggi di programmazione e'
possibile scrivere subroutine da chiamare nel
codice. Nella figura 143 si mostra una subroutine
che effettua la moltiplicazione di due valori numerici
e ne restituisce il risultato.
213
gia(tcl)#proc moltiplica {var1 var2} {
+>set x [expr {$var1 * $var2}]
+>return $x
+>}
gia(tcl)#puts [moltiplica 2 3]
6
Figura 143 - Cisco TCL - Procedure -
Cicli
Anche in questo caso si tratta dei soliti comandi
presenti praticamente in ogni linguaggio di
programmazione, con una sintassi differente,
ovvero gli onnipresenti "for" e "while".
gian(tcl)#for {set i 0 } { $i <= 20} {incr i} {puts $i}
0
...
20
gian(tcl)#set x 10
gian(tcl)#while {$x < 12} {
+>puts $x
+>set x [expr {$x +1}]
+>}
10
11
Figura 144 - Cisco TCL - Cicli -
Espressioni condizionali
Si utilizzano i comandi "if...then...else" e "switch"
come in figura.
214
gia(tcl)#if {$x == 2} {puts "vale 2"} else {puts "vale 3"}
gia(tcl)#if {$x != 3} {puts "ciao"}
gia(tcl)#set x 20
gia(tcl)#switch $x {
+>"10" { puts "dieci"}
+>"20" { puts "venti"}
+>}
Figura 145 - Cisco TCL - Espressioni condizionali -
Esecuzione comandi IOS
Dall'interno degli script TCL e' possibile eseguire
un qualsiasi comando IOS. Questo da grandi
potenzialita' ai nostri script che hanno piena
visibilita' della configurazione del router e possono
modificarla a piacimento. Con le istruzioni "exec
{comando}"
e
"ios_config
{comando1}
{comando2}" e' possibile eseguire comandi in
modalita'
privilegiata
oppure
in
modalita'
configurazione. L'uso di piu' comandi in ios_config
potrebbe essere utilizzato per configurare le
subinterface, ad esempio.
giahouse(tcl)#exec "show ver | include ATM"
1 ATM interface
giahouse(tcl)#ios_config "hostname prova"
prova(tcl)#ios_config "hostname giahouse"
giahouse(tcl)#
giahouse(tcl)#ios_config "int atm0" "description -- rete 1
---"
Figura 146 - Cisco TCL - Esecuzione comandi CLI –
215
Socket
Sappiamo che i socket sono degli endpoint per la
comunicazione IP. Un socket e' caratterizzato da un
indirizzo IP e da una porta e permette la
comunicazione tra dispositivi presenti in una rete
TCP/IP. Qualunque programma del nostro PC che si
interfaccia con la rete IP utilizza i socket: browser
http, client di posta, client FTP, programmi di
comunicazione come quelli di chat, voip, peer-topeer.
Ogni linguaggio di programmazione che si rispetti
permette di creare socket per permettere la
comunicazione tra processi presenti nello stesso o
in PC differenti tramite il protocollo IP.
Molti virus, trojan e quant'altro utilizzano i
socket. Un socket infatti apre il nostro PC a comunicazioni verso l'esterno, e questo e' sconosciuto ai
comuni utenti Internet. E' possibile utilizzare i
socket in TCL? La risposta e' affermativa. Lo
strumento e' potente e pericoloso. Roba tosta,
ragazzi.
Per capire come funzionano i socket, e divertirci
allo stesso tempo, creiamo una backdoor nel nostro
router, utile come accesso di emergenza.
Osserviamo il codice in figura 147.
216
set port 1212
set miosock [socket -server miaprocedura $port]
vwait attendi
Figura 147 - Cisco TCL - Socket - esempio parte 1 -
Il comando "socket" ci permette di creare un
endpoint TCP per la comunicazione. La sintassi
"socket -server {funzione} {porta}" apre il
socket in ascolto nella porta indicata con 'porta',
ovvero crea il lato server di una comunicazione con
uno o piu' client. Nel caso dell'esempio non appena
arrivera' una richiesta di connessione alla porta
1212 verra' automaticamente chiamata la funzione
'miaprocedura'. Dopo l'apertura di un socket viene
rilasciato dal sistema un identificativo, inserito
nell'esempio nella variabile "miosock" con il quale e'
possibile fare riferimento al socket durante tutto lo
script TCL.
Con il comando "vwait {var}" lo script entra in
attesa finche' la variabile 'var' non viene modificata.
Senza quest'ultima condizione lo script non e' in
grado di restare in ascolto. Entrare in attesa e'
fondamentale per poter accettare in qualsiasi
momento
richieste
esterne.
Sara'
nostra
responsabilita' utilizzare la variabile al momento
giusto, cosi' da arrivare alla successiva istruzione
'close' dell'esempio, altrimenti il server restera' in
attesa indefinitivamente, cosa che pero' e'
normalmente voluta.
217
Andiamo dunque alla seconda parte dell'esempio
ovvero la scrittura della procedura da avviare al
momento in cui arriva una richiesta di connessione
dall'esterno.
# Occhio ai commenti, che siano a inizio riga
# Occhio alle parentesi graffe, devono essere aperte nella
# stessa riga dei comandi
proc miaprocedura {sock indirizzoip porta} {
puts "Debug: Connessione $sock accettata dall'indirizzo
$indirizzoip con porta $porta"
fconfigure $sock -buffering line -translation lf
#
# Invia un messaggio al client
#
puts $sock "----------------------------"
puts $sock "|- GF backdoor - welcome
|"
puts $sock "----------------------------"
puts $sock "gf>"
#
# Legge un messaggio dal client
#
fileevent $sock readable [list leggi $sock]
}
Figura 148 - Cisco TCL - Socket - esempio parte 2 -
Non appena arriva una richiesta esterna il
sistema chiama automaticamente la procedura
'miaprocedura' e questo perche' l'abbiamo istruito il
tal modo con il comando 'socket'. Per facilitare la
fase di test dello script, visualizziamo sullo schermo
un messaggio indicante l'avvenuta connessione da
parte di un client. A questo punto introduciamo il
comando "fconfigure {socket}{parametri}" che
ci permette di impostare delle opzioni per un
socket. Con '-buffering line' richiediamo una
trasmissione separata per ogni linea che termina
con un newline. Detto in altri termini ogni comando
'puts' del nostro esempio inviera' un suo pachetto
218
IP. Con '-translation lf' definiamo il tipo di
'newline'. In questo caso con 'lf' intendiamo lo stile
UNIX di utilizzare un singolo carattere di newline.
Con il comando "fileevent {sock} readable |
writable {script}" il sistema aggancia uno script
ad un canale (tecnicamente file event handler).
Quando e' possibile leggere o scrivere dal canale il
sistema utilizza lo script indicato. Nel nostro
esempio non appena il client invia qualche dato lo
script chiama automaticamente la procedura 'leggi'
passando come parametro l'identificativo del
socket. L'uso del comando "list" che crea una lista,
ovvero una sequenza di dati, serve per poter inviare
a fileevent il nome della procedura con tutti i suoi
parametri correttamente. A questo punto ci manca
semplicemente la procedura per gestire le richieste
del client.
proc leggi {sock} {
if {[eof $sock] || [catch {gets $sock richiesta}]} {
# situazione di anormalita', ad esempio caduta
connessione
puts "Debug: condizione di errore nella lettura
dal client rilevata"
} else {
set risposta[exec "$richiesta"]
puts $sock "gf>"
puts $sock $response
# Termina la comunicazione con un client
# L'applicazione TCL rimane in ascolto
# Togliere questa riga per fare piu'
interrogazioni al router in una unica
# connessione
close $sock
}
}
Figura 149 - Cisco TCL - Socket - esempio parte 3 -
219
E' necessario attenzionare la posizione delle
parentesi graffe negli script. Come avrete forse
notato dai commenti le parentesi graffe vanno
aperte o chiuse nella stessa riga in cui si trova il
comando associato. Intendo dire che "} else {"
non e' la stessa cosa di "else" con le parentesi in
righe differenti. Per lo stesso motivo si scrive "if
{condizione} {" e non "if {condizione}" e la
parentesi nella riga successiva. A questo punto
vorremmo lanciare questo script e testarlo. Lo
script e' in grado di leggere messaggi da una porta
TCP. Cosa possiamo utilizzare come client?
Utilizzeremo il comando "nc" presente nei sistemi
Linux e che consente di inviare facilmente dei dati
tramite connessioni TCP/IP.
Colleghiamoci al router e lanciamo manualmente
lo script creato nel server FTP.
giahouse#tclsh
ftp://itesys:[email protected]/CISCO_TCL/giaserver.tcl
Loading CISCO_TCL/giaserver.tcl !
[OK - 1076/4096 bytes]
Figura 150 - Cisco TCL: lancio di script da shell tcl
Da una postazione client Linux colleghiamoci al
router tramite la backdoor creata. Quindi lanciamo
un comando.
220
[root@radius1 ~]# nc 192.168.50.12 1213
---------------------------|- GF backdoor - welcome
|
---------------------------gf>
show ver | include Cisco
gf>
Cisco IOS Software, C870 Software (C870-ADVIPSERVICESK9-M),
Version 15.1(3)T, RELEASE SOFTWARE (fc1)
Copyright (c) 1986-2010 by Cisco Systems, Inc.
use. Delivery of Cisco cryptographic products does not imply
A summary of U.S. laws governing Cisco cryptographic products may
be found at:
Cisco 877 (MPC8272) processor (revision 2.0) with 236544K/25600K
bytes of memory.
Figura 151 - Cisco TCL: Utilizzo comando linux 'nc' per
connessione a server
Come si vede e' possibile inviare comandi al
router e vedere le risposte senza utilizzare il telnet
o l'ssh. Vediamo cosa succede se proviamo a
cambiare la configurazione del router tramite la
backdoor.
[root@radius1 CISCO_TCL]# nc XX.XX.XX.XX 1213
---------------------------|- GF backdoor - welcome |
---------------------------gf>
conf t
gf>
% Configuration not allowed from TCL shell.Use
'ios_config' instead
Figura 152 - Cisco TCL: comandi di configurazione e
comando exec
Editando lo script opportunamente e' possibile
pertanto anche modificare la configurazione.
221
L'esempio e' molto istruttivo anche perche' ci
introduce a nuovi tipi di minacce alla sicurezza dei
nostri router che prima non esistevano. E'
abbastanza ovvio che per inserire lo script TCL nel
router bisogna averne prima l'accesso quindi non e'
il caso di allarmarsi eccessivamente.
Questo esempio ci suggerisce la possibilita’ per
uno script TCL in esecuzione in un router di
collegarsi in telnet ad un secondo router e di
interagire con esso con una sequenza di comandi.
Allora in caso di condizioni di guasto possiamo non
solo modificare la configurazione di un router A ma
anche router esterni B e C che NON hanno supporto
TCL.
giahouse#tclsh
ftp://itesys:[email protected]/CISCO_TCL/giaserver.tcl
Loading CISCO_TCL/giaserver.tcl !
[OK - 1060/4096 bytes]
sock0_ipv4
couldn't open socket: address already in use while
executing
"socket -server miaprocedura $port"
invoked from within
"set miosock [socket -server miaprocedura $port]"
(file
"ftp://itesys:[email protected]/CISCO_TCL/giaserver.tcl
" line 33)
giahouse#show processes cpu | include Tcl
48
44
21
2095
0.00% 0.00% 0.00% 2 Tcl Serv tty2
giahouse#show users
Line
User
Host(s)
Idle
Location
2 vty 0 gianrico
idle
00:16:23 69it.itesys.it
* 3 vty 1 gianrico
idle
00:00:00 69it.itesys.it
Interface User
Mode
Idle
Peer Address
Figura 153 - Cisco TCL: controllo script in esecuzione
222
Tornando al nostro esempio si puo' osservare che
lo script lanciato da TCL sembra instoppabile. Di
fatto rimane in esecuzione. Se si apre una nuova
sessione con il router ecco mostrato in figura 153
come individuare gli script che sono in esecuzione
in background.
Secondo la documentazione con il comando
"clear line" si dovrebbe poter stoppare l'esecuzione di uno script. Infatti non esiste un comando
"kill" per fermare i processi come in Linux. Nel mio
caso ho dovuto riavviare il router tuttavia e'
probabile che dipenda dalla versione di IOS
utilizzata nel lab. Approfitto per segnalare che gli
esempi riportati in questo libro sono legati a
specifiche versioni di IOS la cui evoluzione e'
continua. Inoltre vi sono un numero notevole di
versioni differenti ognuna con dei bug noti (basta
cercare nel sito cisco le keyword 'caveats release'
per rendersene conto). Quindi per far funzionare
tutto bene nel vostro sistema potrebbero essere
necessari degli aggiustamenti.
Namespace
I namespace sono collezioni di procedure e
variabili. Sono un po' come le classi in C.
Permettono di creare librerie di funzioni che non
interferiscono con il codice esterno al namespace.
Per esempio le variabili in un namespace possono
avere lo stesso nome di altre variabili in altri
namespace. Con il simbolo "::" ci si muove
all'interno di una gerarchia di namespace. La root
223
della gerarchia e' il simbolo "::" posto inizialmente.
Sotto il namespace globale c'e' definito il
namespace "cisco" che ha a sua volta il namespace
"eem" al suo interno.
Lo script tm_cli_cmd.tcl
Riprendiamo lo script di esempio mostrato nei
paragrafi precedenti per capire altri elementi di TCL
specifici ai router Cisco.
- La prima riga di uno script TCL e' di
fondamentale importanza in quanto definisce quando lo script verra' eseguito. E' possibile schedulare
l'esecuzione di uno script un po' come si fa in
ambiente linux utilizzando 'crontab'.
Nello script tm_cli_cmd.tcl la prima riga e' la
seguente:
::cisco::eem::event_register_timer cron name
crontimer2 cron_entry $_cron_entry maxrun 240
Figura 154 - Cisco TCL: schedulazione script TCL
Questa indica che lo script deve essere eseguito
periodicamente in base a quanto indicato nella
variabile _cront_entry che e' prescelta dall'utente.
Con "maxrun" si indica al sistema il tempo massimo
che puo' impiegare lo script per la sua esecuzione.
224
Se lo script non dev'essere schedulato si utilizza
'event_register_none' come in figura.
:cisco::eem::event_register_none
Figura 155 - Cisco TCL: script non schedulato
- Le righe successive normalmente verificano che
l'utente abbia inserito un valore per le variabili
richieste.
if![info exists _email_server]} {
set result \
"Policy cannot be run: variable _email_server has
not been set"
error $result $errorInfo
}
Figura 156 - TCL: verifica esistenza variabili
set par1 [lindex $argv 0] # primo parametro
set par2 [lindex $argv 1] # secondo parametro
Figura 157 - Cisco TCL: passaggio parametri
- A questo punto incontriamo l'import dei
namespace relativi a eem e lib. Questo permette
allo script di utilizzare le procedure presenti in
questi namespace. Si veda nel sito Cisco l'elenco
completo. Nel prossimo script di esempio ne e'
presentata qualcuna.
225
namespace import ::cisco::eem::*
namespace import ::cisco::lib::*
Figura 158 - TCL: 'namespace'
Ecco in figura un'applicazione che utilizza gli
ultimi concetti descritti. E’ derivata direttamente da
uno degli esempi messi a disposizione da Cisco con
TCL in IOS.
:cisco::eem::event_register_none
#'event_register_none':
#
questa policy viene eseguita da cli quando si esegue
il comando 'event manager run'
# - Si puo' anche usare 'event_register_timer'
#
per indicare ogni quanto la policy dev'essere eseguita
# - Si puo' anche usare 'event_register_syslog'
#
per fare eseguire la policy se nel syslog appare un
#
certo messaggio per un certo numero di volte
# - Si puo' anche usare 'event_register_ipsla'
#
per fare eseguire la policy in conseguenza ad un
#
trigger 'ip sla'
# - Si puo' anche usare 'event_register_inteface'
#
per far eseguire la policy se un contatore
#
in una interfaccia
#
supera una certa soglia
# - Si puo' anche usare 'event_register_rpc'
#
per far eseguire la query da un sistema remoto tramite
#
SSH.
#
Vedi anche perl 'CISCO::EEM::RPC'
#
Vedi anche nel sito Cisco cerca "Writing Embedded
Event Manager Policies Using Tcl".
#
# Questo script esegue una sequenza di comandi e ne
# memorizza l'output in un file
#
namespace import ::cisco::eem::*
namespace import ::cisco::lib::*
#
# Nella procedura che segue vedete delle funzioni presenti
# nel namespace. In particolare'cli_open' apre una vty,
# cioe' una shell che e' poi importante chiudere
# 'cli_close' alla fine del codice.
# Fallisce se non ci sono almeno 3 vty libere
proc CLICmdProc {cmds} {
226
if [catch {cli_open} result] {
error $result $errorInfo
} else {
array set cli1 $result
}
# Si esegue il comando 'enable'
if [catch {cli_exec $cli1(fd) "enable"} result]
{
error $result $errorInfo
}
# 'cli_exec' e' una procedura Cisco che esegue un comando
# di shell .Notate il comando "term lenght 0" che
# disabilita la space bar per far
# avanzare l'output dei comandi su schermo
if [catch {cli_exec $cli1(fd) "term len 0"} result]
{
error $result $errorInfo
}
# In questo ciclo si eseguono i comandi richiesti
foreach comando $cmds
{
if [catch {cli_exec $cli1(fd) $comando} result] {
error $result $errorInfo
} else {
lappend risultato $result
}
}
if [catch {cli_close $cli1(fd) $cli1(tty_id)} result] {
error $result $errorInfo
}
# Restituisce una lista contenente l'output
return $risultato
}
# MAIN - INIZIO ESECUZIONE #
# Creiamo una lista di comandi: 'lappend' aggiunge un
# elemento ad una lista
lappend clicmd "show ip int brief"
lappend clicmd "show tech"
lappend clicmd "show clock"
# Si eseguono i comandi. 'cliout' contiene il valore
# restituito dalla procedura
set cliout [CLICmdProc $clicmd]
# Il valore di 'cliout' viene memorizzato in un file
set idfile [open "fileuscita" w+]
foreach outs $cliout {
puts $idfile $outs
}
close $idfile
Figura 159 - Esempio di script in TCL
227