Aug 30, 2010

SNMP basic commands

In this article we are going to see the main SNMP commands that are provided by the net-snmp and net-snmp-utils packages.

The MIBs used by these tools normally reside in the /usr/share/snmp/mibs/ directory. Therefore, if we have ever to install new MIBs (e.g. for a VMware ESXi) we will have to leave them into that directory.

[root@centos ~]# ls -l /usr/share/snmp/mibs/
total 2364
...
-r--r--r-- 1 root root   8259 feb 16 12:09 SNMPv2-CONF.mib
-rw-r--r-- 1 root root   8263 feb 16 11:19 SNMPv2-CONF.txt
-r--r--r-- 1 root root  31588 feb 16 12:09 SNMPv2-MIB.mib
-rw-r--r-- 1 root root  29305 feb 16 11:19 SNMPv2-MIB.txt


snmpget

The snmpget command provides information about a specific OID.

For instance, to request the name of the device (system.sysName OID, belonging to the SNMPv2-MIB module) we will run the following order:

[root@centos ~]# snmpget -v 2c -c centos-community 192.168.1.10 SNMPv2-MIB::system.sysName.0
SNMPv2-MIB::sysName.0 = STRING: centos

We can also use abbreviations as follows:

[root@centos ~]# snmpget -v 2c -c centos-community 192.168.1.10 system.sysName.0
SNMPv2-MIB::sysName.0 = STRING: centos

[root@centos ~]# snmpget -v 2c -c centos-community 192.168.1.10 sysName.0
SNMPv2-MIB::sysName.0 = STRING: centos

Also say that multiple queries and use the OID in numeric format can be done.

[root@centos ~]# snmpget -v 2c -c centos-community 192.168.1.10 sysName.0 sysUpTime.0
SNMPv2-MIB::sysName.0 = STRING: centos
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (69808) 0:11:38

[root@centos ~]# snmpget -v 2c -c centos-community 192.168.1.10 .1.3.6.1.2.1.1.5.0
SNMPv2-MIB::sysName.0 = STRING: centos


snmptranslate

The snmptranslate command allows to make translations of OIDs from numeric format to variable and vice versa.

[root@centos ~]# snmptranslate .1.3.6.1.2.1.2.2.1.4.2
IF-MIB::ifMtu.2

[root@centos ~]# snmptranslate -On IF-MIB::ifMtu.2
.1.3.6.1.2.1.2.2.1.4.2

In order to get the complete OID, we must use the -Of parameter.

[root@centos ~]# snmptranslate -Of IF-MIB::ifMtu.2
.iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry

For example it can happend that we don't remember the complete OID name. In this case, the -Ib parameter will provide us the best match.

[root@centos ~]# snmptranslate -Ib 'i*tu'
IF-MIB::ifMtu

But if we want to get all the matches that fit with the selected pattern, we will use the -TB option.

[root@centos ~]# snmptranslate -TB 'sys.*ime'
SNMPv2-MIB::sysORUpTime
SNMPv2-MIB::sysUpTime
DISMAN-EVENT-MIB::sysUpTimeInstance
IP-MIB::ipSystemStatsDiscontinuityTime

Finally, also say that the snmptranslate command is very useful to show the entire OIDs tree or all branches that hang of a particular OID.

[root@centos ~]# snmptranslate -Tp -IR | more
+--iso(1)                    
|
+--org(3)
|
+--dod(6)
|
+--internet(1)
...

[root@centos ~]# snmptranslate -Tp -IR system
+--system(1)
|
+-- -R-- String    sysDescr(1)
|        Textual Convention: DisplayString
|        Size: 0..255
+-- -R-- ObjID     sysObjectID(2)
+-- -R-- TimeTicks sysUpTime(3)
|  |
|  +--sysUpTimeInstance(0)
...


snmpwalk

The snmpwalk command is utilized to perform a series of followed GETNEXTS instructions, and thus to obtain for example all the values of a specific branch.

