POODLE Attack (die SSLv3!)
Leyendo noticias de seguridad, me topé con este interesante ataque que afecta la versión SSLv3 y permite a un atacante desencriptar porciones de tráfico HTTPS, como por ejemplo cookies.

Últimamente al pobre protocolo no le ha ido muy bien, basta recordar el mortal Heartbleed descubierto hace unos meses, y otros ataques como BEAST y CRIME descubiertos hace un par de años, o Lucky-13, por citar algunos.

Una de las personas que participó en el descubrimiento de esta vulnerabilidad es Thai Duong, quien también participó (junto a Juliano Rizzo) en el descubrimiento de BEAST y CRIME. En este caso, Thai trabajó con otros empleados de Google (Bodo Möller y Krzysztof Kotowicz) para el descubrimiento.

Como mencioné al principio, el ataque afecta sólo a SSLv3, el cual está obsoleto desde hace unos años, pero que todavía es soportado por muchos servidores y browsers por compatibilidad. La versión más actual del protocolo es TLSv1.2, pero los clientes pueden negociar con el servidor una versión inferior del protocolo, en caso de no soportar esta última.

El ataque no es tan directo como Heartbleed, ya que es necesario realizar previamente un ataque Man-in-the-Middle (MiTM). Pero un ataque MiTM no es tan complejo si tenemos acceso a la red de la víctima, o si accedemos a una red WiFi pública (hoteles, bares, etc).

Los detalles del ataque los pueden leer en el paper original, pero básicamente explota la encripción CBC utilizada en SSLv3, debido a la forma en que este algoritmo utiliza los paddings para completar bloques.

Según comentan en el paper, la única forma de evitar este ataque es eliminando el uso de SSLv3. En el mismo, proponen utilizar el mecanismo TLS_FALLBACK_SCSV para la negociación, en clientes y servidores. Utilizando TLS_FALLBACK_SCSV, el servidor siempre utilizará la versión más actual del protocolo habilitada en el mismo, rechazando cualquier intento de conexión con una versión inferior. Obviamente, si el servidor no soporta una versión superior a SSLv3, entonces será vulnerable igual.

Existen varios mecanismos para averiguar qué versiones de SSL/TLS soporta un servidor. Les dejo un par para que verifiquen sus servidores.

Una forma simple, es utilizar la capacidad de ejecución de scripts de NMAP, el cual todo administrador de seguridad tiene instalado:
$ nmap --script ssl-enum-ciphers -p 443 <IP Servidor>
Algo más avanzado es utilizar una herramienta dedicada a chequear conexiones SSL, denominada SSLyze, la cual pueden descargar aquí. Esta herramienta está escrita en python y se puede ejecutar sin instalarse:
$ python sslyze.py --regular <IP Servidor>:443
Finalmente y también muy interesante, es la herramienta web provista por Qualys, la cual chequea múltiples vulnerabilidades SSL, así como lista los protocolos soportados y genera un reporte. La misma se accede aquí.
Nagios: generar gráficos con PNP4Nagios
Hace tiempo que estoy trabajando con Nagios y MRTG, como pudieron observar en Nagios: monitoreo remoto de dispositivos + agentes Linux + agentes Windows, y  Monitoreo de ancho de banda en routers/switches/etc usando MRTG. Ambas herramientas me resultaron excelentes y me ayudan mucho en el monitoreo diario de la infraestructura de red.
Desde hace un tiempo vengo buscando la forma de integrar más gráficos en Nagios, y me pareció interesante utilizar MRTG para hacerlo. Esto es perfectamente posible y hasta comencé a trabajar en ello, pero luego descubrí PNP4Nagios y cambié la perspectiva.

Tal como cita la página oficinal:
PNP es un addon para Nagios que analiza datos de performance (performance data) provistos por los plugins y los almacena en bases de datos RRD.
Oye, eso suena similar a lo que MRTG hace. Pues claro, el acercamiento es similar, almacenar datos en bases de datos RRD y luego graficar a partir de ellos utilizando rrdtool. De forma similar trabajan Ntop y otras herramientas.

PNP4Nagios tiene una interfaz web muy atractiva y simple de usar, permitiendo seleccionar intervalos de tiempo de forma dinámica, navegar fácilmente entre servicios de hosts, y generar reportes en PDF. Tal vez una de las características más interesantes es la posibilidad de definir templates propios para indicarle la forma de evaluar y generar los gráficos. Dado que trabaja directamente con RRDTool, brinda todas las facilidades de graficación que esta herramienta provee.

Cabe destacar que para poder graficar datos, los plugins deben retornar información en el campo performance_data, y no todos los plugins lo hacen. Por suerte, quienes diseñan buenos plugins si entregan datos de performance. Estos datos deben tener un formato especial para que PNP pueda parsearlos y almacenarlos, pero esa discusión la dejaré para algún artículo sobre creación de plugins.
Para saber fácilmente si un plugin entrega datos de performance, pueden ejecutarlo desde la consola y ver si incluye el caracter pipe "|" en el resultado impreso. Todo lo que venga luego del pipe son datos de performance. Por ejemplo:
  $./check_icmp -H 10.6.143.101
  OK - 10.6.143.101: rta 1,593ms, lost 0%|rta=1,593ms;200,000;500,000;0; pl=0%;40;80;; rtmax=4,541ms;;;; rtmin=0,832ms;;;;
Este plugin entrega 4 datos de performance:
  - rta: tiempo de respuesta,
  - pl: porcentaje de pérdida de paquetes,
  - rtmax: tiempo máximo de respuesta,
  - rtmin: tiempo mínimo de respuesta.
 

Integración con Nagios

PNP4Nagios provee varios modos de integrarse con Nagios, cada uno con sus ventajas y desventajas:

  • Synchronous: cada vez que Nagios ejecuta un plugin, luego llama el script process_perfdata.pl para actualizar los valores de la base de datos RRD y el archivo XML correspondiente. La mayor desventaja de esta forma de integración es que Nagios ejecuta process_perfdata.pl cada vez que realiza un check de host o servicio.
  • Bulk: este modo permite realizar múltiples actualizaciones de datos de performance juntos. Nagios escribe en un archivo temporal los datos obtenidos en cada check, y a intervalos definidos, Nagios ejecuta el script process_perfdata.pl.
  • Bulk with NPCD: desde el punto de vista de Nagios, es la mejor opción, dado que se independiza de la ejecución del script process_perfdata.pl. La ejecución de script queda a cargo del demonio NPCD (Nagios Performance C Daemon), el cual monitorea un directorio, donde deben ubicarse los datos de performance, a la espera de que un archivo sea creado. De esta forma, Nagios se encarga de guardar los datos de la ejecución de los plugins en archivos y luego mover los archivos al directorio donde los tomará NPCD.
  • Bulk with NPCD and npcdmod: el flujo de datos es igual a Bulk with NPCD, con la diferencia que simplifica la configuración de Nagios, ya que las definiciones de cómo procesar los datos se dejan al módulo npcdmod. El uso de este módulo se realiza definiendo un broker en la configuración de Nagios. Debe tenerse en cuenta que este modo no funciona con Nagios 4.
  • Gearman: se utiliza el módulo Gearman como agente intermediario entre Nagios y el procesamiento de los datos. Nagios se encarga de generar los datos y mod_gearman (broker para Nagios) se encarga de encolarlos para su procesamiento, utilizando el demonio gearmand. Luego el script process_perfdata.pl escanea esta cola en busca de datos. La mayor ventaja de este modo es que Nagios y PNP4Nagios pueden ejecutarse en máquinas distintas, ya que la conexión de Nagios con Gearman es a través de sockets. Además Gearman funciona con workers y puede tener múltiples workers trabajando a la vez. Este modo es el ideal para instalaciones de Nagios con hosts y servicios.

De las opciones listadas, elegí utilizar el modo Bulk with NPCD y npcdmod, dado lo fácil que es ponerlo en funcionamiento, y las ventajas que provee sobre el modo Synchronous. Si algún día utilizan Nagios 4, deberían utilizar otra opción como Bulk with NPCD o Gearman.


Instalación y Configuración

Instalar PNP4Nagios en debian y derivados es tan simple como ejecutar:
  # apt-get install pnp4nagios rrdtool
Existen paquetes para otras distribuciones como CentOS.
 
Luego de instalarlo, para integrarlo con Nagios utilizando el modo Bulk with NPCD y npcdmod, debe realizarse los siguientes pasos.

Setear la variable RUN en yes, en el archivo /etc/default/npcd, para habilitar en demonio NPCD.
RUN=yes
Editar el archivo /etc/nagios3/nagios.cfg de la siguiente manera:
# Habilita el procesamiento de datos de performance entregados por los plugins de chequeo
process_performance_data=1
# Hacer que Nagios comparta su información con la librería npcdmod
broker_module=/usr/lib/pnp4nagios/npcdmod.o config_file=/etc/pnp4nagios/npcd.cfg
Recargar Nagios:
/etc/init.d/nagios3 reload
Gualá, ya está la integración, eso fue fácil.

Por defecto, PNP4Nagios se habilita en un directorio web distinto al de Nagios. Los gráficos se acceden apuntando a las siguientes direcciones:
http://<nombre servidor>/pnp4nagios/pnp4nagios/graph?host=<nombre del host>
http://<nombre servidor>/pnp4nagios/pnp4nagios/graph?host=<nombre del host>&srv=<descripción del servicio>
Como nombre de host debe utilizarse el nombre que se utilizó para definirlo en Nagios.


Una forma más directa de acceder a los gráficos, es agregar el link como un action_url en la definición de hosts en Nagios. El camino fácil es definir nuevos templates para hosts y servicios, de la siguiente manera:
define host {
 use generic-host
 name pnp-host
 action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_
 register 0
}
define service {
 name pnp-service
 action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$
 register 0
}
Luego, para cada host o servicio que se desee ver gráficos, simplemente agregar pnp-host y pnp-service en la definición de hosts.


Pensamientos Finales

