viernes, 23 de septiembre de 2011

Instalacion de ntop en Debian 6


Instalación de ntop en Debian 6

   Necesitamos esta aplicación en la red de la oficina para detectar problemas y consumos elevados de tráfico. En la versión 6 de debian parece ser que la instalación del Ntop tiene algún problema y hemos tenido que compilar la aplicación nosotros mismos.

Instalación

   Primero una serie de dependencias que fueron apareciendo a media que se configuraba la aplicación.

apt-get install libtool
apt-get install m4
apt-get install autoconf automake
apt-get install libpcap0.8-dev
apt-get install gdbm
apt-get install libgdbm-dev
apt-get install librrd-dev
apt-get install python-dev
apt-get install libgeoip-dev

   Ahora procedemos a compilar la aplicación.

make

   Y ahora la instalamos...

make install

Post instalación

   Ahora generamos un usuario para que ejecute el ntop. El directorio para el usuario (parámetro -d) es /usr/local/share/ntop, que es donde se instala la aplicación. -M para no crear el directorio home ya que está creado y como shell ponemos /bin/false (parámetro -s) para que no se puedan conectar al sistema con este usuario. Por último, ponemos el nombre del usuario.

useradd -d /usr/local/share/ntop -M -s /bin/false ntop


   Necesitamos un script de arranque para que el Ntop se ejecute con el arranque de la maquina. Cogí el fichero ntop que se generó para la versión 5 de Debian desde aquí. El fichero original lo descargué de esa página con el nombre [ntop_3.3.orig.tar.gz]. De este fichero extraigo el fichero que se instala en /etc/init.d y se llama ntop. Luego lo modifico un poco a mi gusto y añadimos el script /etc/init.d/ntop al arranque de la maquina.

   update-rc ntop defaults

   La salida del comando es la que sigue:

insserv: warning: script 'ntop' missing LSB tags and overrides

   El error que arroja la consola, nos indica que el script no está preparado para el nuevo modelo de arranque de Debian (y otros). Ahora hay que especificar las dependencias del script añadiendo las lineas siguientes al script de arranque. Información sobre esto en debian-wiki.


### BEGIN INIT INFO
# Provides:             Nombre del script de arranque.
# Required-Start:    Servicios que tienen que estar arrancados antes que éste script.
# Required-Stop:    Este script debe de terminar antes de que terminen estos Servicios.
# Should-Start:       Servicios que deberían estar arrancados pero no indispensables.
# Should-Stop:       Servicios que se tienen que parar tras parar este script.
# Default-Start:       Por defecto iniciar en los runlevels...
# Default-Stop:       Por defecto parar en los runlevels...
# Short-Description: Una descripción corta.
# Description: Una descripción larga.
#
### END INIT INFO


   Definitivamente el script queda como se muestra.


#! /bin/sh
# ntop script
#
# NOTE: Copy this script in /etc/init.d/ntop
#
# Author:
# Paul Mansfield <paul.mansfield@uk.worldpay.com>
# Worldpay - 20020218
#
# Fixed by L.Deri - May 2007
#
# Modificado por Salvador Gonzalez para mi instalacion en Debian 6


### BEGIN INIT INFO
# Provides:          ntop
# Required-Start:    $local_fs $network $syslog
# Required-Stop:     $network 
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: ntop daemon
# Description: ntop daemon para monitorizar trafico.
#
### END INIT INFO


set -e


NAME=ntop
DAEMON=/usr/local/bin/ntop
NTOPPID=/var/run/ntop.pid


test -x $DAEMON || exit 0


start_ntop() {
    echo -n "Starting ntop "
    $DAEMON -u ntop > /var/log/ntop.out &
    echo " ...done"
}


stop_ntop() {
    echo -n "Stopping ntop "
    if test -f $NTOPPID ; then
kill `cat $NTOPPID`
echo -n " killed pid `cat $NTOPPID`"
rm $NTOPPID
    fi
    echo " ...done"
}