[root@centos ~]# snmpwalk -v 2c -c centos-community 192.168.1.10 system
SNMPv2-MIB::sysDescr.0 = STRING: Linux server 2.6.18-164.11.1.el5 #1 SMP Wed Jan 20 07:32:21 EST 2010 x86_64
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (342908) 0:57:09.08
SNMPv2-MIB::sysContact.0 = STRING: Root  (configure /etc/snmp/snmp.local.conf)
SNMPv2-MIB::sysName.0 = STRING: centos
...


Aug 23, 2010

VMware vSphere (ESXi): There is no more space for virtual disk

El título de este artículo refleja un error que nos puede ocurrir al administrar un VMware vSphere si no tenemos en cuenta ciertos detalles relacionados con la estructura de ficheros que emplea una máquina virtual.

Concretamente el mensaje de error al que me refiero es el siguiente: msg.hbacommon.outofspace: There is no more space for virtual disk xxxxxx. You may be able to continue this session by freeing disk space on the relevant partition, and clicking Retry. Otherwise, click Abort to terminate this session.


El problema es muy sencillo: alguna de nuestras máquinas virtuales ha ido creciendo de tamaño de tal manera que se ha agotado el espacio de nuestro datastore.

Vamos a poner un ejemplo para entender el asunto: supongamos que tenemos un datastore con un tamaño de 32 GB, y dentro de él creamos una máquina virtual a la que le asignamos 2 GB de memoria RAM y un disco virtual de 16 GB (vmdk).

Ya de primeras podremos pensar que nos quedan libres 16 GB, y estaremos en lo cierto. Pero en el momento en el que arranquemos dicha máquina virtual, se creará un nuevo archivo temporal con extensión vswp (fichero de swap creado por vSphere que coincidirá en tamaño con la cantidad de memoria RAM asignada) dentro del directorio donde resida la máquina virtual. El tamaño de dicho archivo será de 2 GB, luego ya no nos quedarán 16 GB libres, sino 14 GB.

Y el tema no se acaba aquí. Si en algún momento creamos un snapshot, el fichero vmdk que alberga la máquina virtual pasará a ser de sólo lectura (se congela), y se creará un nuevo archivo vmdk donde se irán guardando los cambios (incrementales) que afecten al vmdk congelado. Por lo tanto al hacer el snapshot, nos encontramos ante un nuevo archivo que podrá ir creciendo de forma dinámica en el tiempo.


Luego si en un momento dado el snapshot de esa máquina virtual (o de otras) aumenta de tal manera que nos quedemos sin espacio libre en el datastore, la máquina virtual que crezca dinámicamente sufrirá un crash y tendremos un mensaje como el de la imagen.

Por todo esto siempre he pensado que el snapshot debe de ser una herramienta que se utilice de forma temporal, por ejemplo cuando vayamos a actualizar un sistema operativo o aplicación. Transcurrido un tiempo prudencial, deberemos eliminarlo.

El rendimiento de una máquina virtual no puede ser el mismo si se trabaja con un disco virtual estático que si se hace sobre otro que varía su tamaño de forma dinámica.

Aug 16, 2010

Instalación y configuración de SNMP

En el presente artículo vamos a ver cómo configurar el servicio SNMP en una distribución CentOS 5.5 de 64 bits.

Lo primero que haremos será instalar los paquetes necesarios en el sistema:
[root@centos ~]# yum install net-snmp net-snmp-utils

A continuación definiremos las ACL (Access Control Lists) o listas de control de acceso dentro del fichero de configuración del demonio (snmpd.conf), a través de las cuáles indicaremos quién podrá conectarse al servicio SNMP y con qué permisos.

Básicamente vamos a crear dos ACLs, local y mynetwork, ambas pertenecientes a la comunidad centos-community. La primera de ellas tendrá permisos de lectura y escritura sobre las ramas de OIDs, y la segunda de ellas, únicamente permisos de lectura.

[root@centos ~]# cat /etc/snmp/snmpd.conf
...
com2sec local 127.0.0.1/32 centos-community
com2sec mynetwork 192.168.1.0/8 centos-community