A diferencia de MRTG que utiliza consultas SNMP para obtener sus datos, PNP4Nagios utiliza los datos entregados por los plugins de Nagios... los cuales pueden sacar datos por SNMP o de muchas otras maneras. Esta funcionalidad me resultó mucho más abarcativa, y ya que igualmente necesito Nagios y estoy obteniendo datos con sus plugins, por qué no aprovecharlos para generar los gráficos.
Claro que es posible obtener con MRTG datos de otras fuentes que no sea SNMP, MRTG es muy flexible. Sería posible llegar a resultados similares a los obtenidos con Nagios y PNP, pero de una forma más laboriosa. No estoy diciendo que esta solución reemplace MRTG, sino que me parece mucho más completa. La elección de utilizar una u otra es de cada administrador.



Referencias

- PNP4Nagios Documentation
- Archivo /usr/share/doc/pnp4nagios/README.Debian
Obtener uso de CPU y memoria, temperatura y estado de interfaces de dispositivos Cisco, utilizando SNMP
Continuando con la labor de monitorear el estado de dispositivos conectados a la red, decidí profundizar en el control de equipamiento Cisco. Para ello, recurrí al viejo pero muy vigente y útil protocolo SNMP. Los dispositivos Cisco, como la gran mayoría de los dispositivos de red, proveen información detallada a través de SNMP. El problema es que entre tanta información provista, uno se puede marear y perder lo que le interesa conocer.