case "$1" in
  start)
    start_ntop
    ;;

  stop)
    stop_ntop
    ;;

  restart)
    stop_ntop
    start_ntop
    ;;

  *)
    echo "Usage: /etc/init.d/$NAME {start|stop|restart}"
    exit 1
    ;;
esac
exit 0


Configuración de ntop para el primer arranque

   Es necesario generar un usuario y clave para el Ntop. No confundir con el usuario que ejecuta el Ntop en nuestro sistema. Ejecutamos el ntop con el parametro -A para ponerle la clave al admin. Pero aparece el siguiente error:


ntop -A
ntop: error while loading shared libraries: libntopreport-4.1.0.so: cannot open shared object file: No such file or directory

   Busco las librerías del ntop en el sistema y me las encuentro ubicadas en /usr/local/lib. Así que edito el fichero vi /etc/ld.so.conf y añado el texto include /usr/local/lib para indicarle al sistema ejecutado ldconfig que debe añadir las librerías de dicho directorio al sistema. Hay muchas maneras de hacer esto, pero esta es sencilla.

Arranque de ntop

/etc/init.d/ntop start


   Verificamos que el ntop está arrancado buscando el puerto 3000 en modo escucha. Si atacamos este puerto por medio del navegador debemos ver la información de la aplicación.


ps aux | grep ntop
ntop      2882  0.3  2.9 222704 30008 pts/0    Sl   11:26   0:00 /usr/local/bin/ntop -u ntop

   Aquí vemos que hay proceso ntop en memoria y levantado por el usuario ntop.

netstat -an | grep 3000
tcp        0      0 0.0.0.0:3000            0.0.0.0:*               LISTEN

   Y aquí vemos que hay un proceso a la escucha en el puerto 3000. Si pedimos una lista de los servicios de la maquina en escucha vemos lo siguiente. (sólo una parte)

netstat -a

tcp        0      0 *:ssh                   *:*                     LISTEN     
tcp        0      0 *:3000                  *:*                     LISTEN 


   Aquí vemos que el sistema no sabe que escucha en el puerto 3000. Modificamos el fichero /etc/services e incluimos en su sitio (están ordenados por el número del servicio) la línea ntop 3000/tcp # ntop. De este modo el comando netstat -a da la siguiente salida que es más bonita e informativa.


tcp        0      0 *:ssh                   *:*                     LISTEN     
tcp        0      0 *:ntop                  *:*                     LISTEN


Monitorización

   Desde el navegador atacamos al servidor donde instalamos el ntop al puerto 3000. http://servidor:3000 y debemos ver algo como esto:


Retoques finales

   El log del ntop se crea como /var/log/ntop.out. Lo comprobamos para ver si hay algún problema y así solucionarlo. En el log, la linea **ERROR** RRD: Disabled - unable to create base directory (err 13, /usr/local/var/ntop/rrd) nos indica que hay un error. Lo corregimos creando el directorio que necesita. También se observa que podemos mandar la salida del log y tratarla por medio del rsyslogd. NOTE: -L | --use-syslog=facility not specified, child processes will log to the default (24).


  Hacemos que el log del ntop lo gestione el demonio rsyslog. Para conseguirlo he colocado la siguiente entrada en el fichero /etc/rsyslog.conf.


# Modificaciones para ntop
local5.* /var/log/ntop.log
:msg, contains, "ntop" /var/log/ntop.log


   y le indiqué al script de arranque /etc/init.d/ntop que se ponga en modo demonio y la salida al syslog con la facility local5.


start_ntop() {
    echo -n "Starting ntop "
    $DAEMON -d -u ntop --use-syslog=local5 -L
    echo " ...done"
}


   Parece que sin la configuracion :msg, contains, "ntop" no funciona la salida al log de la aplicación.

Rotación de los logs

   Para rotar el fichero /var/log/ntop.log creamos un fichero ntop en el directorio /etc/logrotate.d con el contenido que se muestra a continuación.


/var/log/ntop.log {
        daily
        missingok
        rotate 3
        delaycompress
        notifempty
        create 640 root adm
        sharedscripts
        postrotate
                /etc/init.d/ntop restart > /dev/null
        endscript
}