A continuación crearemos dos grupos, uno de sólo lectura (MyROGroup) y otro de lectura/escritura (MyRWGroup) que podrán utilizar cualquier versión del protocolo SNMP (any).

[root@centos ~]# cat /etc/snmp/snmpd.conf
...
group MyROGroup any mynetwork
group MyRWGroup any local

access MyROGroup "" any noauth exact all none none
access MyRWGroup "" any noauth exact all all all

Y por último, definiremos las ramas que permitiremos visualizar.

[root@centos ~]# cat /etc/snmp/snmpd.conf
...
view all included .1

Ahora sólo tendremos que reiniciar el servicio y hacer que éste se inicie automáticamente cada vez que arranque el sistema.

[root@centos ~]# service snmpd restart

[root@centos ~]# chkconfig snmpd on

Para comprobar que todo funciona correctamente, podremos hacer la prueba de listar la estructura de system.

[root@centos ~]# snmpwalk -v 2c localhost -c centos-community system


Aug 9, 2010

Datastore USB en VMware vSphere (ESXi)

En el artículo anterior vimos cómo conectar un dispositivo USB a un VMware vSphere (ESXi). Si analizamos el texto, podremos extraer dos importantes limitaciones: por un lado que el sistema de ficheros es FAT16 (tamaño máximo del volumen y de los ficheros de 2 GB) y por otro, que no podemos utilizarlo como un datastore.

Pues bien, me propuse intentar convertir la unidad USB en un hipotético datastore. Para ello sabía que previamente tendría que formatear dicho espacio de almacenamiento como VMFS, y posteriormente crear un datastore dentro del volumen, el cual pudiera ser reconocido por el VMkernel y utilizado para almacenar las máquinas virtuales.

Para ello se puede emplear la herramienta que proporciona VMware a través de su service console: vmkfstools (permite crear y manipular discos virtuales, sistemas de archivos, volúmenes lógicos y dispositivos de almacenamiento físico).

~ # vmkfstools -C vmfs3 -b 2M -S datastoreusb /vmfs/devices/disks/mpx.vmhba33\:C0\:T0\:L0\:1
Creating vmfs3 file system on "mpx.vmhba33:C0:T0:L0:1" with blockSize 1048576 and volume label "none".
/vmfs/devices/disks/mpx.vmhba33:C0:T0:L0:1: Permission denied. (Have you set the partition type to 0xfb?)
Error: Permission denied

Al ejecutar el comando anterior nos encontramos con el primer problema: el tipo de partición no es válida. Esto lo podemos arreglar fácilmente a través de fdisk.

~ # fdisk /vmfs/devices/disks/mpx.vmhba33\:C0\:T0\:L0

Command (m for help): p

Disk /vmfs/devices/disks/mpx.vmhba33:C0:T0:L0: 2004 MB, 2004877312 bytes
255 heads, 63 sectors/track, 243 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot Start End Blocks Id System
/vmfs/devices/disks/mpx.vmhba33:C0:T0:L0p1 * 1 243 1951866 6 FAT16

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): fb
Changed system type of partition 1 to fb (VMFS)

Command (m for help): p

Disk /vmfs/devices/disks/mpx.vmhba33:C0:T0:L0: 2004 MB, 2004877312 bytes
255 heads, 63 sectors/track, 243 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot Start End Blocks Id System
/vmfs/devices/disks/mpx.vmhba33:C0:T0:L0p1 * 1 243 1951866 fb VMFS

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table

Al volver a ejecutar el comando de creación del datastore, obtenemos un nuevo error: el VMkernel no está cargado o el tipo de llamada no está implementada.