Dado que no encontré mucha información que detalle cómo monitorear e interpretar la información de los recursos más importantes (si encontré pedazos de información por separado), decidí investigar y armar documentación propia. Distintas páginas de Cisco proveen información, pero dan por asumido que conocemos relativamente bien la información provista. Lo único que me resultó realmente útil es el navegador de objetos SNMP (http://tools.cisco.com/Support/SNMP/do/BrowseOID.do?local=en). En base a este último pude recopilar y armar las consultas que yo requería.

Yendo al grano, con la información provista en este artículo podrán no sólo saber cómo obtener por SNMP información del estado de los recursos del dispositivo, sino también entender los valores obtenidos.

Me centraré en obtener la información listada a continuación, la cual abarca todo lo necesario para conocer el estado de un dispositivo:
- Estado de las interfaces de red del dispositivo.
- Uso de CPU.
- Temperatura del chasis, y/u otra información provista por los sensores que el equipo posea.
- Uso de memoria.
En el artículo me centraré en describir los OIDs necesarios para obtener la información listada. Los ejemplos los haré utilizando snmpwalk como herramienta de consulta. Esta misma información se puede obtener con distintos clientes snmp, snmpwalk es sólo uno de ellos, muy versátil y completo. Una vez que se conocen los OIDs y la información provista, es muy fácil automatizar el monitoreo con herramientas como Nagios, o scripts propios. Dejaré la integración con Nagios para otro artículo :D

Si les interesa el monitoreo de redes, pueden encontrar más información al respecto en mis anteriores artículos:
- Nagios: monitoreo remoto de dispositivos + agentes Linux + agentes Windows
- Monitoreo de ancho de banda en routers/switches/etc usando MRTG
- Armar servidor de logging con rsyslog y configurar dispositivos para logging remoto
- Instalar Zabbix en Debian GNU/Linux

Estado de Interfaces

Hay ciertas interfaces que son muy interesantes para monitorear, dado que ello nos permitirá saber si un equipo importante perdió la conexión. Interfaces de este tipo pueden ser uplinks entre edificios, conexiones a servidores, enlaces a la WAN, etc.

El OID utilizado para ver el estado de las interfaces es el 1.3.6.1.2.1.2.2.1.8 (objeto ifOperStatus), descripto como "The current operational state of the interface". Este OID contiene una entrada por cada interfaz presente en el switch.
Por ejemplo, al realizar un walk en un 2950, obtenemos la siguiente información:
$ snmpwalk -v2c -c public 192.168.1.100 -On  1.3.6.1.2.1.2.2.1.8
.1.3.6.1.2.1.2.2.1.8.1 = INTEGER: up(1)
.1.3.6.1.2.1.2.2.1.8.2 = INTEGER: down(2)
.1.3.6.1.2.1.2.2.1.8.3 = INTEGER: down(2)
...
...
Ok, esto nos da el estado de las interfaces... pero cómo sabemos cuál interfaz es cada una? Para esto existe el OID 1.3.6.1.2.1.2.2.1.2 (objeto ifDescr), que contiene información de la interfaz. En el ejemplo anterior, la consulta de este OID nos dará lo siguiente:
$ snmpwalk -v2c -c public 192.168.1.100 -On  1.3.6.1.2.1.2.2.1.2
.1.3.6.1.2.1.2.2.1.2.1 = STRING: FastEthernet0/1
.1.3.6.1.2.1.2.2.1.2.2 = STRING: FastEthernet0/2
.1.3.6.1.2.1.2.2.1.2.3 = STRING: FastEthernet0/3
...
Ahora si, ya sabemos que el OID 1.3.6.1.2.1.2.2.1.8.1 representa el estado de la interfaz FastEthernet0/1, el 1.3.6.1.2.1.2.2.1.2.3 la Fa0/3, etc. Para cada interfaz que se desee monitorear, deberá consultarse primero la descripción de la misma, así sabemos con cuál OID se relaciona.


Uso de CPU

Cisco almacena distintos valores para el uso de CPU, utilizando distintos períodos de tiempo. Los OIDs son:
  • 1.3.6.1.4.1.9.9.109.1.1.1.1.10 (cpmCPUTotalMonIntervalValue): uso de CPU en el intervalo especificado por 1.3.6.1.4.1.9.9.109.1.1.1.1.9 (cpmCPUMonInterval). El intervalo suele ser 5 segundos, y este OID es el que debe utilizarse en lugar de cpmCPUTotal5sec y cpmCPUTotal5secRev, ya en desuso.
  • 1.3.6.1.4.1.9.9.109.1.1.1.1.7 (cpmCPUTotal1minRev): uso en el último minuto. Anteriormente se utilizaba cpmCPUTotal1min.
  • 1.3.6.1.4.1.9.9.109.1.1.1.1.8 (cpmCPUTotal5minRev): uso en los últimos cinco minutos. Debe utilizarse en lugar de cpmCPUTotal5min.
La empresa recomienda utilizar cpmCPUTotal5minRev, dado que representa la mejor estimación de uso.
Todos estos valores representan porcentaje de uso y van de 0 a 100.

Ejemplo de consulta del valor de carga de CPU en los últimos 5 minutos es el siguiente:
$ snmpwalk -v2c -c public 192.168.1.100 -On  1.3.6.1.4.1.9.9.109.1.1.1.1.8
.1.3.6.1.4.1.9.9.109.1.1.1.1.8.1 = Gauge32: 6
es decir, la carga es de 6%.

En la página How to Collect CPU Utilization on Cisco IOS Devices Using SNMP se explica bien como obtener información del uso de CPU.


Sensores (midiendo temperatura y estado de fans)

Existen varios sensores en los dispositivos que permiten medir diferentes valores, como la temperatura del chasis y el funcionamiento de los fans. Los valores de los sensores se almacenan en el objeto 1.3.6.1.4.1.9.9.91.1.1.1.1.4 (entSensorValue).
Por ejemplo, accediendo los valores de los sensores en un 4500 obtendremos algo así:
$ snmpwalk -v2c -c public 192.168.1.200 -On 1.3.6.1.4.1.9.9.91.1.1.1.1.4
.1.3.6.1.4.1.9.9.91.1.1.1.1.4.9 = INTEGER: 35
.1.3.6.1.4.1.9.9.91.1.1.1.1.4.15 = INTEGER: 1
.1.3.6.1.4.1.9.9.91.1.1.1.1.4.18 = INTEGER: 2
Este objeto contiene entradas indexadas según el índice físico de cada entidad (en este caso, el sensor es la entidad). Para saber a qué entidad refiere cada índice, se puede consultar el objeto 1.3.6.1.2.1.47.1.1.1.1.2 (entPhysicalDescr), el cual describe cada entidad física.
En el ejemplo anterior, podemos ver lo siguiente al consultar este objeto:
$ snmpwalk -v2c -c public 192.168.1.200 -On 1.3.6.1.2.1.47.1.1.1.1.2
...
.1.3.6.1.2.1.47.1.1.1.1.2.9 = STRING: "Chassis Temperature Sensor"
...
.1.3.6.1.2.1.47.1.1.1.1.2.15 = STRING: "Power Supply Fan Sensor"
...
.1.3.6.1.2.1.47.1.1.1.1.2.18 = STRING: "Power Supply Fan Sensor"
Es decir, los valores obtenidos anteriormente son la temperatura del chasis y el estado de los fans de las fuentes.
Ahora, qué significan esos valores? en qué unidades están representados? Bueno, para esto necesitamos consultar ooootro objeto, el 1.3.6.1.4.1.9.9.91.1.1.1.1.1 (entSensorType), que nos indica de qué tipo es cada sensor:
.1.3.6.1.4.1.9.9.91.1.1.1.1.1.9 = INTEGER: 8
.1.3.6.1.4.1.9.9.91.1.1.1.1.1.15 = INTEGER: 12
.1.3.6.1.4.1.9.9.91.1.1.1.1.1.18 = INTEGER: 12
Cisco tiene predefinidos estos valores en una tabla, la cual se puede encontrar en su página. La tabla indica lo siguiente:
1:other
2:unknown
3:voltsAC
4:voltsDC
5:amperes
6:watts
7:hertz
8:celsius
9:percentRH
10:rpm
11:cmm
12:truthvalue
13:specialEnum
14:dBm
Con esto sabemos que el primer sensor mide grados celsius (valor 8), y los otros dos otorgan un valor booleano (12). Pero qué significan los valores 1 y 2? cuál es verdadero y cuál es falso? Consultando la página de Cisco, encontramos lo siguiente:
other(1): a measure other than those listed below
unknown(2): unknown measurement, or
arbitrary, relative numbers
voltsAC(3): electric potential
voltsDC(4): electric potential
amperes(5): electric current
watts(6): power
hertz(7): frequency
celsius(8): temperature
percentRH(9): percent relative humidity
rpm(10): shaft revolutions per minute
cmm(11),: cubic meters per minute (airflow)
truthvalue(12): value takes { true(1), false(2) }
specialEnum(13): value takes user defined enumerated values
dBm(14): dB relative to 1mW of power
Gracias a esta última información, ahora sabemos que 1 es verdadero, y 2 es falso. Es decir, el Fan 1 funciona bien, mientras que el 2 no.

Juntando todo este meollo de consultas, ahora sabemos lo siguiente:
  • El switch posee 3 sensores.
  • El primero mide la temperatura del chasis, la cual en este momento es de 35º
  • Los otros dos sensores chequean el estado de los fans de las fuentes, estando el primer fan funcionando bien y el segundo no.
 
Uso de Memoria

Es posible ver el uso de memoria de los dispositivos, así como la cantidad de memoria libre, accediendo al objeto 1.3.6.1.4.1.9.9.48 (ciscoMemoryPoolMIB). Cisco divide la memoria en pools, según su uso. Los tipos de pools predefinidos son:
1:  processor memory
2:  i/o memory
3:  pci memory
4:  fast memory
5:  multibus memory
Además, los pools pueden ser categorizados en dinámicos o predefinidos. De los listados anteriormente, sólo el tipo processor debe ser soportado por todos los dispositivos.
Ejemplo de valores obtenidos en un 2950:
$ snmpwalk -v2c -c public 192.168.1.100 -On 1.3.6.1.4.1.9.9.48
.1.3.6.1.4.1.9.9.48.1.1.1.2.1 = STRING: "Processor"
.1.3.6.1.4.1.9.9.48.1.1.1.2.2 = STRING: "I/O"
.1.3.6.1.4.1.9.9.48.1.1.1.3.1 = INTEGER: 2
.1.3.6.1.4.1.9.9.48.1.1.1.3.2 = INTEGER: 0
.1.3.6.1.4.1.9.9.48.1.1.1.4.1 = INTEGER: 1
.1.3.6.1.4.1.9.9.48.1.1.1.4.2 = INTEGER: 1
.1.3.6.1.4.1.9.9.48.1.1.1.5.1 = Gauge32: 2417476
.1.3.6.1.4.1.9.9.48.1.1.1.5.2 = Gauge32: 687872
.1.3.6.1.4.1.9.9.48.1.1.1.6.1 = Gauge32: 1467696
.1.3.6.1.4.1.9.9.48.1.1.1.6.2 = Gauge32: 1492064
.1.3.6.1.4.1.9.9.48.1.1.1.7.1 = Gauge32: 1274620
.1.3.6.1.4.1.9.9.48.1.1.1.7.2 = Gauge32: 1492060
De los valores obtenidos, tenemos que:
  • 1.3.6.1.4.1.9.9.48.1.1.1.2 (ciscoMemoryPoolName) define el nombre del pool. En el ejemplo hay dos pools, Processor e I/O.
  • 1.3.6.1.4.1.9.9.48.1.1.1.5 (ciscoMemoryPoolUsed) muestra el uso de memoria actual de cada pool, expresado en bytes.
  • 1.3.6.1.4.1.9.9.48.1.1.1.6 (ciscoMemoryPoolFree) representa la memoria libre en cada pool, también en bytes.
La memoria total del equipo se puede obtener sumando los bytes libres con los utilizados.
Tips: Montar carpeta compartida VirtualBox en Guests debian y derivados
Hoy me topé con un problema extraño, pero que por lo que encontré googleando, es común. Hasta ahora no se me había dado por montar shares en una máquina virtual debian (virtualizada usando VirtualBox), así que no me había pasado. Usando guests Windows siempre me funcionó correctamente.
Dado que requiere algunos pasos, decidí armar un mini instructivo de cómo hacerlo, ya que seguramente alguien más se encuentre con el mismo problema. Veamos los pasos:

Como todo manual de VBox indica, primero hay que instalar las Guest Additions antes de poder compartir carpetas entre el host y el guest. Previo a esto, hay que contar con los headers del kernel (paquete linux-headers-), y make. Una vez que cuentan con estos paquetes (make instala los compiladores y demás), realizar lo siguiente:
  1. Ir a la ventana de la máquina virtual, elegir la opción "Dispositivos" -> Insertar imagen de CD de las «Guest Additions»". Esto habilitará la imagen en la lectora virtual del guest.
  2. Montar el cd virtual ejecutando: mount /dev/cdrom -o exec
  3. Ejecutar el script correspondiente a Linux:  /media/cdrom/VBoxLinuxAdditions.run
Con lo anterior debería bastar para montar los shares según el manual oficial, ejecutando:
mount -t vboxsf share /lugar-a-montar
Sin embargo esto no es así en debian (y derivados también, no se en otras distros), al menos al utilizar VBox 4.3.10. Por alguna razón cambiaron de lugar el path donde se instalan las Guest Additions, o bien apuntaron mal el enlace de mount.vboxsf... sea cual sea la razón, al intentar montar una partición, mount dará error y syslog dirá:
sf_read_super_aux err=-22
Para evitar esto, tenemos dos alternativas:
1. Linkear el directorio desde donde debería estar a donde realmente está:
ln -s /opt/VBoxGuestAdditions-4.3.10/lib/VBoxGuestAdditions /usr/lib/
2. O linkear el ejecutable mount.vboxsf a donde está el ejecutable realmente:
rm /sbin/mount.vboxsf
ln -s /opt/VBoxGuestAdditions-4.3.10/lib/VBoxGuestAdditions/mount.vboxsf /sbin/mount.vboxsf
Bien, esto debería alcanzar... salvo en algunos casos. Increíblemente si dejamos el mismo nombre de share que el del directorio al que apunta el share (por ejemplo usar el share "datos" para apuntar al directorio /datos), mount fallará horriblemente diciendo:
/sbin/mount.vboxsf: mounting failed with the error: Protocol error
Mientras que syslog indicará lo siguiente:
sf_read_super_aux err=-71
WTF?! si, increíble. Así que recuerden llamar distinto al share que a la carpeta a la que apunta. Por ejemplo, ponerle vdatos al share que apunta a /datos en el host (siguiendo el ejemplo anterior).

Ahora si, a montar felizmente (?!).


Referencias

Shared folders will not mount after 3.10 update
Mounting share directory on Linux host result in Protocol error if default share name is used
Instalar Zabbix en Debian GNU/Linux
Después de haber leído muchas buenas críticas acerca de Zabbix, decidí instalarlo sobre un debian para probarlo. Dado que no fue una tarea trivial, decidí documentarla para facilitarle la vida a alguien más. Para empezar, salvo un artículo específico, no encontré documentación que explique bien cómo utilizar los paquetes provistos en debian. Debian trae Zabbix en sus repositorios, pero instalar el servicio no es tan directo como instalar los paquetes, requiere varios pasos adicionales. Esto me molestó bastante, dado que se podría automatizar todo este proceso en la misma instalación del paquete. Igualmente, conociendo los pasos, no es una tarea compleja, sólo algo tediosa :P El artículo en el que me basé para la instalación es How To Install Zabbix on Ubuntu & Configure it to Monitor Multiple VPS Servers.


Instalar los paquetes necesarios
Para instalar Zabbix, ejecutar lo siguiente:
# apt-get install apache2 php5-mysql mysql-server zabbix-server-mysql zabbix-frontend-php
Los paquetes de Apache, PHP5 y MySQL sólo son necesarios si aún no los instalaron, se agregan por completitud. Los paquetes de Zabbix crean los archivos del servidor zabbix, y copian los archivos del front-end en /usr/share, pero sólo eso... restan varios pasos. Es posible instalar Zabbix sobre PostgreSQL.


Configuración base de datos

Los paquetes instalados no crean la base de datos, ni el usuario, por lo que hay que hacerlo manualmente. Los siguientes pasos explican cómo hacer este proceso:
  1. Desde MySQL (i.e. logueados con $mysql -u root -p), crear la base de datos, el usuario y asignarle permisos:
    mysql> create database zabbix_db;
    mysql> create user 'zabbix_usr'@'localhost' identified by 'ELpassword';
    mysql> grant all privileges on zabbix_db.* to 'zabbix_usr'@'localhost';
    mysql> flush privileges;
  2. Los valores para el nombre de usuario y base de datos pueden elegirse a gusto. El comando final permite recargar los permisos para que se asignen los nuevos.
  3. Crear las tablas y asignar los valores default provistos por Zabbix. Para esto existen los archivos /usr/share/zabbix-server-mysql/{schema.sql.gz, images.sql.gz, data.sql.gz}. Descomprimirlos y ejecutarlos con MySQL, con destino la base de datos recién creada.
    /usr/share/zabbix-server-mysql$ gunzip schema.sql.gz images.sql.gz data.sql.gz
    $ mysql -u root -p zabbix_db < schema.sql
    $ mysql -u root -p zabbix_db < images.sql
    $ mysql -u root -p zabbix_db < data.sql

Servidor Zabbix

Según la definición de la base de datos, hay que adaptar el archivo de configuración del serivicio Zabbix. Debe editarse el archivo /etc/zabbix/zabbix_server.conf y ajustar los siguientes valores:
DBName=zabbix_db
DBUser=zabbix_usr
DBPassword=ELpassword
Además, dado que por defecto el servicio Zabbix no inicia automáticamente, debe editarse el archivo /etc/default/zabbix-server y dejar la siguiente sentencia:
START=yes
Luego si podremos iniciar el servicio:
# /etc/init.d/zabbix-server start

Front-End Web

Para habilitar el front end web, deben realizarse los siguientes pasos:
  1. Copiar el archivo de configuración de Apache, provisto en el paquete Zabbix, a su lugar correspondiente, para habilitar el acceso web:
    # cp /usr/share/doc/zabbix-frontend-php/examples/apache.conf /etc/apache2/conf-enabled/zabbix.conf
    En versiones anteriores de debian, los archivos de configuración se copian en /etc/apache2/conf.d

  2. Editar el archivo /etc/php5/apache2/php.ini y asignar los siguientes valores a las variables correspondientes, para adaptar la configuración de PHP a los requerimientos de Zabbix
    post_max_size = 16M
    max_execution_time = 300
    max_input_time = 300
    date.timezone = America/Argentina/Buenos_Aires
    donde el timezone dependerá de su ubicación (ver List of Supported Timezones).
  3. Reiniciar el servidor Apache:
    # service apache2 restart
  4. Abrir, desde el navegador, la página de Zabbix. La misma se encuentra en http://<IP del servidor>/zabbix. Esto redirige al wizzard de configuración inicial, donde:
    2- Se chequea que los requisitos para correr Zabbix se cumplan. Si alguno no se cumple, mostrará un fail y no permitirá seguir hasta tanto se corrija.
    3- Solicita se configuren los datos de la base de datos. Si MySQL no aparece entre las opciones, es que les falta el paquete php5-mysql
    4- Permite asignar los valores del servidor Zabbix. Si no cambiaron nada en la configuración del server, dejar los que están por defecto.
    5- Muestra el resultado de la configuración y permite revisar los valores antes de terminar.
    6- Intenta crear el archivo /etc/zabbix/zabbix.conf.php. Si el servicio no tiene permiso para hacerlo (lo cual será así), descargar el archivo y copiarlo manualmente en el directorio correspondiente.
    Una vez creado el archivo, clickear "Retry" y mostrará un mensaje OK. Clickear "Finish" para ir a la página principal.
  5. Ingresar al sistema con el usuario admin y contraseña zabbix.

Fin
AirWatch MDM Review
Hace un tiempo comenzamos a utilizar dispositivos Android en la empresa y se hizo evidente que necesitaríamos un software para administrarlos. Desde hace varios años utilizamos BlackBerry, para lo cual contamos con BlackBerry Enterprise Server (BES). Personalmente BES siempre me pareció una cagada, tiene sus cosas buenas y fue uno de los pioneros del rubro, pero las cosas no andan bien. Los servicios de BB en general siempre me parecieron una bosta. Que algún administrador de BES me diga si al menos una vez al mes (o a la semana) algún BB deja de sincronizar los mails y encuentra otro remedio más que desvincular el equipo y volver a vincurlarlo? si, a veces se soluciona con una reiniciada, pero muchas veces no! y lo peor es que es imposible saber la causa.

Bueno, dejando mi resentimiento hacia BES, volvemos a Android. Android es una plataforma muy buena, pero creo que no tan orientada a las empresas todavía. De a poco va queriendo, pero todavía le falta bastante. El tema es que los dispositivos Android parecen estar pensados solamente para el usuario hogareño. Para poder utilizar este sistema a nivel corporativo, necesitamos una herramienta que nos brinde ciertas funcionalidades.

Veamos primero qué es lo que se necesita para poder administrar dispositivos móviles en general, y luego nos adentraremos en AirWatch en particular.


Introducción MDM para Android

Mi experiencia me permite distinguir las siguientes necesidades, a la hora de administrar dispositivos móviles Android (u otros) corporativos:
  • Uso de mail corporativo: Android soporta ActiveSync para poder utilizar un servidor de correo Exchange. La necesidad que identifico es poder administrar esta conexión desde un software centralizado.
  • Políticas de seguridad: muy pero muy importante es poder aplicar restricciones a los equipos. Como la mayoría sabe, existen miles de aplicaciones maliciosas para Android. Si permitimos a cualquier usuario instalar cualquier cosa, vamos a tener un grave problema. Las políticas de seguridad deben permitir:
    • Forzar uso de PIN o patrón para bloquear el dispositivo.
    • Bloquear la instalación y desinstalación de aplicaciones. Así como no queremos que instalen nada, también queremos que no desinstalen software básico.
    • Bloquear "reset to factory" del equipo. Si borran la configuración, después pueden hacer cualquier cosa.
    • >
    • Bloquear el cambio de ciertas capacidades estéticas, como cambio de wallpaper.
  • Instalación remota de aplicaciones: bien, no permitimos instalar aplicaciones al usuario, pero si el mismo necesita algo para sus tareas, debemos poder instalarselo. Estos usuarios puede que no estén físicamente en las instalaciones de la empresa, así que poder instalar aplicaciones desde el administrador, es un requisito.
  • Uso de encripción: dado que los equipos pueden transportar información sensible, es necesario poder activar la encripción de la tarjeta de memoria y/o memoria del equipo.
  • Bloqueo / Wipe remoto: si un dispositivo es robado o perdido, el administrador debe poder bloquearlo e incluso borrarlo para que no se accedan a los datos de la empresa.
  • Configuración centralizada: tener que configurar muchos dispositivos de a uno, no solo estresa a cualquiera, sino que es una pérdida de tiempo. La mejor alternativa es realizar la configuración una vez, y que todos los dispositivos la apliquen al conectarse.

Los programas que proveen estas funcionalidades se denominan Mobile Device Management (MDM), y hay varios dando vueltas. El mismo BES es un MDM que implementa las funcionalidades descriptas. Uno de estos MDMs es AirWatch y en él me enfocaré el resto del artículo. AirWatch, según sus propias palabras, es el MDM líder a nivel empresarial.


AirWatch

Estuve utilizándo AirWatch durante un par de semanas, haciendo varias pruebas, y quería compartir mi experiencia con esta herramienta, por si alguno de ustedes está buscando algún MDM y está indeciso. Les comentaré tanto las cosas buenas, como las cosas malas que encontré al utilizarlo.

Para empezar, me pareció muy útil que soporte múltiples sistemas operativos (Android, iOS, BlackBerry, Symbian, Windows Phone, Mac OS X, entre otros). Si el parque de dispositivos no es homogéneo, como en nuestro caso, esto es una característica importante. Es importante observar aquí que no es la panacea. Si bien el soporte de sistemas operativos existe, en muchos casos el soporte es muy limitado. Por ejemplo, no podrán reemplazar BES por AirWatch para administrar los BlackBerry, ya que las características que AirWatch soporta para BB son muy (MUY) limitadas.
En cada opción de configuración de AirWatch, podrán observar al costado, qué sistemas operativos la soportan. Incluso dependiendo la versión del sistema operativo, puede que la opción esté disponible o no (por ejemplo, algunas cosas disponibles para Android 3, no están disponibles para Android 2). A favor de AirWatch hay que decir que en muchos casos la limitación la pone el sistema operativo. Si el sistema operativo no provee una forma de evitar el uso de la cámara, el software no podrá hacerlo.
Otro punto a tener en cuenta, es que la mayoría de las opciones de configuración para Android, sólo están disponibles para dispositivos SAFE (Samsung For Enterprises). Si no adquirieron dispositivos Android que sean SAFE, casi que ni les conviene utilizar AirWatch.

AirWatch implementa todos los puntos listados en la introducción, aunque no todos para todos los sistemas operativos. Para equipos SAFE, todas las opciones están disponibles, teniendo algunas limitaciones en cuanto a la granularidad.
Algo interesante es que AirWatch permite organizar los dispositivos en unidades organizativas (por ejemplo, departamento), y a los usuarios por grupos. Luego es posible definir perfiles (que incluyen políticas de uso, certificados, bookmarks, VPN, WiFi, etc) por unidad organizativa y por grupo de usuario. Esto brinda la flexibilidad de poder definir, por ejemplo, que ciertas restricciones se apliquen a los usuarios de comercial, que se encuentren en el grupo de usuarios atención al cliente. La organización de los grupos resulta un poco confusa al principio, pero luego del uso se va afinando.

La instalación remota de aplicaciones existe, pero no es del todo directa. Es posible distribuir tanto aplicaciones públicas, como adquiridas por la empresa (llámese APK). Es posible instalar las APK sin intervención del usuario, pero si es una aplicación de la Play Store, requerirá la intervención del usuario, algo para nada conveniente. Tal vez sea algo que me falló a mi, pero luego de varias pruebas, no logré que se instale algo directamente.

Dado que muchos dispositivos incluyen aplicaciones que tal vez no deseamos (Google trae algunas que en modo usuario son imposible desinstalar... llámese Gmail, G+, etc), es posible desinstalarlas/desactivarlas mediante AirWatch. Este es un punto muy a favor del software, dado que sin rootear el dispositivo no es posible eliminar ciertas aplicaciones. Además es posible restringir la instalación de aplicaciones y no permitir que el usuario desinstale las importantes. Esto se logra con los grupos de aplicaciones Blacklisted, Whitelisted y Required. Todas las listas se arman con los IDs de las aplicaciones. Cada aplicación tiene un ID único, como com.google.android.gm para GMail.
  • Blacklisted permite listar las aplicaciones explícitamente prohibidas. Si una aplicación está en esta lista, no se podrá instalar.
  • Whitelisted, si está activa, restringe que no se instale ninguna aplicación que no se encuentre en la lista.
  • Required no permite que el usuario desinstale ninguna de las aplicaciones listadas.
Me parece importante remarcar que las aplicaciones que vienen "de fábrica" como GMail, seguirán instaladas incluso si utilizamos la Whitelist y no la incluímos. La única forma que logré de remover estas aplicaciones es listándolas explícitamente en la Blacklist.
El único aspecto negativo que encontré en esta funcionalidad, es que el sistema permite al usuario llegar hasta el último paso de la instalación antes de decirle "está prohibido instalar la aplicación". Estaría bueno que no lo permitiera de entrada.

Otro aspecto que en nuestro caso era importante, es dónde está instalado el servidor. Para empezar, AirWatch vende el servicio en la nube, es decir, está el servidor instalado en algún lugar del ciberespacio, y nosotros lo administramos remotamente. Consultando con un agente oficial, me indicaron que también es posible instalar el sistema on-site, es decir, tener nuestro propio servidor AirWatch. El requerimiento para hacerlo es contratar por lo menos 100 licencias, donde las licencias son por dispositivos... para hacer una prueba inicial no resulta muy atractivo tener que contratar 100 licencias. Como dato extra, cada licencia cuesta entre 5 y 6 dólares mensuales. No estoy para nada a favor de colocar datos de la empresa en la nube, mucho menos información de dispositivos, que incluye localización, registro de llamadas, mensajes, etc, pero en este caso, no tuvimos opción.

Algo que todavía no mencioné es que la interfaz de administración es Web. La interfaz es, a mi gusto, poco intuitiva y confusa. No es fácil familiarizarse con ella, e incluso luego de utilizarla un par de semanas, a veces no encuentro las cosas. Tal vez sea una mera impresión mia, pero conversando con mis compañeros de trabajo, les dio la misma sensación. La primer gran confución es la diferencia entre los usuarios. Existen dos tipos de usuarios, los administradores, y los "dueños" de dispositivos. Los primeros tienen permiso de administrar la aplicación, y mediante roles se puede restringir lo que pueden hacer. Los segundos se utilizan para registrar equipos. Es decir, cuando damos de alta un equipo, éste debe pertenecer a algún usuario, por lo que antes habrá que dar de alta el usuario. Cada uno de estos usuarios puede tener asignado uno o más equipos.
Otra confusión es dónde estamos parados. Como cada dispositivo pertenece a una unidad organizativa, si estamos en una de ellas, no podremos ver los dispositivos en otras (salvo que estemos en la OU raíz, donde podemos ver todos). Lo mismo sucede con los usuarios.
Un problema que encontré aquí es mover dispositivos o usuarios entre unidades organizativas... simplemente, no pude. Si el usuario tiene asignado un dispositivo que se encuentra en una dada OU, no se puede mover el usuario, y lo mismo pasa con los dispositivos.
Más allá de ser confusa, tengo para decir a favor de la interfaz que genera interesantes gráficos. El dashboard es muy visual y La información sobre los dispositivos es muy completa.

Un aspecto muy negativo, es la falta de documentación. Googlear cómo hacer algo en AirWatch es prácticamente inútil. Sólo se encuentran broshures de propaganda. Incluso en la página de AirWatch no encontrás los manuales! Tienen una sección de whitepapers que no me resultó muy útil. Por suerte, nuestro proveedor de AirWatch en la nube brindó un buen soporte a nuestras consultas, y nos entregaron un manual oficial... aunque este manual oficial no era muy completo tampoco. En fin, punto negativo en cuanto a documentación.


Agente AirWatch

La administración de los dispositivos se logra instalando un agente AirWatch en cada uno de ellos. Este agente se instala desde la Play Store de Google (en el caso de Android), y se registra en el servidor utilizando una URL de enrollment (que no es la misma que la de administración), el ID de la unidad organizativa, y un usuario del tipo "dispositivo" (no uno de administración).

Para la instalación encuentro como punto negativo que no se provea una APK. El uso de la Play Store de Google fuerza registrar una cuenta Google. Para un dispositivo corporativo, por qué la empresa debería tener cuentas Google? Parte del monopolio encubierto de Google.

Una vez que se registra el dispositivo, se aplica la configuración indicada por el servidor, la cual incluye el perfil del usuario. Acá encontré otro problema. Si bien el agente provee una forma de forzar la sincronización, la aplicación del perfil no siempre funciona. Tuve muchísimos problemas creando bookmarks desde el servidor. A veces el agente los borra, no se actualizan...

Encontré riesgoso el echo de no poder prohibir la desactivación del agente. Si bien encontré la forma de que el usuario no desinstale el agente (Required list, descripta anteriormente), no encontré la forma de que el usuario no desactive el agente. Una vez que se desactiva el agente, el usuario sigue teniendo las restricciones, pero el servidor pierde el contacto con el dispositivo.


Conclusión

AirWatch es un muy buen comienzo en la administración centralizada de dispositivos móviles. Sin embargo, creo que odavía tienen mucho camino por delante. Tal vez dependa mucho de la evolución de los sistemas operativos como Android, que seguramente tomarán un approuch cada vez más empresarial, como BB.
No utilizaría AirWatch como reemplazo de BES. Si tienen dispositivos BB, debido al limitado soporte, recomiendo seguir utilizando BES por más feo que sea :P

Como puntos a favor encuentro que:

  •  Implementa las características más importantes de un MDM.
  •  Brinda muy buena información sobre los dispositivos.
  •  Permite una buena restricción de las aplicaciones instaladas y que no se pueden desinstalar.
  •  Soporte de múltiples sistemas operativos.
  •  Aplicación de políticas por grupos de usuarios y/o dispositivos. Facilidad de generar perfiles y aplicar uno o más a cada dispositivo.

En contra, encuentro que:

  • La interfaz web de administración no es muy intuitiva.
  • La documentación casi inexistente, ya que una vez que nos vamos adentrando en el software y queremos hilar más fino, no se encuentra información al respecto.
  • El soporte de Android es principalmente para equipos SAFE, y salvo iOS, las características disponibles para el resto de los SOs es muy limitada.
  • El agente falla cada tanto y no aplica correctamente los perfiles.
  • Se requieren demasiadas licencias (al menos 100) para poder instalar el servicio on-site.
Thunderbird/Icedove como cliente de Mails, Calendario y Libreta de direcciones de Exchange
El conjunto de herramientas de Exchange utilizado en entornos Windows, es muy importante en la mayoría de las empresas. Para tener una Workstation GNU/Linux totalmente funcional con respecto a sus pares Windows, necesitamos integrar tanto mails, como calendario y libreta de direcciones, provistos por Exchange.

Por suerte, existe una excelente herramienta denominada DavMail que nos facilita la vida. Esta herramienta actúa de proxy entre el cliente de mails que utilicemos (Thunderbird/Icedoe, Evolution, etc) y el servidor Exchange. Para ello, transforma protocolos estándar (IMAP, SMTP, LDAP, etc) en solicitudes WebDav (extensión del protocolo HTTP) reconocidas por el servicio OWA de Exchange.

A continuación explicaré cómo utilizar Thunderbird/Icedove como cliente de mails, calendario y libreta de direcciones provistos por Exchange, a través de DavMail. La explicación está basada en los tutoriales provistos en la propia página de DavMail: IMAP Thunderbird mail setup, Thunderbird calendar setup y Thunderbird directory setup. Además, la explicación está basada sobre debian GNU/Linux, pero la configuración es igual para otras distribuciones e incluso Windows.


Instalación y configuración de DavMail

Descargar DavMail desde su página en sourceforge. Dirigirse al directorio de instalación y ejecutar:
  #dpkg -i davmail.deb # ver nombre real del paquete descargado, o renombrarlo
  #apt-get -f install  # instala todas las dependencias necesarias para davmail

DavMail también está disponible para Windows y Mac, dado que está programado en Java.

Una vez instalado DavMail, debe ejecutarse. Lo recomendable es linkearlo para que se ejecute al inicio de sesión del usuario, así no tenemos que ejecutarlo a mano cada vez que queramos usarlo. En la primera ejecución hay que configurarlo para que apunte al servidor Exchange.
Los campos requeridos, como base, se encuentran en la pestaña Main, y son los siguientes:
  - Exchange Protocol: elegir EWS para Exchange 2010, o WebDav para Exchange 2007.
  - OWA (Exchange URL): la URL del servidor Exchange, por ejemplo: https://miserver.com/OWA
  - Elejir los puertos locales en los que DavMail debe esperar conexiones POP, IMAP, SMTP, Caldav y LDAP. El cliente que configuremos, se conectará a estos puertos. Pueden dejar los puertos default y desactivar alguno de los protocolos si no son necesarios (POP por ejemplo).


Configuración de la cuenta de mail en Thunderbird/Icedove

Los pasos para configurar la cuenta de dominio en el cliente Thunderbird, son los siguientes:
  1- Elegir Crear una nueva cuenta de e-mail. Dependiendo de si ya tienen configurada alguna cuenta o no, los pasos pueden variar un poco al principio.
      - Si no tienen una cuenta definida, el wizzard busca para crear una cuenta con alguno de sus partners. Si este es el caso, clickear el botón "Saltear esto y usar mi correo existente".
      - Si ya tienen otra cuenta en Thunderbird, ir a "Editar -> Configuración de Cuentas...", elegir "Acciones de cuenta -> Agregar una cuenta de correo".
  2- Completar el campo de Nombre y dirección de mail en la configuración de la cuenta. Aconsejo destildar la opción recordar contraseña. Dar continuar.

  3- Al dar continuar, Thunderbird fallará en la comprobación del dominio y les solicitará que ingresen los datos manualmente. En la configuración, utilizar los siguientes valores:
Entrante/Incoming:
IMAP (pueden elegir POP, pero IMAP es más completo)
Nombre del servidor: localhost
Puerto: el puerto que configuraron en DavMail. Por defecto es 1143.
SSL: Ninguno.
Autenticación: Contraseña normal.
Saliente/Outgoing:
Nombre del servidor: localhost
Puerto: el puerto que configuraron en DavMail para SMTP. Por defecto 1025.
SSL: Ninguno.
Autenticación: Contraseña normal.
  Nombre de usuario: su nombre de usuario en el dominio, agregando el nombre del dominio: DOMINIO\usuario

Tal vez DavMail indique que el servidor Exchange provee un certificado no confiable. Esto sucede si el servidor utiliza un certificado autofirmado, o firmado por una CA local. Dar aceptar.


Calendario

Para configurar el calendario, debemos instalar la extensión iceowl-extension (extensión Lightning):
  # apt-get install iceowl-extension

Luego, desde Thunderbird/Icedove abrimos el calendario "Events and Tasks -> Calendar", y realizamos los siguientes pasos:
  1- Click derecho en el panel izquierdo (deben tener el predefinido calendario "Home") y clickeamos "New Calendar".
  2- En la ventana que aparece, elegimos "On the Network", luego "Siguiente".

  3- En la siguiente opción elegimos "CalDAV" en el formato, y utilizamos la siguiente dirección para el "Location": http://localhost:1080/users/usuario@dominio.com/calendar, donde deberán reemplazar usuario@dominio.com por su usuario y dominio.

  4- Una vez que terminen, les solicitará un nombre de calendario, color, si desean recibir recordatorios. Configurar a gusto.
  5- Para finalizar, les solicitará las credenciales de dominio. Hay que colocarlas como en el caso de los mails, utilizando el formato DOMINIO\usuario para el nombre de usuario.


Libreta global de direcciones

La libreta global de direcciones de Exchange se habilita de la siguiente manera:

  1- Ir a "Herramientas -> Libreta de direcciones".
  2- En la ventana emergente, seleccionar "Archivo -> Nuevo -> Directorio LDAP".
  3- Abre una nueva ventana, donde se nos solicitan los siguientes datos:
      Nombre: el que ustedes elijan (ej: Exchange)
      Servidor: localhost
      DN base: ou=people
      Número de puerto: 1389 (ver la configuración de DavMail para saber qué puerto usar con LDAP, por defecto es 1389)
      DN para inicio de sesión: DOMINIO\usuario

Para que Icedove autocomplete con las direcciones de la libreta global, hay que ir a "Editar -> Preferencias -> solapa Redacción". Allí tildar la opción "Servidor de directorios" y elegir la libreta recién creada.

Cuando vayan a redactar un e-mail, Thunderbird/Icedove les solicitará la contraseña del usuario de dominio.
Ejecutar e Instalar Android en VirtualBox
El otro día leí el interesante artículo de linuxitoCómo instalar Android en una máquina virtual QEMU/KVM y me alentó a probarlo. Para hacerlo, preferí utilizar VirtualBox, ya que tengo todas mis máquinas virtuales ahí, y me pareció bueno publicar mi experiencia, como complemento a la de linuxito.

No conocía la versión x86 de Android. Hasta ahora había utilizado Android desde el SDK, mediante Android Virtual Devices (AVD). Este emulador es muy completo, pero también muy pesado, y la ejecución no es muy fluida que digamos (salvo que tengas una máquina muy potente). No me pasó lo mismo con la virtualización mediante VirtualBox.


Creación de la máquina virtual

Para empezar, descarguemos la última imagen de Android para x86 desde la página del proyecto. Algo a tener en cuenta es que esta versión de Android es para tablets, por lo que algunas aplicaciones para celulares como WhatsApp no funcionarán.

La máquina virtual que creemos en VirtualBox debe tener ciertas características, dado que Android aparentemente no trae todos los drivers y tiene requerimientos mínimos. Para la configuración base de la virtual, me basé en la información de Android x86 - VirtualBoxHowTo.
Utilicemos la siguiente definición:
- Tipo: Linux
- Versión: 2.6
- Disco: 10GB deberían ser suficientes.
- Memoria: 256MB como mínimo, 512MB recomendado. Yo le pondría 1GB para que funcione bien fluído.
- Memoria de video (Pantalla -> Vídeo): 8MB
- Controlador de audio (Audio): SoundBlaster 16
- Red: Utilizar NAT o bridge. En modo bridge es necesario un servidor DHCP.
    - Tipo de adaptador: PCnet-FAST III
- Montar la imagen ISO de Android en la lectora virtual (Almacenamiento -> Controller: IDE)
 
Ejecución de prueba

Al iniciar la máquina virtual, vemos que existen varias opciones de booteo. Si quieren hacer una prueba antes de instalar, pueden ejecutar Android en modo live (primer opción).

En modo live, solamente nos solicitará que configuremos el idioma, la red WiFi, y nos preguntará sobre la localización. Como estamos en una virtual, y sólo queremos probar el sistema, dar skip a la configuración del WiFi y no tildar ninguna de las opciones de localización.

El sistema inicia en cuestión de segundos y vemos el escritorio de Android. Acá me topé con un problema. Si están utilizando la integración del mouse de VirtualBox, probablemente les suceda que no ven el puntero dentro de la máquina virtual. Esto hace casi imposible su uso. Para solucionarlo, simplemente hay que deshabilitar la integración desde VirtualBox:
Máquina -> Inhabilitar integración del ratón (Ctrl + I)

Instalación de Android

Para instalar Android en el disco virtual, debemos iniciar desde el cd y realizar los siguientes pasos:
  1. Seleccionar el modo instalación en GRUB.
  2. Una vez que se carga el sistema de instalación, aparece el gestor de particiones.


  3. En el mismo seleccionar "Create/Modify partitions", con lo cual se abre cfdisk


  4. Aquí seleccionar New -> Primary y dejar el tamaño completo del disco. Cuando la partición aparece, marcarla como booteable (opción Bootable).


  5. Luego dar a la opción Write para que se guarden los cambios. Esta opción preguntará si estamos seguros de lo que vamos a hacer, pues decir que yes!
  6. Una vez terminado esto, seleccionar Quit para salir. Esto nos retorna a la pantalla anterior, en la cual ahora podemos seleccionar la partición para instalar el sistema.


  7. Seleccionarla y formatearla con ext3.


  8. Al formatear el sistema consultará de nuevo si estamos seguros de lo que deseamos hacer, responder nuevamente que yes!
  9. Luego se nos consulta si deseamos instalar grub como boot loader. Seleccionar que si.
  10. Para finalizar, el sistema nos pregunta si deseamos hacer que /system sea un directorio de lectura+escritura. Esto permitirá mejor debugging, pero ocupará más espacio y la instalación demorará más. Dar que si, tampoco es tanto lo que pesa (ni lo que tarda).
  11. Cuando termina la copia de archivos, seleccionar reiniciar para ejecutar el nuevo sistema.


Como podrán observar, la instalación completa no demora más de 10 minutos (en mi caso no demoró ni 5).


Primer ejecución

La primer ejecución solicitará que configuremos algunas cosas:
  1. Idioma: seleccionar el que más les guste.
  2. Configuración de WiFi: seleccionar skip, usaremos la conexión física.
  3. Cuenta de Google: sin una cuenta de Google configurada no se puede hacer mucho en Android, pero pueden pasar este paso sin configurar una.
  4. Enviar información de localización a Google: en este paso se nos consulta si deseamos información de localización "anonimamente" a Google. Al no tener GPS en la máquina virtual, no hace diferencia dejar tildadas o no las opciones.
  5. Nombre: la tablet necesita un nombre para personalizar aplicaciones. Pongan lo que gusten.

Configuraciones básicas

Al usar un rato Android en la virtual, encontré algunos problemas. El primero que encontré es que al abrir alguna aplicación, se rota la pantalla y no puedo retornar a la posición original. Como se imaginarán, usar el sistema rotado 90º no es nada cómodo! Esto se puede solucionar fácilmente deshabilitando el auto-rotate:
Aplicaciones -> Settings -> Accessibility -> Destildar Auto-rotate scree
Otro problema es que cuando se apaga la pantalla para ahorrar energía, no puedo recuperar el control. Para evitar esto deshabilité el modo sleep:
Aplicaciones -> Settings -> Display -> Sleep -> Never Timeout

Comentarios finales

Usar la versión de Android x86 en VirtualBox u otras máquinas virtuales es muy simple y anda mucho mejor que usar AVD. Sin embargo AVD es mucho más completo que esta versión, dado que trae múltiples versiones de Android para múltiples dispositivos.
Hay que tener en cuenta que si no configuran una cuenta Google, no podrán instalar nada... prácticas monopólicas? naaaa

Probar aplicaciones en el ambiente virtualizado es mucho mejor que andar instalando porquerías en una tablet o un celular directamente. Esto nos permitirá conocer Android más a fondo, dado que no tendremos miedo de romper un caro aparato. También nos servirá para testear como se ven y ejecutan aplicaciones web.

En resumen, jueguen con este Android, que para eso está :)
Monitoreo de ancho de banda en routers/switches/etc usando MRTG
Luego de tener algunos problemas de saturación de ancho de banda, me volqué a la búsqueda de una herramienta que pueda graficar el uso de los links.
Comencé la búsqueda con herramientas que puedan graficar datos almacenados en archivos pcap, creados con tcpdump o wireshark, para lo cual encontré tcptrace. Si bien tcptrace es una herramienta interesante, me resultó bastante anticuada para lo que yo necesitaba, que era una visualización simple del uso de los links.