miércoles, 21 de septiembre de 2011

Script para hacer backup de maquinas virtuales vmware

   Bueno, aunque últimamente me siento mucho más cómodo haciendo scripts y trabajando con Linux, hay veces que tienes que hacer cosas en Windows. Ahora le ha tocado el turno a la Powershell de Windows. Digan lo que digan, es una consola de comandos al estilo Linux, siempre se copia lo bueno.

   He creado este script, copiando un poco de aquí y poco de allí, para hacer copias de maquinas virtuales de VMWare que estan arrancadas. La idea es generar un Snapshot de la máquina, luego se copia a un datastore destino y luego se elimina el snapshot. Además de esa funcionalidad, queríamos una programación rudimentaria de los backups (fecha de lanzamiento y número de copias).

   El script se lanza todos los días. Se comprueba un fichero csv y si el fichero indica que se debe hacer backup de una maquina se lanza. Por último, la máquina se mueve a una carpeta y se dejan sólo un número finito de copias, también indicadas por el fichero csv.

   El fichero csv tiene el siguiente formato:

VMMaquina,DestinoBackup,n_copias,planificaciones
XXXXY,vmbackup,2,1;20
YYYYX,vmbackup,1,2

   El primer parámetro se corresponde con el nombre de la maquina a clonar. El segundo es el datastore destino de la copia. El tercero es el número de copias a conservar. El último parámetro separa por ";" las fechas en que lanzar el backup.

   El Script:

# Nos aseguramos de que la PowerShell sepa que tiene que cargar
add-pssnapin VMware.VimAutomation.Core

##########  Funciones
# VMMaquina --> Maquina virtual a clonar
# DestinoBackup --> Datastore destino para la maquina clonada

function clonarMaquinaVirtual($VMMaquina, $DestinoBackup) {

    if ( (($VMMaquina -ne $null) -and ($DestinoBackup -ne $null)) ) {
        Echo "Copiar ($VMMaquina) en ($DestinoBackup)"

        # Formato de la fecha
        $date = Get-Date -Format "yyyyMMdd"

        #Connect to vCenter - Instalado en XXXXX
        Connect-VIServer "XXXXXXXX"

        $vm = get-VM $VMMaquina
       
        if ($vm -eq $null) {
            Echo "No se encontro la maquina $VMMaquina en el VC."
        } else {
            #Generamos el Snapshot
            $cloneSnap = $vm | New-Snapshot -Name "Snapshot de Backup"

            # Obtenemos la maquina a  clonar
            $vmView = $vm | Get-View
           
            # Desde donde clonamos
            $cloneFolder = $vmView.parent
           
            # Parametros de la maquina clonada
            $cloneSpec = new-object Vmware.Vim.VirtualMachineCloneSpec
            $cloneSpec.Snapshot = $vmView.Snapshot.CurrentSnapshot

            # Donde la clonamos
            $cloneSpec.Location = new-object Vmware.Vim.VirtualMachineRelocateSpec
            $cloneSpec.Location.Datastore = (Get-Datastore -Name $DestinoBackup | Get-View).MoRef
            $cloneSpec.Location.Transform =  [Vmware.Vim.VirtualMachineRelocateTransformation]::sparse

            #Nombre de la copia
            $cloneName = "$vm-$date"
           
            ############# Clonamos la Maquina ###############
            $vmView.CloneVM( $cloneFolder, $cloneName, $cloneSpec )
           
            # Nombre la maquina clonada
           Get-VM $cloneName

            # Quitamos el Snapshot
            Get-Snapshot -VM (Get-VM -Name $VMMaquina) -Name $cloneSnap | Remove-Snapshot -confirm:$False

            # Quitar del inventario la maquina clonada
            Remove-VM -VM $cloneName -confirm:$False
        }
       
        # Desconectamos
        Disconnect-VIServer -Confirm:$false
    }

}

# Reorganizamos en carpetas los backups
#

# vm --> Nombre de la maquina virtual
# copies --> Numero de copias a mantener de la maquina clonada