~ # vmkfstools -C vmfs3 -b 2M -S datastoreusb /vmfs/devices/disks/mpx.vmhba33\:C0\:T0\:L0\:1
Creating vmfs3 file system on "mpx.vmhba33:C0:T0:L0:1" with blockSize 8388608 and volume label "datastoreusb".
Usage: vmkfstools -C vmfs3 /vmfs/devices/disks/vml... or,
vmkfstools -C vmfs3 /vmfs/devices/disks/naa... or,
vmkfstools -C vmfs3 /vmfs/devices/disks/mpx.vmhbaA:T:L:P
Error: vmkfstools failed: vmkernel is not loaded or call not implemented.

La primera posibilidad la descartamos:

~ # vmkload_mod -l | grep vmkernel
vmkernel 0x418037800000 0x29bfc5 0x0 0x0 0 Yes

Si observamos el fichero /var/log/messages podremos ver que lo que realmente está ocurriendo es que no se puede formatear la memoria USB como VMFS; la operación no está soportada por el VMkernel (qué listos estos ingenieros de VMware...).

~ # tail -f /var/log/messages
...
vmkernel: 0:00:32:01.819 cpu1:4097)NMP: nmp_CompleteCommandForPath: Command 0x16 (0x410004106a00) to NMP device "mpx.vmhba33:C0:T0:L0" failed
vmkernel: 0:00:32:01.819 cpu1:4097)ScsiDeviceIO: 770: Command 0x16 to device "mpx.vmhba33:C0:T0:L0" failed H:0x0 D:0x2 P:0x0 Valid sense data:
vmkernel: 0:00:32:01.819 cpu3:14174)Resv: 276: SCSI-2 Reservations are not supported by device mpx.vmhba33:C0:T0:L0.
vmkernel: 0:00:32:01.821 cpu3:14174)LVM: 6491: LVMProbeDevice failed on (4152466112, mpx.vmhba33:C0:T0:L0:1): Device does not contain a logica

Por lo tanto podemos concluir que sólo puede crearse un datastore bien conectando un nuevo disco (a través de fibra, iSCSI, SCSI o montando un volumen VMFS ya existente) o montando una carpeta compartida por NFS.

Aug 2, 2010

Conectar una unidad USB a un VMware vSphere (ESXi)

En este artículo vamos a ver cómo conectar y montar una unidad USB (en mi caso una memoria USB de 2 GB) a un VMware vSphere (ESXi). Para las pruebas voy a utilizar un VMware ESXi 4.0 (updated02).

Los requerimientos son dos: tener acceso a la service console y tener formateada la unidad de almacenamiento USB como FAT16 (recordar que VMware vSphere sólo reconoce dos clases de sistemas de archivos, FAT16 y VMFS).

En primer lugar, al conectar el dispositivo USB a la máquina podremos ver en el fichero /var/log/messages que una nueva unidad de almacenamiento USB ha sido encontrada.

~ # tail -f /var/log/messages
...
vmkernel: 0:00:09:58.654 cpu2:4316)<6>usb 1-7: new high speed USB device using ehci_hcd and address 2
...
vmkernel: 0:00:10:00.816 cpu1:9814)ScsiPath: 3715: Plugin 'NMP' claimed path 'vmhba33:C0:T0:L0'
vmkernel: 0:00:10:00.819 cpu1:9813)usb-storage: detected SCSI revision number 0 on vmhba33

Si le echamos un ojo a la tabla de particiones, podremos ver que el dispositivo ha sido detectado por el VMkernel.

~ # fdisk -l

Disk /dev/disks/mpx.vmhba33:C0:T0:L0: 2004 MB, 2004877312 bytes
255 heads, 63 sectors/track, 243 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot Start End Blocks Id System
/dev/disks/mpx.vmhba33:C0:T0:L0p1 * 1 243 1951866 6 FAT16

...

También si listamos todos los adaptadores de almacenamiento del sistema, podremos ver que disponemos de un nuevo dispositivo USB.

~ # esxcfg-mpath -l
...

usb.vmhba33-usb.0:0-mpx.vmhba33:C0:T0:L0
Runtime Name: vmhba33:C0:T0:L0
Device: mpx.vmhba33:C0:T0:L0
Device Display Name: Local USB Direct-Access (mpx.vmhba33:C0:T0:L0)
Adapter: vmhba33 Channel: 0 Target: 0 LUN: 0
Adapter Identifier: usb.vmhba33
Target Identifier: usb.0:0
Plugin: NMP
State: active
Transport: usb