Continuando la búsqueda, me orienté a herramientas que obtengan resultados por SNMP, en lugar de archivos pcap. De esta manera fui a dar con Multi Router Traffic Grapher (MRTG). Descubrí que esta herramienta es muy utilizada, e incluso en la propia página de Cisco proveen información sobre cómo usar MRTG (una búsqueda en google "mrtg site:www.cisco.com" mostrará muchos resultados).

Según la descripción en la página oficial:
MRTG monitorea dispositivos de red por SNMP y dibuja lindas imágenes mostrando cuánto tráfico ha pasado a través de cada interfaz.
Si bien la idea parece ser monitorear routers, la herramienta permite ir más allá y monitorear cualquier dispositivo de red que envíe información de uso de interfaces a través de SNMP. Y no sólo eso, también permite monitorear uso de CPU, disco y memoria.
MRTG está escrito en perl y funciona tanto en GNU/Linux como en Windows (además de NetWare... por si a alguien le interesa), y es libre, licenciado mediante GPL.

Si bien llevo un par de días probándolo, MRTG me parece la solución ideal para la tarea de monitoreo de links, y es un adicional muy interesante poder monitorear CPU, memoria y disco. Lo estoy probando con un switch Cisco Catalyst de más de 200 ports y va de lujo.
Este es un ejemplo de los gráficos que muestra:


Bueno, básta de cháchara y pasemos a lo importante, cómo instalar y configurarlo.


Instalación

La instalación es muy simple, dado que el paquete se encuentra en los repositorios de las distribuciones más importantes. Hay que tener en cuenta que se necesita tener un servidor web instalado, como ser Apache.

En debian, MRTG se instala simplemente ejecutando:
  # apt-get install mrtg

Mientras que en derivados de Red Hat (CentOS, Fedora) es:
  # yum -y install mrtg

La instalación crea un archivo de configuración básico que no tiene prácticamente nada. En debian el archivo de configuración es /etc/mrtg.cfg, mientras que en derivados Red Hat es /etc/mrtg/mrtg.cfg. Además se crea un archivo cron en /etc/cron.d/mrtg.
El resto de la explicación la haré basándome en debian, que es donde lo probé, pero para los derivados de Red Hat sólo cambian los paths a los archivos.

En debian hay que crear el directorio que hospede los archivos web. Dependiendo de su configuración del servidor web, el path puede variar, pero por defecto, el directorio se crearía en /var/www:
  # mkdir /var/www/mrtg

Cambiamos el grupo owner para que Apache tenga más permisos sobre los archivos:
  # chown root:www-data /var/www/mrtg


Configuración

La configuración básica de MRTG es muy simple. La forma más rápida y fácil de tener una configuración que realice pull de un dispositivo para ver el uso de ancho de banda, es usando la herramienta cfgmaker (instalada por el paquete mrtg) de la siguiente manera:
  # cfgmaker --global 'WorkDir: /var/www/mrtg' --output /etc/mrtg.cfg public@192.168.1.10