function reorganizarDS($vm, $copies) {
    # Conectamos la Unidad Z: a \\xxxxxxxxxxx\vmbackup (samba)
    $net = new-object -ComObject WScript.Network
    $net.MapNetworkDrive("z:", "\\xxxxxxxxxx\vmbackup", $false, "USER", "PASS")
   
    $rutaMaquina = "z:\" + $vm
    $origenRutaMaquina = "z:\" + $vm + "-*"
   
    # Reorganizamos la maquina
    if (-not (Test-Path $rutaMaquina)) {
        Echo "Creamos una carpeta para la maquina en ($rutaMaquina)."
        New-Item $rutaMaquina -type directory
    }
    # Movemos las maquinas al directorio
    Echo "Movemos desde ($origenRutaMaquina) a ($rutaMaquina)."
   
    Move-Item $origenRutaMaquina $rutaMaquina

    Echo "Realizamos limpieza de ($vm) y dejamos ($copies) copias"

    # Cuantas maquinas hay almacenadas
    $numCopias = $(Get-Item "$rutaMaquina\*").count
    Echo "Hay ($numCopias) copias de la maquina"
   
    if ($numCopias -gt $copies) {
        Echo "Borrando maquinas"
        do {
            dir $rutaMaquina | sort lastwritetime | select -first 1 | remove-item -recurse -force
            $numCopias = $(Get-Item "$rutaMaquina\*").count
            Echo "Ahora quedan ($numCopias) maquinas."
        } until ($numCopias -eq $copies)
    }

    Echo "Limpieza terminada"
   
    # Desconectamos la unidad Z:
    $net.RemoveNetworkDrive("z:")
}   

########## Fin funciones


# Import Backup CSV
$backupinfo =  Import-Csv C:\scripts\MaquinasBackups.csv

# Recorremos la lista de maquinas
foreach ($datosBackup in $backupinfo) {
    if ($($datosBackup.VMMaquina) -eq "") {
        Echo "Hay una maquina en blanco..."
    } else {
        # Buscamos que dia del mes es hoy
        $todayIs = Get-Date -Format "dd"
        # Cambiamos los dias 0X por X
        $todayIs = [int] $todayIs
       
        Echo "Hoy es ($todayIs)."
       
        Echo "Comprobando maquina ($($datosBackup.VMMaquina)) que debe quedar con ($($datosBackup.n_copias)) copias."
        Echo "Se debe lanzar los dias..."
        # Parseamos el ultimo parametro. Los dias se separan por ;
        $backupDates = ($($datosBackup.planificaciones)).split(";")
        foreach ($backupDate in $backupDates) {
            Echo "El dia ($backupDate) se tiene que hacer backup."
            if ($todayIs -eq $backupDate) {
                $backupVM = $($datosBackup.VMMaquina)
                $backupDest = $($datosBackup.DestinoBackup)
                Echo "Lanzamos el backup de ($backupVM) en ($backupDest)"
               
                # Llamamos al script c:\scripts\BackupVms.ps1
                Echo "Lanzando la copia"
                clonarMaquinaVirtual $backupVM $backupDest
                Echo "Copia terminada"
               
                # Como hemos hecho backup es necesario limpiar lo viejo
                reorganizarDS $backupVM $($datosBackup.n_copias)
            }
           
        }
    }
}


miércoles, 24 de agosto de 2011

Añadir un disco duro en caliente a un Linux

   Muchas veces es necesario añadir un disco duro nuevo a un servidor. Si podemos hacerlo sin pararlo pues mejor. Así no hay que avisar a nadie y somos autónomos. En mi antiguo trabajo lo tenía documentado, pero perdí esa información al cambiar a otra empresa. Ahora iré documentando por aquí esas cosillas que nos ayudan día a día.
  1. Desde una consola ejecutamos el comando echo "- - -" > /sys/class/scsi_host/host#/sca. Hay que cambiar # por el numero de host adecuado.
  2. Ahora podemos actuar sobre el disco como queramos teniéndolo disponible como una unidad nueva. Será necesario crear las particiones y formatearlo.

martes, 9 de agosto de 2011

