Cisco Centinel – Utilidad en C# y Perl para monitorizar un dispositivo Cisco
Posted in cisco, Google, HelpDesk, Networking, Scripting, seguridad, Sistemas, soporte, Utilidades on Sep 28th, 2012
Referencia:
http://www.javcasta.com/2012/09/24/networking-cisco-perl-scripting-con-modulo-net-telnet-cisco/
Descargar:
Requisitos:
- En maquina cliente:
- - Framework .Net 3.5 o 4 instalado
- - Perl (ActivePerl) instalado
- - Modulo de Perl Telnet-Cisco (ver referencia)
- Y si deseas que se puedan enviar alertas por mail: Modulo de Perl Email-Send-Gmail (ppm install Email-Send-Gmail)
- En dispositivo Cisco a monitorizar:
- - ICMP habilitado tal que conteste (a un ping) con un icmp echo-reply ante un icmp echo-request.
- - Acceso vía telnet si se desea usar las opciones de:
- – % CPU del dispositivo
- – ICMP: ping desde el dispositivo a un host
Esta utilidad la he implementado bajo C# 4.0 y desarrollado en sharpDevelop 4.2, compilada para .Net 3.5 client profile.
C# lo he usado para la GUI o el interfaz gráfico de usuario y la opción de enviar un ping al dispositivo a monitorizar.
Para obtener, vía telnet, el % de utilización de la CPU y efectuar un ping desde el dispositivo a otro host, he usado scripts en Perl con el módulo Telnet-Cisco y el módulo Email-Send-Gmail.
La mecánica de la utilidad es la siguiente.
En el grupo parámetros:
Hostname o IP: Se debe de poner el nombre o ip del dispositivo Cisco a monitorizar.
Intervalo: El tiempo x en segundos del delay o retardo del bucle de monitorización.
En el grupo Monitorizar:
Elegimos mediante los checkBox los métodos de monitorización:
1- Ping desde nuestro host al dispositivo a monitorizar (pudiendo variarse el timeout del ping en un textBox)
2- Mostrar el % de uso de la CPU del dispositivo a monitorizar
3- Ping desde el dispositivo a monitorizar a un host
(la utilidad presenta en el comboBox nuestras IPs como destino del ping desde el dispositivo, pudiendose elegir una de estas o editar la que deseemos)
Los campos usuario y clave, obviamente son para acceder vía telnet al dispositivo a monitorizar
(sin tener acceso vía telnet los métodos 2 y 3 no surtirán efecto).
Tras tener parametrizada la utilidad, se comenzaria el bucle de monitorización cada x sg clikando en
el botón comenzar monitorización. Para parar, se clikaria el boton stop.
En el richTextBox veremos el estado del dispositivo y el ciclo (cuantas veces cada x sg se han efectuado los métodos de monitorización)
Tambien veremos una imagen con 3 estados:
- ? = indeterminado (no se ha empezado a monitorizar o se ha clikado el boton stop)
- OK = El dispositivo responde correctamente a los métodos de monitorización
- !!! = El dispositivo no responde correctamente a los métodos de monitorización.
Si se da este último caso y el ciclo es >= a 2 y esta marcado el checkBox de enviar alerta vía e-mail:
Se enviará un correo electrónico desde una cuenta de gmail (hay que parametrizar la cuenta y la clave)
a la dirección de correo definida en el textBox, conteniendo los datos de la alerta.
Para ello es condicion necesaria tener instalado el módulo de perl Email-Send-Gmail (http://search.cpan.org/dist/Email-Send-Gmail-0.33/)
El código de los scripts en perl
cisco-telnet.pl
local $| = 1;
use Net::Telnet::Cisco;
# JavCasta - http://javcasta.com/ - 2.012
my $device = $ARGV[0];
my $usuario = $ARGV[1];
my $clave = $ARGV[2];
my $pinghost = $ARGV[3];
my $cpu = $ARGV[4];
eval {
my $session = Net::Telnet::Cisco->new(Host => $device);
$session->login($usuario, $clave);
# Execute a command
my $comando = 'ping '.$pinghost;
my @output = $session->cmd($comando);
print @output;
my $compara = 'CPU';
if ( $cpu eq $compara ) {
my @output2 = $session->cmd('show processes cpu | include CPU');
print @output2;
print 'fin'; #añado fin para tratamiento de cadenas desde c#
}
$session->close;
};
if ( $@ ) {
my @output = "Error: $@";
print @output;
}
send-mail.pl
local $| = 1;
use strict;
use warnings;
use Email::Send;
use Email::Send::Gmail;
use Email::Simple::Creator;
my $miFrom = $ARGV[0];
my $miTo = $ARGV[1];
my $miSubject = $ARGV[2];
my $miBody = $ARGV[3];
my $miClave = $ARGV[4];
my $email = Email::Simple->create(
header => [
From => $miFrom,
To => $miTo,
Subject => $miSubject,
],
body => $miBody,
);
my $sender = Email::Send->new(
{ mailer => 'Gmail',
mailer_args => [
username => $miFrom,
password => $miClave,
]
}
);
eval { $sender->send($email) };
#die "Error enviando email: $@" if $@;
if ( $@ ) {
my @output = "Error_envio_alerta: $@";
print @output;
}
El código del mainform.cs de la aplicación en C#:
/*
* Created by SharpDevelop.
* User: JavCasta - http://javcasta.com/
* Date: 24/09/2012
* Time: 10:26
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Management;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Mail;
namespace CiscoCentinel
{
/// <summary>
/// Description of MainForm.
/// </summary>
public partial class MainForm : Form
{
ManagementClass objMC;
ManagementObjectCollection objMOC;
string[] ipaddresses;
int i = 0;
bool continuar = true;
int ciclo = 0;
string comando = "";
bool enviar = false;
string cuerpo1, cuerpo2, cuerpo3 ="";
public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//
// TODO: Add constructor code after the InitializeComponent() call.
//
misips();
}
//ref: run a perl script from c#
//http://social.msdn.microsoft.com/Forums/zh/csharpgeneral/thread/ea9455e1-b254-49e1-99df-41718ea80b5b
void Button1Click(object sender, EventArgs e)
{
//Comenzamos a monitorizar
richTextBox1.Text = "";
progressBar1.Style = ProgressBarStyle.Marquee;
//Bucle cada intervalo
while (continuar) {
progressBar1.Style = ProgressBarStyle.Marquee;
ciclo++;
enviar = false;
groupBox3.Text="Estado - ciclo: " + ciclo.ToString();
//si icmp ping al -> ping al router
if (checkBox1.Checked) {
if (miPing(textBox1.Text)) {
//MessageBox.Show("OK");
richTextBox1.Text += (DateTime.Now).ToString()+": Ping al dispositivo " + textBox1.Text + " OK!!!" + "\r\n";
richTextBox1.SelectionStart = richTextBox1.Text.Length;
pictureBox1.Visible = false;
pictureBox2.Visible = true;
pictureBox3.Visible = false;
}
else
{
richTextBox1.Text += (DateTime.Now).ToString()+": Ping al dispositivo " + textBox1.Text + " NO OK!!!" + "\r\n";
richTextBox1.SelectionStart = richTextBox1.Text.Length;
pictureBox1.Visible = false;
pictureBox2.Visible = false;
pictureBox3.Visible = true;
//if (ciclo >= 2) enviamail() con alerta dispositivo no responde a ping
if ( ciclo > 1 ) {
cuerpo1 = (DateTime.Now).ToString()+": Ping al dispositivo "+textBox1.Text+" NO OK!!!\r\n";
enviar = true;
}
} //else
}
//si icmp ping desde el dispositivo al host
if (checkBox3.Checked) {
comando = "cisco-telnet.pl" + " " + '"' +textBox1.Text +'"' + " " +'"'+ textBox2.Text+'"' + " " + '"'+textBox3.Text+'"' + " " + '"'+ comboBox1.Text+'"';
if (checkBox2.Checked) comando += " " + '"'+"CPU"+'"';
if (!checkBox2.Checked) comando += " " + '"'+"foo"+'"';
Cursor.Current = Cursors.WaitCursor;
elproceso();
}
//enviar
string cuerpo = '"'+ cuerpo1 + cuerpo2 + cuerpo3 +'"';
enviaAlerta("send-mail.pl"+" "+'"'+textBox8.Text+'"'+" "+'"'+textBox4.Text+'"'+" "+'"'+"Alerta"+'"'+" "+cuerpo+" "+'"'+textBox7.Text+'"');
enviar = false;
//delay
Sleep(int.Parse(textBox5.Text));
} //while
continuar = true;
}
static void Sleep(int sg)
{
//http://forums.devshed.com/showpost.php?p=1621059&postcount=6
DateTime dt1 = DateTime.Now;
int diff = 0;
while (diff < sg)
{
DateTime dt2 = DateTime.Now;
TimeSpan ts = dt2.Subtract(dt1);
diff = (int)ts.TotalSeconds;
Application.DoEvents();
}
}
public void elproceso()
{
try {
ProcessStartInfo perlStartInfo = new ProcessStartInfo(@"perl.exe");
//MessageBox.Show(comando);
perlStartInfo.Arguments = comando;
perlStartInfo.UseShellExecute = false;
perlStartInfo.WindowStyle = ProcessWindowStyle.Minimized;
perlStartInfo.RedirectStandardOutput = true;
perlStartInfo.RedirectStandardError = true;
perlStartInfo.CreateNoWindow = false;
Process perl = new Process();
perl.StartInfo = perlStartInfo;
perl.Start();
string output = perl.StandardOutput.ReadToEnd();
perl.WaitForExit(5000);
if (output.Contains("CPU"))
{
int first = output.IndexOf("CPU");
int last = output.LastIndexOf("fin");
string str2 = output.Substring(first, last - first);
richTextBox1.Text += str2 + "\r\n";
}
//si Success rate is 80 o 100 percent ok, si no no ok
if (output.Contains("Success rate is 80") || output.Contains("Success rate is 100"))
{
richTextBox1.Text += (DateTime.Now).ToString()+": Ping desde el dispositivo " + textBox1.Text + " al host " + comboBox1.Text + " OK!!!" + "\r\n";
pictureBox1.Visible = false;
pictureBox2.Visible = true;
pictureBox3.Visible = false;
enviar = false;
}
else
{
if (output.Contains("Success rate"))
{
richTextBox1.Text += (DateTime.Now).ToString()+": Ping desde el dispositivo " + textBox1.Text + " al host " + comboBox1.Text + " NO OK!!!" + "\r\n";
richTextBox1.SelectionStart = richTextBox1.Text.Length;
pictureBox1.Visible = false;
pictureBox2.Visible = false;
pictureBox3.Visible = true;
if (ciclo > 1)
{
cuerpo2 = (DateTime.Now).ToString()+": Ping desde el dispositivo "+textBox1.Text+" al host "+comboBox1.Text+" (respuesta <= del 60%) NO OK!!!\r\n";
enviar = true;
}
}
else
{
if (output.Contains("Error:"))
{
richTextBox1.Text += (DateTime.Now).ToString()+ ": No hay conexion al dispositivo " + textBox1.Text + " via telnet!!!" + "\r\n";
if (ciclo > 1)
{
cuerpo3 = (DateTime.Now).ToString()+": No hay conexion al dispositivo "+ textBox1.Text+" via telnet \r\n";
enviar = true;
}
}
}
}
} //try
catch (Exception ex) {
richTextBox1.Text += ex.ToString() + "\r\n";
}
Cursor.Current = Cursors.Default;
}
public void misips()
{
objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
objMOC = objMC.GetInstances();
i=0;
foreach(ManagementObject objMO in objMOC)
{
if(!(bool)objMO["ipEnabled"])
continue;
i=i+1; // i = nº de NICs
ipaddresses = (string[]) objMO["IPAddress"];
if (ipaddresses != null) {
foreach(string sIP in ipaddresses) {
comboBox1.Text=sIP;
comboBox1.Items.Add(sIP);
}
}
}
}
public bool miPing(string mihost)
{
Ping p = new Ping();
int myTimeOut = int.Parse(textBox6.Text);
bool result = false;
try
{
PingReply reply = p.Send(mihost, myTimeOut);
if (reply.Status == IPStatus.Success)
return true;
}
catch { }
return result;
}
void Button2Click(object sender, EventArgs e)
{
//stop
progressBar1.Style = ProgressBarStyle.Blocks;
continuar = false;
Process[] prs = Process.GetProcesses();
foreach (Process pr in prs)
{
if (pr.ProcessName == "perl")
{
pr.Kill();
}
}
pictureBox1.Visible = true;
pictureBox2.Visible = false;
pictureBox3.Visible = false;
}
void Button3Click(object sender, EventArgs e)
{
Process.Start("http://javcasta.com");
}
// send alerta por email
public void enviaAlerta(string comando)
{
if (enviar) try {
ProcessStartInfo perlStartInfo = new ProcessStartInfo(@"perl.exe");
perlStartInfo.Arguments = comando;
perlStartInfo.UseShellExecute = false;
perlStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
perlStartInfo.RedirectStandardOutput = true;
perlStartInfo.RedirectStandardError = true;
perlStartInfo.CreateNoWindow = false;
Process perl = new Process();
perl.StartInfo = perlStartInfo;
perl.Start();
string output = perl.StandardOutput.ReadToEnd();
perl.WaitForExit(10000);
if (output.Contains("Error_envio_alerta")) richTextBox1.Text += output +"\r\n";
else richTextBox1.Text += "Enviada alerta por email";
} catch {}
}
}
}
Y voila






















[...] Idea Origen de la utilidad: Cisco Centinel – Utilidad en C# y Perl para monitorizar un disposi… [...]