donde:
--global 'WorkDir: /var/www/mrtg' especifica el directorio donde se pondrán los datos recaudados, es decir, el del server web,
--output /etc/mrtg.cfg especifica el archivo de configuración a crear,
public@192.168.1.10 indica que se use la comunidad SNMP "public" y que la IP del dispositivo es 192.168.1.10.
La comunidad "public" es la default en muchos dispositivos y por seguridad debe cambiarse, dado que es la "contraseña" de acceso a los datos SNMP. Obviamente el dispositivo que estemos consultando debe tener habilitadas las consultas SNMP con la comunidad utilizada.

cfgmaker generará un nuevo archivo mrtg.cfg que contiene configuraciones globales, así como definiciones para cada interfaz que el dispositivo reporte en el pull SNMP. Lo más destacable de la configuración global es la sentencia "WorkDir:" que especifica el directorio pasado por parámetro.

El siguiente paso es generar los archivos web para la configuración recién creada. Para ello, se utiliza la herramienta indexmaker, que también viene con mrtg. La generación de dichos archivos se realiza de la siguiente manera:
# indexmaker /etc/mrtg.cfg --output /var/www/mrtg/index.html
donde:
/etc/mrtg.cfg es el archivo de configuración,
--output /var/www/mrtg/index.html es la ubicación y nombre del archivo index principal.