Lo curioso de todo esto es que el VMkernel monta automáticamente el dispositivo en el directorio /vmfs/volumes/NO NAME, el cual es realmente un enlace simbólico a /vmfs/volumes/mpx.vmhba33:C0:T0:L0:1.

~ # ls -al /vmfs/volumes
...
l--------- 0 root root 1984 Jan 1 1970 NO NAME -> mpx.vmhba33:C0:T0:L0:1
drwxr-xr-x 1 root root 8 Jan 1 1970 c2a427e4-2d317086-fef9-b5750d88536c
l--------- 0 root root 1984 Jan 1 1970 datastore1 -> 4c0d40f4-c5706eb3-98db-001560a6d735
drwxr-xr-x 1 root root 8 Jan 1 1970 mpx.vmhba33:C0:T0:L0:1


Jul 26, 2010

Detección de rootkits con Rkhunter (Rootkit Hunter) (II)

Una vez presentadas las características de los rootkits y la herramienta que tenemos en Linux para combatirlos, vamos a pasar a instalar Rkhunter 1.3.6 en una máquina CentOS 5.4 de 64 bits.

Rkhunter puede instalarse de forma permanente en el sistema:

[root@centos ~]# tar zxf rkhunter-1.3.6.tar.gz

[root@centos ~]# cd rkhunter-1.3.6

[root@centos rkhunter-1.3.6]# ./installer.sh --install

O de forma temporal:

[root@centos ~]# mkdir /tmp/rkh

[root@centos ~]# cd /tmp/rkh

[root@centos rkh]# tar zxf rkhunter-1.3.6.tar.gz

[root@centos rkh/rkhunter-]# cd rkhunter-1.3.6

[root@centos rkhunter-1.3.6]# ./installer.sh --layout custom . --install

[root@centos rkhunter-1.3.6]# cd files

Para el caso del presente artículo emplearemos la forma temporal. Lo primero que haremos será actualizar las bases de datos con la información del malware actualizada por los desarrolladores de Rkhunter, y a continuación, crearemos una base de datos inicial (rkhunter.dat) con la información (MD5, permisos, etc.) de los principales binarios del sistema.

[root@centos files]# ./rkhunter --update
[ Rootkit Hunter version 1.3.6 ]

Checking rkhunter data files...
Checking file mirrors.dat [ No update ]
Checking file programs_bad.dat [ No update ]
...

[root@centos files]# ./rkhunter --propupd
[ Rootkit Hunter version 1.3.6 ]
File created: searched for 159 files, found 134, missing hashes 35

Si en algún momento alguno de los binarios sufre algún tipo de modificación, tendremos que volver a ejecutar la opción propupd.

Para realizar un escaneo ejecutaremos el siguiente comando (se ha obviado parte de la salida del comando):

[root@centos files]# ./rkhunter --check --sk
[ Rootkit Hunter version 1.3.6 ]

Checking system commands...

Performing 'strings' command checks
Checking 'strings' command [ OK ]

Performing 'shared libraries' checks
Checking for preloading variables [ None found ]
Checking for preloaded libraries [ None found ]
Checking LD_LIBRARY_PATH variable [ Not found ]

Performing file properties checks
Checking for prerequisites [ Warning ]
/bin/awk [ OK ]
/bin/basename [ OK ]
...
Checking for rootkits...

Performing check of known rootkit files and directories
55808 Trojan - Variant A [ Not found ]
ADM Worm [ Not found ]
...
Performing additional rootkit checks
Suckit Rookit additional checks [ OK ]
...
Performing malware checks
Checking running processes for suspicious files [ None found ]
...
Performing Linux specific checks
Checking loaded kernel modules [ OK ]
...
Checking the network...