Nuevo curro... nueva vida...

    Bueno, pues ya está hecho, después de 13 años ya era hora... nuevo trabajo, nuevos compañeros, nuevos objetivos, nuevo horario, nuevos problemas...

    Vamos a ver que nuevos proyectos van surgiendo y como los afrontamos, siempre hay cosas que aprender y cosas que enseñar.

jueves, 10 de marzo de 2011

Tunel SSH inverso - Reverse SSH tunnel

Donde trabajo tenemos un servidor linux expuesto a Internet. Se trata de un debian lenny. En el servidor hay un Apache y un Ftp seguro.Mi empresa contrató en su momento un Hosting que dispone de un Firewall para proteger el servidor. Durante una revisión que se realizó en la empresa de Hosting, se hizo un análisis de los servidores buscando vulneravilidades y se encontraron problemas en el servidor.

Para proteger el servidor tenía que realizar una serie de acciones, entre ellas actualizar la distribución con los últimos parches de seguridad y actualizar el servidor Apache pasando de la versión 2.2.9 a la 2.2.14 como mínimo. Los pasos que tenía en mente eran bastante sencillos.
  1. Conectarme al servidor.
  2. Lanzar un apt-get update
  3. Lanzar un apt-get dist-upgrade
  4. Cambiar unos parámetros en la configuración del servidor Apache.
   Estimación = 10 minutos de trabajo.

Paso 1

Me conecto por ssh. 10 segundos. Todo va bien.

Paso 2

Desde la terminal lanzo el comando apt-get update. Pensé, un par de minutos bajando los datos de los paquetes y luego actualizo. Me quedo mirando la pantalla y lo único que veo es que el servidor es incapaz de resolver las direcciones de los servidores de paquetes debian. Investigando me doy cuenta de que el Firewall del Hosting tiene capado el tráfico hacia Internet, lo que hace inviable cualquier tipo de actualizacion. ¿Cuál es el proceso ahora?. Pues hay que pedir a la empresa de Hosting que abra dicho tráfico. Estimación = 2 días para que solventen el problema.

Quedo mal con mi empresa

O eso piensas rápidamente. ¿Que más puedo hacer?. Me vienen a la mente los túneles SSH. Si puedo abrir una conexión SSH también puedo generar un tunel y hacer más cosas. Lo que necesito es un tunel inverso. La idea es abrir un puerto local en el servidor remoto que se conecte a un puerto de mi puesto de trabajo donde tenga un proxy que redirija el tráfico a Internet.
En mi PC dipongo de una aplicación que abre un puerto local y redirige el tráfico al ISA Server de mi empresa. El puerto en mi PC donde está escuchando el Proxy es el 5865. Ahora se trata de abrir un tunel SSH inverso con el comando ssh -R 20000:localhost:5865 root@servidorenelhosting ¿Qué hace esto? Pues en primer lugar se conecta al servidor que está en el Hosting, abre el puerto 20000 y lo enlaza a mi PC (localhost) con el puerto 5865. El resultado es que si yo le digo al servidor que lance tráfico por el puerto 20000 en realidad ese tráfico es lanzado por el tunel contra mi PC y este lo lanza hacia Internet a través del ISA Server de mi empresa.

Pasos 2 y 3

Necesitamos que la herramienta apt-get salga por un proxy y eso lo conseguimos ejecutando el comando export http_proxy=http://localhost:20000 en el servidor. Ahora lanzamos el apt-get update y luego el apt-get dist-upgrade. Todo va como la seda. Estimación correcta = 30 minutos. (No quedas tan mal)

Lo de instalar el servidor Apache version 2.2.14 o superior es otra história.

lunes, 7 de febrero de 2011

Automatizar alta de usuarios en linux

  Hoy he tenido que automatizar la creación de usuarios en linux. Al final lo hago con lo siguiente:

  1. Obtengo la clave para el usuario perl -e 'print crypt("la_clave", "salt"),"\n"'
  2. Esto nos devuelve una cadena tal que "sa2ZenP9x1FSA"
  3. Ejecutamos el comando useradd -p sa2ZenP9x1FSA nombre_del_usuario.