Ejecución de MRTG

Con todo en su lugar, ahora debemos ejecutar mrtg. La instalación genera un archivo cron que ejecutará MRTG cada 5 minutos. Cada vez que se ejecuta, obtiene los valores de las interfaces para los dispositivos configurados, los almacena en su base de datos RRD, y crea los gráficos.

Para ver si todo está bien, lo mejor es ejecutar al menos una vez el programa por consola, de la siguiente manera:
# env LANG=C /usr/bin/mrtg
env LANG=C se utiliza para setear la variable de entorno LANG, dado que si utilizan otro valor como UTF-8, arrojará un error.

La primera vez que ejecuten mrtg arrojará varios errores del tipo "no encuentro tal archivo". Esto es normal, dado que los archivos que busca todavía no existen y se crean con la primer ejecución. Ejecuciones sucesivas no deberían arrojar estos errores.

Una vez que se prueba que todo está bien, ya no hace falta ejecutarlo a mano, dado que de eso se encargará cron.

Acceder a las gráficas es tan simple como apuntar con el navegador a la dirección del servidor donde se encuentra instalado MRTG. Por ejemplo:
http://192.168.1.100/mrtg

Configuración avanzada

Vimos como realizar una configuración de forma casi automática. Ahora, dependiendo lo que deseen monitorear y cómo, deberán editar el archivo de configuración creado con cfgmaker, o bien crearlo de cero.
Para esto hace falta conocer un poco más la estructura del archivo de configuración. El mismo se divide básicamente en tres secciones: opciones globales,  configuración de targets y definición de thresholds. Listaré las opciones que me parecen más importantes de cada una, para poder tunear la herramienta un poco.
Es interesante tener en cuenta que se pueden incluir otros archivos de configuración en el de la configuración global, utilizando el keyword "Include". Por ejemplo: Inlude: switches.inc.


Global

Entre las opciones globales, destaco:
  • WorkDir: establece el directorio de trabajo, donde se ubican los archivos de log y web. En el ejemplo básico, el directorio se estableció a /var/www/mrtg, pero se puede cambiar al que se desee.
    Es posible cambiar el directorio donde se ubican los html (HtmlDir), logs (LogDir) e imagenes (ImageDir). Si se utilizan estas opciones, no debe establecerse el WorkDir, dado que sobreescribe estas opciones.
  • Forks: permite definir cuántos procesos disparar para realizar consultas SNMP. Si se tienen que consultar muchos dispositivos, utilizar más de un proceso a la vez puede optimizar considerablemente la tarea.
  • Interval: tiempo, en minutos, que transcurre entre ejecuciones de mrtg (por defecto es 5 minutos). Esto se refleja en los gráficos web, y se utilizar en modo daemon.
  • Language: permite setear el lenguaje en el cual se muestran los datos web. MTRG soporta múltiples lenguajes, y tranquilamente podríamos elegir "spanish" como valor.
  • RunAsDaemon: muy interesante opción que permite independizarnos de cron y optimizar la ejeción. Si se setea en yes, no hace falta llamar el programa mrtg desde cron cada cierto intervalo de tiempo, sino que el programa se ejecuta una vez y luego queda en ejecución, realizando actualizaciones al intervalo seteado.
    En este caso es importante setear la opción "Interval" citada anteriormente, y eliminar la entrada de cron, dado que cada ejecución de mrtg iniciará un demonio nuevo.
    Esta opción debería utilizarse siempre, dado que ejecutar el programa con cron conlleva la creación del proceso y tener que releer los archivos de configuración cada vez.
Ejemplo de configuración global:
    WorkDir: /var/www/mrtg
    Forks: 3
    Language: spanish
    RunAsDaemon: yes
    Interval: 5


Targets

La definición de targets tiene una cantidad de opciones abrumadora, por lo que listaré algunas que me parecen las principales. Cada target debe tener un nombre único, y el nombre debe agregarse a cada parámetro que pertenezca al mismo target (entre corchetes). Este nombre se usa también para el nombre de los archivos web, log e imágenes.
  • Target: es la principal sentencia al definir un dispositivo a monitorear. Acepta muchos formatos (y cuando digo muchos, es MUCHOS) para definir el target. Las formas más comunes son las siguientes:
    • Basica: "puerto:comunidad@router"
      donde:
      - puerto: es el número de la interfaz en el router a monitorear. La documentación no dice mucho al respecto, pero al menos en los Cisco, los puertos se numeran de forma consecutiva desde la primer placa, y arrancan desde el valor 2. Por ejemplo, la Fa0/37 pasa a ser el puerto 38, mientras que la Gi1/1 es el puerto 50 (es la interfaz 49 - por los 48 de la primer placa-, más 1 porque arranca en 2 la numeración).
      - comunidad: es la comunidad SNMP que asignaron en el dispositivo.
      - router: es el nombre DNS o la dirección IP del router/switch/etc a monitorear.
      Ejemplo: definición para graficar la interfaz 38 de un switch 3560.
              Target[switch3560_2]: 39:public@192.168.1.10
    • OIDs explícitos: "OID_1&OID_2:comunidad@router". Los OIDs son los identificadores SNMP que determinan los valores a obtener. Los OIDs están en cierta forma estandarizados, pero cada fabricante puede definir los que quiera. MTRG necesita al menos dos OIDs para realizar sus gráficos (uno lo dibuja en verde y el otro en azul). Esto no necesariamente necesita tener dos OIDs distintos, tranquilamente se puede especificar el mismo OID dos veces.
      Ejemplo: graficar el uso de CPU.
       Target[switch3560_1]: 1.3.6.1.4.1.9.2.1.57.0&1.3.6.1.4.1.9.2.1.57.0:public@192.168.1.10
    Hay muchas otras formas de definir targets, así que si necesitan otra, busquen en el manual que están bien descriptas.
  • MaxBytes: especifica los valores máximos que cualquiera de los dos valores medidos puede tomar. En el caso de interfaces, los tamaños máximos serían la velocidad soportada. Tener en cuenta que el valor es en bytes, no bits se especifica en las interfaces: 100 MB Ethernet = 12500000.
    Ejemplo:
     MaxBytes[switch3560_2]: 12500000
  • Title: el string que se muestra en la barra del título de la página Web.
    Ejemplo:
     Title[switch3560_2]: Analisis de trafico Switch 3560
  • PageTop: texto a agregar al tope de la página HTML definida para el target. Hay que tener en cuenta que se pueden usar varias líneas, siempre que la primer columna esté vacío.
    Ejemplo:
      PageTop[switch3560]: <h1>Analisis de trafico Switch 3560</h1>
    <div id="sysdetails">
    <table>
    <tr>
    <td>System:</td>
    <td>Switch 3560 in </td>
    </tr>
    <tr>
    <td>Max Speed:</td>
    <td>125.0 MBytes/s</td>
    </tr>
    </table>
    </div>
  • Directory: si se especifica, los archivos web, para ese target, se ubicarán allí en lugar del WorkDir (o HtmlDir, LogDir, ImageDir). El directorio debe ser creado manualmente, dado que mrtg no lo creará.
    Ejemplo: colocar los archivos del switch3560 en el directorio /var/www/mrtg/switches
     Directory[switch3560]: /var/www/mrtg/switches
  • XSize e YSize: permiten especificar el tamaño del gráfico. Por defecto, los gráficos son de 400x100 pixels. Xsize debe estar comprendido entre 20 y 600, mientras que YSize debe ser mayor a 20.
    Ejemplo:
     XSize[switch3560_2]: 600
     YSize[switch3560_2]: 150
  • XZoom e YZoom: permiten hacer zoom en el gráfico.
    Ejemplo:
     XZoom[switch3560_2]: 2.0
     YSize[switch3560_2]: 2.0
  • Options: permite setear algunos valores booleanos. Por ejemplo, por defecto los gráficos son en bytes y el tiempo se grafica de derecha a izquierda. Es posible cambiar este valor a algo más intuitivo, como valores en bits y que el gráfico crezca de izquierda a derecha:
    Options[switch3560]: growright, bits
    Existen muchas otras opciones para setear por gráfico, y se pueden encontrar en la documentación.