Performing check for backdoor ports
Checking for TCP port 1524 [ Not found ]
Checking for TCP port 1984 [ Not found ]
...
Performing checks on the network interfaces
Checking for promiscuous interfaces [ None found ]

Checking the local host...

Performing system boot checks
Checking for local host name [ Found ]
...
Performing group and account checks
Checking for passwd file [ Found ]
...
Performing system configuration file checks
Checking for SSH configuration file [ Found ]
...
Performing filesystem checks
Checking /dev for suspicious file types [ None found ]
Checking for hidden files and directories [ Warning ]

Checking application versions...

Checking version of GnuPG [ OK ]
...
System checks summary
=====================

File properties checks...
Required commands check failed
Files checked: 134
Suspect files: 5

Rootkit checks...
Rootkits checked : 253
Possible rootkits: 0

Applications checks...
Applications checked: 4
Suspect applications: 2

Dentro del log (rkhunter.log) podremos encontrar información más detallada sobre los warnings y errores encontrados.

Rkhunter dispone de un fichero de configuración donde podremos definir distintas opciones del escaneo (por ejemplo si está permitido el acceso por SSH para root).

[root@centos files]# cat rkhunter.conf
...
ALLOW_SSH_ROOT_USER=yes


Jul 20, 2010

Scripts internos en Zabbix

Uno de los puntos fuertes de Zabbix es que a través de los agentes podemos ejecutar comandos o scripts dentro de los huéspedes o máquinas monitorizadas.

A diferencia de los scripts externos que son ejecutados por el servidor de Zabbix, los scripts internos serán lanzados por el propio agente dentro de la máquina monitorizada.

Vamos a mostrar un ejemplo sencillo, en donde un agente ejecutará periódicamente (cada 30 sg) un script encargado de volcar en un fichero (/tmp/file) el espacio ocupado por el directorio /etc. Este script devolverá el resultado de la operación (variable $?). Las pruebas serán realizadas en un CentOS 5.4 de 64 bits con Zabbix 1.8.1.

Lo primero que haremos será crear un directorio dentro del árbol de Zabbix para ubicar posteriormente nuestro script (script.sh).

[root@centos ~]# mkdir -p /etc/zabbix/internalscripts/

[root@centos ~]# vim /etc/zabbix/internalscripts/script.sh
#!/bin/bash
du -shx /etc >> /tmp/file
echo $?

[root@centos ~]# chown -R zabbix:zabbix /etc/zabbix/internalscripts

[root@centos ~]# chmod 700 /etc/zabbix/internalscripts/script.sh

Después tendremos que editar el fichero de configuración del agente de Zabbix habilitando la posibilidad de ejecutar comandos remotos.

[root@centos ~]# cat /etc/zabbix/zabbix_agentd.conf
...
# Nombre del host (salida del comando hostname)
Hostname=centos.local

EnableRemoteCommands=1

[root@centos ~]# service zabbix-agent restart

Ahora ya podremos crear un item (desde el interfaz web de Zabbix) que utilice el script creado. Le llamaremos por ejemplo "script interno".



En la figura anterior puede verse que dicho item deberá ser de tipo Zabbix agent (active), y como clave (key) utilizaremos la función system.run para ejecutar el script. El script devolverá un número entero decimal (0 en caso de éxito y 1 en caso contrario); por lo tanto escogeremos como tipo de información Numeric (unsigned).

Un error típico que suele cometer la gente al crear un item de esta naturaleza consiste en establecer un tipo retornado incorrecto. Para el caso anterior hemos dicho que se trataba de un valor entero decimal. Si en dicho script no hubiésemos puesto la línea "echo $?", al poco tiempo de activar el item éste se hubiera deshabilitado, obteniendo un estado con el mensaje Not supported.

Analizando el log del agente de Zabbix hubiéramos visto una línea como la siguiente:

[root@centos ~]# tail -f /var/log/zabbix-agent/zabbix_agentd.log
...
796:20100629:174748.005 Active check [system.run[/etc/zabbix/internalscripts/script.sh]] is not supported. Disabled.