Un dato interesante es que, dado que muchas definiciones de targets comparten la misma configuración, o configuraciones similares, mtrg permite utilizar valores default. Los datos default se configuran de la misma manera que se especifico para los targets, pero usando los caracteres _ ^ y $
En todos los casos, un valor en blanco, borra la configuración default. Cada una de las configuraciones default pueden ser sobre-escritas más abajo, con otra configuración default. Esto permite usar valores default distintos para distintos targets.
Veamos las opciones de configuración:
  • Valores default se especifican con el underscore "_". Las definiciones en targets sobreescriben este valor.
    Ejemplo: Especificar que todos los gráficos sean en bps, y crezcan hacia la derecha
          Options[_]: growright, bits
  • El signo "^" permite pre-agregar texto a valores definidos en los targets.
    Ejemplo: poner en el título de todos los targets el valor "Analisis MRTG -"
          Title[^]: Analisis MRTG -
    Ahora, si por ejemplo se define el target switch3560:
          Title[switch3560_2]: Switch 3560 Fa0/2
        El resultado será una página con el título "Analisis MRTG - Switch 3560 Fa0/2".
  • Finalmente, el signo peso "$" permite agregar texto al final de valores definidos en los targets.
    Ejemplo: agregar el texto "- Laboratorio" a todos los títulos.
          Title[$]: - Laboratorio

Ejemplo completo de configuración de Target (interfaz FastEthernet0/1 en switch 3560):
Options[_]: growright, bits
XSize[_]: 600
YSize[_]: 150
XZoom[_]: 2.0
YSize[_]: 2.0
Title[^]: Analisis MRTG -
Target[switch3560_2]: 39:public@192.168.1.10
MaxBytes[switch3560_2]: 12500000
Title[switch3560_2]: Switch 3560 Fa0/2
PageTop[switch3560]: <h1>Analisis de trafico Switch 3560</h1>
      <div id="sysdetails">
     <table>
     <tr>
     <td>System:</td>
     <td>Switch 3560 in </td>
     </tr>
     <tr>
     <td>Max Speed:</td>
     <td>125.0 MBytes/s</td>
     </tr>
     </table>
      </div>

Thresholds

La definición de thresholds permite realizar alguna acción cuando los valores sobrepasen un límite pre-establecido. Las acciones posibles son llamar un script externo o mandar un mail. Si se define llamar a un script externo, puede utilizarse la variable SetEnv para enviar parámetros extra.

Como ejemplo de uso de thresholds, veamos la configuración para mandar un mail cuando la interfaz 2 del switch 3560 supera los 90Mb/s:
# Directorio donde colocar los valores de threshold almacenados
ThreshDir: /var/www/mrtg/thresh
# Servidor de mail a utilizar
ThreshMailServer: mail.midominio.com
# Dirección a poner en el from del mail
ThreshMailSender: mtrg@midominio.com
# Definir a quienes mandar e-mail cuando se supere un límite. Se puede definir por host
ThreshMailAddress[_]: admin@midominio.com
# Definicion de limite maximo de uso de una interfaz (90Mb/s = 11.25MB/s = 11796480 Bytes/s)
ThreshMaxI[switch3560_2]: 11796480
Tener en cuenta el uso de "ThreshDir", dado que sin él, mrtg no tiene donde almacenar los datos de mediciones de límites, causando que cada detección sea independiente y mandando muchos mails. Es decir, estamos interesados que nos informe si superamos los 90Mb/s una vez, y hasta que no baje de 90Mb/s, no vuelva a mandar otro mail.


Monitoreo Cisco

Para poder monitorear dispositivos Cisco, primero hay que habilitar una comunidad SNMP para ser accedida en modo lectura. El nombre de la comunidad es el "password" para acceder a la información, por lo que debe mantenerse secreta.
Adicionalmente se puede setear una access-list que brinde acceso al servidor SNMP sólo a la IP elegida.
La configuración es la siguiente:
  (config)# snmp-server community ro 50  (config)# access-list 50 permit

Referencias

- MRTG 2.17.4 configuration reference
- MRTG (Multi Router Traffic Grapher) en Debian-Ubuntu
- Network Monitoring Using Free Linux Tools
- MRTG Configuration in Debian
- Quick HOWTO : Ch23 : Advanced MRTG for Linux
- Use MRTG to monitor bandwidth
- Cisco Task 3--Using MRTG to Monitor and Graph Traffic Loads
Cargar scripts JavaScript una sola vez + llamar función cuando la carga termina
Programando interfaces con JavaScript me topé con un problema al que no encontré una solución concreta. Cuando tenemos una página dinámica que carga scripts JS usando AJAX a medida que los va necesitando, podemos caer en el problema de cargar el mismo script más de una vez. Esto se debe a que de antemano no sabemos si el script se cargó o no y lo necesitamos para cumplir alguna función. Un ejemplo rápido de ver es el caso de asignar un evento a un componente. Supongamos que tenemos una página con el siguiente componente: <DIV ID="contenedor">contenido</DIV> y tenemos una sección que cambia según el accionar del usuario, pero carga un script jQuery de la siguiente forma:
$.getScript('/js/bind.js');
cuyo contenido es el siguiente:
$('#contenedor').click(function(event){ $("#contenedor").append("hola"); });
Si llamamos la misma sección más de una vez, lo que sucederá es que el evento click se enlaza más de una vez al componente "contenedor", haciendo que la palabra "hola" se agregue varias veces, en lugar de una sola vez como se esperaría. Van entendiendo por dónde va el problema? De alguna forma, la sección que carga el script debería saber que el script ya se cargó y no debería cargarlo de nuevo. El tema es cómo saber esto... En internet encontré algunas alternativas (sobre todo en StackOverflow) que explican cómo escapar este problema, pero al parecer ni JavaScript, ni jQuery implementan una solución directa, el programador debe encargarse de diseñar una función a tal fin. Otro problema con el que me topé relacionado a esto es cómo saber en qué momento se terminaron de cargar varios scripts. Si usas jQuery, ellos recomiendan usar la función $(document).ready() para esperar a que la página se cargue. La realidad es que cuando se cargan scripts con $.getScript, el evento ready no espera a que estos scripts se carguen. No obstante $.getScript permite definir una función como parámetro que será llamada cuando el script se termine de cargar... pero y si queremos esperar a que un conjunto de scripts se carguen? Para matar dos pájaros de un tiro (los problemas citados), diseñé una función jQuery denominada load_script, la cual decidí compartir con el mundo porque ninguna de las soluciones que encontré me pareció completa. Esta función está basada en distintas propuestas de distintos usuarios de StackOverflow. La función utiliza dos variables globales: loaded_scripts y loading_scripts. loaded_scripts mantiene la lista de scripts que ya se cargaron, así no se los vuelve a cargar nuevamente, mientras que loading_scripts mantiene la lista de scripts que se están cargando actualmente, para saber en qué momento se terminó de cargar todo. Los parámetros de la función son: script_list y callback. script_list es un arreglo con la lista de scripts que se deben cargar y por los cuales debe esperarse a que carguen, mientras que callback es una función definida por el programador que se llamará cuando todos los scripts se terminen de cargar.
/**
 * Load the given JavaScript scripts and call the callback function when all of them are fully loaded.
 * Each script is loaded only once, meanning that if this function is called two times with the same script name
 * it will be loaded the first time. This avoids problems like redeclared functions or variables, event binded more than
 * once, and every other error produced by a script loaded multiple times.
 * The function uses two global array variables:
 *  loaded_scripts: scripts that has been already loaded. Used to know which scripts should not be loaded again.
 *  loaded_scripts: scripts that are in loading process. Used to know when the loading process is done.
 * 
 * @param script_list array containing the scripts links to load. Ex: ['/js/load_this.js', '/js/binder.js']
 * @param callback the function to call when loading of the scripts is done.
 */
var loaded_scripts = Array();
var loading_scripts = Array();
jQuery.fn.load_scripts = function(script_list, callback)
{
  var script;
  
  //check for already loaded scripts and so they're not loaded again
  for(s in script_list)
  {
    if(loaded_scripts.indexOf(script_list[s]) == -1)
      loading_scripts.push(script_list[s]);
  }
  
  //if all the requested scripts are already loaded, callback and return
  if(loading_scripts.length == 0)
  {
    callback();
    return;
  }
  
  for(s in loading_scripts)
  {
    script = loading_scripts[s];
    $.getScript(script,  function() {
      //when script is loaded, remove it from the loading scripts array.
      //if it's the last script on the array, it means we're done loading, so call the callback function.
      loading_scripts.splice(loading_scripts.indexOf(script), 1);
      loaded_scripts.push(script);
      if((loading_scripts.length == 0) && (callback !== undefined))
 callback();
    });
  }
}
Un ejemplo de uso es el siguiente:
$(window).load_scripts(['/js/load_this.js', '/js/binder.js'], function() {
    $('#contenedor').click(function(event){
        $("#contenedor").append("hola");
    });
});
Espero que la función les sirva, al menos como ejemplo, ya que por lo que vi es un problema recurrente en los foros. Si encuentran algún error en el código, me avisan en los comentarios ;)