Mostrando entradas con la etiqueta GNU/Linux. Mostrar todas las entradas
Mostrando entradas con la etiqueta GNU/Linux. Mostrar todas las entradas
Configurar slaves OpenLDAP para aplicar lock de usuarios por logins fallidos (ppolicy)
Quienes utilicen LDAP para autenticación de servidores/workstations, seguramente se han topado o se toparan con el overlay ppolicy, el cual permite configurar policies de password como largo mínimo, complegidad, history, lock por cantidad de intentos, etc. Cómo habilitar y configurar ppolicy está bastante bien explicado en diversos sites como este, por lo que no lo incluiré acá. El problema es que ninguno explica bien qué hacer si tenes servidores slave que se utilizan para autenticación.

Cuando tenés una configuración master -> slaves, los slaves son read-only, por lo que no guardarán ningún atributo por si mismos, sino que replican lo que tiene el master. Esto es, si por ejemplo están utilizando un slave como ldap server, varios intentos fallidos de login nunca bloquearán la cuenta, porque el tipo no guardará el atributo pwdAccountLockedTime en ningún lado. Esto es lo mismo que sucede cuando intentan hacer un change password y están usando un slave, el pass no se puede cambiar.

Para solucionar este problema, OpenLDAP provee la alternativa de que los slave redirijan los updates al master. Esto es, si alguien quiere actualizar un valor en el slave, el slave redirigirá el update al ldap master, y lo obtendrá por replicación. La solución comprende utilizar updateref, enconjunto con el overlay chain y la opción ppolicy_forward_updates, donde:
  • updateref "<master ldap server>" indica a qué servidor LDAP enviar los updates (se utiliza sólo en slaves). Esta opción por sí sola retorna al cliente la URL del master ldap, y es el cliente quien se debe encargar de tomar esa URL y hacer el update allí.
  • El overlay chain facilita lo anterior, haciendo que el update lo haga el mismo slave, en lugar de retornar la URL del master al cliente. Con chain podemos configurar que si alguna acción dispara un update, el slave se conecte al master y lo aplique. Para ello, hay que configurar un usuario de binding que en el master tenga permisos de escritura para los atributos que deberá actualizar. Este overlay también se usa para resolver DNs que no están replicados en el slave, ya que sin él, OpenLDAP retornará un redirect que el cliente final deberá seguir.
  • ppolicy_forward_updates es la opción del overlay ppolicy que le indica que debe forwardear los password failures, ya que sino asume que es un master y no dispara el hook de redirect.

Veamos todo junto en un ejemplo, donde el ldap master se llama masterserver.dvpem.org. Esta config es para el slave y va en slapd.conf. Incluí sólo las líneas relevantes de la configuración, no es una configuración slapd.conf completa.

IMPORTANTE:
  • La configuración del overlay chain debe ir lo más arriba posible, antes de la configuración de cualquier base de datos y de la configuración de replicación.
  • updateref debe ir luego de la configuración de replicación (syncrelp).
  • El usuario que utilicen para el overlay chain debe tener permiso manage sobre los atributos de password. Por ejemplo, este es el permiso necesario para un user SlaveUpdater:
    {0}to dn.subtree="ou=people,dc=dvpem,dc=org" attrs=pwdChangedTime,pwdAccountLockedTime,pwdFailureTime,pwdHistory,pwdGraceUseTime,pwdReset by dn.base="cn=SlaveUpdater,dc=dvpem,dc=org" manage by * +0 break
...
#importamos el módulo que contiene el overlay chain
moduleload back_ldap.la

#cargamos el overlay
overlay chain
#definimos cuál es la URL del master y con qué usuario bindear. Recuerden que el user debe tener permiso manage.
chain-uri "ldap://masterserver.dvpem.org"
chain-idassert-bind     bindmethod="simple"
                        binddn="cn=SlaveUpdater,dc=dvpem,dc=org"
                        credentials="elpassdeSlaveUpdater"
                        mode="self"
                        #starttls=yes        #necesario si usamos ldaps como protocolo
                        #tls_reqcert=allow   #necesario si usamos ldaps como protocolo
chain-return-error TRUE

...
...

#cargamos el overlay ppolicy
moduleload ppolicy.la
overlay ppolicy

#indicamos dónde está la pólicy default de password (largo, cantidad de intentos, etc). Misma config que en el master.
ppolicy_default "cn=default,ou=Policies,dc=dvpem,dc=org"

#indicamos que se deben forwardear los updates al master
ppolicy_forward_updates

...
...

#configuración estándar syncrelp
syncrelp rid=001
    provider=ldap://masterserver.dvpem.org
    type=refreshAndPersist
    interval=00:00:02:00
    retry="30 10 120 +"
    searchbase="dc=dvpem,dc=org"
    attrs="*,+"
    bindmethod=simple
    binddn="cn=replicator,dc=dvpem,dc=org"
    credentials=elpassdelreplicator
    tls_reqcert=allow

#especificamos a dónde redirigir los updates
updateref "ldap://masterserver.dvpem.org"

Si tienen configurado el slave para utilizar la base cn=config, deberán ejecutar el diguiente ldif (aquí lo llamo enable-ppolicy-forward.ldif):
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: back_ldap

dn: olcOverlay={0}chain,olcDatabase={-1}frontend,cn=config
changetype: add
objectClass: olcOverlayConfig
objectClass: olcChainConfig
olcOverlay: {0}chain
olcChainCacheURI: FALSE
olcChainMaxReferralDepth: 1
olcChainReturnError: TRUE

dn: olcDatabase=ldap,olcOverlay={0}chain,olcDatabase={-1}frontend,cn=config
changetype: add
objectClass: olcLDAPConfig
objectClass: olcChainDatabase
olcDatabase: ldap
olcDbURI: "ldaps://masterserver.dvpem.org"
olcDbStartTLS: none  starttls=no
olcDbIDAssertBind: mode=self
  flags=prescriptive,proxy-authz-non-critical 
  bindmethod=simple
  timeout=0
  network-timeout=0
  binddn="cn=SlaveUpdater,dc=dvpem,dc=org"
  credentials="elpassdeSlaveUpdater"
  keepalive=0:0:0
  starttls=yes
  tls_cert="/etc/ldap/ssl/certificado.pem"
  tls_key="/etc/ldap/ssl/certificado.pem"
  tls_cacert="/etc/ldap/ssl/certificado.pem"
  tls_reqcert=allow
  tls_cipher_suite=NORMAL
olcDbRebindAsUser: FALSE
olcDbChaseReferrals: TRUE
olcDbTFSupport: no
olcDbProxyWhoAmI: FALSE
olcDbProtocolVersion: 3
olcDbSingleConn: FALSE
olcDbCancel: abandon
olcDbUseTemporaryConn: FALSE
olcDbConnectionPoolMax: 16
olcDbSessionTrackingRequest: FALSE
olcDbNoRefs: FALSE
olcDbNoUndefFilter: FALSE

dn: olcDatabase={1}hdb,cn=config
changetype: modify
add: olcUpdateRef
olcUpdateRef: ldaps://masterserver.dvpem.org

dn: olcOverlay={0}ppolicy,olcDatabase={1}hdb,cn=config
changetype: modify
replace: olcPPolicyForwardUpdates
olcPPolicyForwardUpdates: TRUE

Ejecutamos el ldif con ldapmodify (cambien el usuario admin por el que corresponda a ustedes):
ldapmodify -D "cn=admin,cn=config" -W -f enable-ppolicy-forward.ldif

Como siempre, espero que les haya resultado útil. Yo perdí un buen rato hasta entender cómo funciona esta lógica.
Reverse Proxy con Apache en 4 pasos
Los reverse proxy son muy útiles para poder proteger nuestros servers, ya que podemos colocar el server que realiza el procesamiento en la red interna y publicar todo a través del proxy, el cual puede filtrar y actuar de application firewall, balancear carga, etc. La idea del post no es explicar qué es ni qué ventajas tiene un Reverse Proxy, sino cómo crear uno usando apache. Para entender qué son, pueden arrancar por la wiki.
Existen módulos para Apache que nos permiten convertirlo en un Reverse Proxy, denominados mod_proxy_*. Los que interesan para esta explicación son mod_proxy y mod_proxy_http.

Supongamos que tenemos la siguiente configuración:

Internet ----> | www.dvpem.org / proxy.dvpem.org |<---> | background-man1.dvpem.org |

Donde www.dvpem.org tiene IP pública accesible desde Internet y es atendida por el server proxy.dvpem.org, y background-man1.dvpem.org tiene una IP privada. El web server background-man1 es el encargado de procesar todos los pedidos, pero no queremos exponerlo, por lo que levantamos un Reverse Proxy (proxy.dvpem.org), que es quien atiende los request a la página www.dvpem.org y los reenvía a background-man1 para su procesamiento. Una vez que background-man1 termina, retorna los resultados a proxy.dvpem.org que es quien responde finalmente al cliente.

Para lograr esto, sólo necesitamos realizar los siguientes 4 pasos:

1. Instalar apache.
2. Habilitar mod_proxy y mod_proxy_http:
    a2enmod proxy proxy_http
3. Crear un Virtual Host que atienda los pedidos www.dvpem.org y los reenvíe a background-man1:
    <VirtualHost *:80>
        ServerName   www.dvpem.org:80
        ServerAlias  www.dvpem.org
       
        Alias /about.html /var/www/about.html   #about.html lo procesa el proxy
        ProxyPassMatch ^/about.html !           #Indicamos que no proxee los requests del file about.html
       
        ProxyPass / http://background-man1.dvpem.org/           #Mapeamos los request www.dvpem.org para que vayan a background-man1
        ProxyPassReverse / http://background-man1.dvpem.org/    #Reescribe los headers retornados por background-man1 (ej: Location, Content-Location, URI) para que hagan referencia a www.dvpem.org
    </VirtualHost>
En la configuración agregué una yapa, y es que los request de about.html sean retornados por el mismo proxy, utilizando el file que está en su filesystem local. Esto es, no irá a background-man1, sino que lo retornará de un file en el mismo server. Esto puede ser muy útil si queremos que además de proxy sirva algunas cosas.
4. Reloadear la configuración de apache:
    service apache2 reload
   
El módulo es muchísimo más polenta que esto, expliqué un uso muy básico. Algo interesante es que podríamos resolver diferentes paths a diferentes servers, como por ejemplo usando:
    ProxyPass /main http://background-man1.dvpem.org/      
    ProxyPassReverse /main http://background-man1.dvpem.org/
   
    ProxyPass /images http://images.dvpem.org/
    ProxyPassReverse /images http://images.dvpem.org/
   
Pueden leer más sobre mod_proxy en su página oficial.
Obtener SSL/TLS Ciphers Soportados
Ufff casi un año sin postear nada, desde que cambié de trabajo estoy extremadamente ocupado y no he tenido tiempo para postear, a pesar de que estuve viendo muchas cosas interesntes. Espero poder retomar un ritmo de post más seguido :)

Con el auge de las vulnerabilidades en TLS/SSL este último tiempo, tuvimos que ir ajustando el listado de ciphers varias veces, ya que los requerimientos son cada vez más exigentes. El problema es la compatibilidad con sistemas operativos/browsers más antiguos, que no soportan las versiones más nuevas de TLS (TLS 1.2) o ciphers más seguros.

Hoy les traigo algo que me sirvió mucho, que es listar los ciphers soportados por un servidor usando un simple script en bash que se basa en openssl. Si bien hay varias tools que hacen esta tarea, siendo la que más uso TestSSLServer, quería algo que pudiera ejecutar desde cualquier lugar, sin depender de tools externas o la instalación de java. OpensSSL está presente en toda las distribuciones, así que no necesitamos nada extra para correr este script.

El core del script lo encontré en este post de superuser, al cual le hice modificaciones para que OpenSSL use SNI, tenga un check básico de parámetros, permita pasar port por parámetro y reporte sólo los ciphers con resultado positivo. Sería un equivalente de TestSSLServer más básico, pero portable :D

#!/bin/bash -e

if [ "$1" == "" ]; then
    echo "usage: $0  [port]"
    exit
fi

if [ "$2" == "" ]; then
    PORT=443
else
    PORT=$2
fi

# OpenSSL requires the port number.
SERVER=$1:$PORT
DELAY=1
ciphers=$(openssl ciphers 'ALL:eNULL' | sed -e 's/:/ /g')

echo -n "Checking if server is up... "
result=$(echo -n | openssl s_client -connect $SERVER 2>&1)
if [[ "$result" =~ "Connection timed out" ]]; then
    echo "FAIL - connection time out"
    exit 1
fi
echo "OK"

echo "Obtaining cipher list from $(openssl version)."
for cipher in ${ciphers[@]}; do
    result=$(echo -n | openssl s_client -cipher "$cipher" -servername $SERVER -connect $SERVER 2>&1 || echo "")
    if [[ "$result" =~ "Cipher is ${cipher}" || "$result" =~ "Cipher    :" ]] ; then
        echo $cipher
    fi
    sleep $DELAY
done
Ejecutar como servicio un programa que no es demonizable
Hoy estuve lidiando con una aplicación que se ejecuta desde consola y queda escuchando en un puerto, pero que no provee la posibilidad de correr como demonio (tipo Apache, sshd, etc). Para no tener que loguear un usuario y dejar la aplicación en ejecución en alguna consola colgada, mejor es convertirla en un servicio. Mi caso en particular se dió con la aplicación CherryMusic, que permite compartir musica a través de una interfaz web.

Como primer paso, vamos a crear un directorio donde alojar la aplicación, y para un caso como el que describo, creo que el mejor lugar es /opt:
# mkdir /opt/cherrymusic
Para cherrymusic, si hacen un clone del proyecto, el directorio se crea sólo, lo mismo si descomprimen un tar.gz.

A continuación creemos el usuario con el que se ejecutará la aplicación:
# useradd cherrymusic -d /opt/cherrymusic -s /bin/false
El comando anterior indica que el home del usuario será /opt/cherrymusic y que utilice /bin/false como shell... es decir, que no tenga shell.

Para ver qué sucede con nuestra aplicación, estaría bueno ver algún log, así que creemos uno, con los permisos necesarios para que la aplicación pueda escribir:
# touch /var/log/cherrymusic
# chown cherrymusic /var/log/cherrymusic
La ejecución del programa la haremos de la siguiente forma:
# sudo -u cherrymusic -H /usr/bin/python /opt/cherrymusic/cherrymusic --port 8080 &>>/var/log/cherrymusic
Esto es, le decimos que ejecute la aplicación con el usuario cherrymusic (-u), usando el home de dicho usuario (-H), y redirigimos la salida a /var/log/cherrymusic

Como último paso, creamos un init script. Si usamos el viejo estándar, podemos meter un script como el siguiente en /etc/init.d/cherrymusic
#!/bin/bash
### BEGIN INIT INFO
# Provides:          cherrymusic
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
### END INIT INFO
case "$1" in
  start)
    iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
    sudo -u cherrymusic -H /usr/bin/python /opt/cherrymusic/cherrymusic --port 8080 &>>/var/log/cherrymusic
    ;;
  stop)
    iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
    killall -u cherrymusic
    ;;
  *)
    echo "usage: $0 <start | stop>"
    ;;
esac
Ok, tal vez un killall no es lo mejor, pero sirve para mostrar un script muy simple.
Al script le agregué un "plus" que es levantar una regla iptables que redirija lo que llegue por el puerto 80, al 8080. Esto se debe a que, al ejecutar el script con un usuario no privilegiado, el mismo no se puede hookear al puerto 80.
Faltaría sólo agregarlo para que se ejecute al inicio:
  # update-rc.d cherrymusic defaults
Si quisieramos hacer lo mismo, pero utilizando upstart, podemos crear el siguiente archivo en /etc/init/cherrymusic.conf:
# Cherry Music
#
start on runlevel [2345]
stop on runlevel [!2345]
script
  iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
  sudo -u cherrymusic -H /usr/bin/python /opt/cherrymusic/cherrymusic --port 8080 &>>/var/log/cherrymusic
end script
post-stop script
  iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
end script
Eso es todo, ya pueden utilizar "service cherrymusic start" y "service cherrymusic stop", y además la aplicación se ejecutará cada vez que se encienda el equipo. Los pasos serían los mismos si ejecutaran cualquier otra aplicación =)
ejabberd LDAP, certificados y clustering
Después de pelear durante un par de días con ejabberd, me pareció interesante compartir la experiencia ganada en el proceso, ya que no todo es tan directo como parece. La documentación oficial está buena, pero la encontré un poco escueta, por lo que si no usas una configuración similar a la de los ejemplos, no sabes bien qué poner en cada parámetro.
Ejabberd está escrito en lenguaje Erlang, y utiliza el formato de este lenguaje para su archivo de configuración. Si bien no es complicado, no es a lo que uno está acostumbrado.

Comenzaré con lo básico de todos los tutoriales, pero con la idea de que el servidor autenticará con LDAP en lugar de la autenticación interna. Luego pasaré a los topics más interesantes como autopopular rosters con grupos de usuarios LDAP y armar un servicio de alta disponibilidad con dos servidores ejabberd.


Instalación

En debian, Ubuntu y supongo que otros derivados también, ejabberd se encuentra en los repositorios oficiales, por lo que instalarlo es tan fácil como ejecutar lo siguiente:
  # apt-get install ejabberd


Configuración básica

Toda la configuración se realiza desde el archivo /etc/ejabberd/ejabberd.cfg. De base, tendremos que editar lo siguiente:
  {hosts, ["dvpem.org"]}.
  {acl, admin, {user, "vektor", "dvpem.org"}}.
donde:
  • hosts especifica los dominios que ejabberd manejará.
  • acl Indica cuál es el usuario admin. Si utilizan LDAP (ver a continuación) este usuario debe ser uno que exista en el servidor de LDAP.
Como ven, muy poco es necesario para tener ejabberd funcionando. Si no utiliza LDAP deberán cambiar el nombre de usuario por uno local, y luego agregarlo con el comando ejabberctl. Por ejemplo:
  # ejabberdctl register vektor dvpem.org superPASS
Es posible acceder a una interfaz web de administración apuntando a la siguiente URL:
http://<host-o-IP>:5280/admin

Habilitar LDAP

Para habilitar autenticación por LDAP veamos un ejemplo de configuración y qué significa cada valor:
%%{auth_method, internal}.
{auth_method, ldap}.
{ldap_servers, ["ldap.dvpem.org"]}.
{ldap_base, "ou=People,dc=dvpem,dc=org"}.
{ldap_rootdn, "cn=Usuario,dc=dvpem,dc=org"}.
{ldap_password, "PASSusuario"}.
{ldap_port, 636}.
{ldap_encrypt, tls}.
{ldap_uids, [{"uid", "%u"}]}.
Vamos por línea:
  1. Deshabilita (comenta) autenticación interna.
  2. Habilita autenticación por LDAP.
  3. ldap_servers: indica cuáles son los servidores LDAP a los que se conectará ejabberd.
  4. ldap_base: especifica el DN base a partir del cual buscar los usuarios. Esto dependerá si se utiliza AD, OpenLDAP, u schemas propios.
  5. ldap_rootdn: especifica el usuario utilizado para conectar ejabberd con LDAP. El usuario utilizado debe poder listar usuarios y grupos, como mínimo.
  6. ldap_password: password del usuario utilizado en la conexión con LDAP.
  7. ldap_port: puerto del servidor LDAP.
  8. ldap_encrypt: indica que utilice TLS en la conexión.
  9. ldap_uids: indica qué atributo contiene el identificador del usuario. Esto también variará según el schema. En AD podría utilizarse samAccountName.
Reiniciar servidor ejabberd:
# server ejabberd restart
Nota 1: si iniciar ejabberd falla, probar de ejecutarlo en modo debug:
# ejabberd --debug
Nota 2: cuando la configuración está mal (o algo falla), puede que igualmente ejabberd deje un procesos corriendo y que ello les traiga problemas al intentar iniciar ejabberd nuevamente. Es un problema que queda medio oculto porque al iniciar ejabberd no arroja error, pero al mirar la lista de procesos escuchando, vemos que ninguno espera conexiones en el puerto default 5222 o 5280. En este caso, buscar y matar los procesos colgados antes de iniciar ejabberd nuevamente:
# killall -u ejabberd

Usar grupos de LDAP como grupos en los rosters

Es posible tomar los grupos de LDAP y utilizarlos en el roster, de forma que cada cliente que se conecte vea los grupos y los usuarios incluidos. Para ello, se puede utilizar el módulo mod_shared_roster_ldap, que por defecto no viene habilitado. Editar el archivo ejabberd.cfg, y en la sección de módulos agregar mod_shared_roster_ldap:
...
{modules,
 [
  ....
  {mod_shared_roster_ldap, [
        {ldap_base, "ou=Group,dc=dvpem,dc=org"},
        {ldap_rfilter, "(objectClass=posixGroup)"},
        {ldap_ufilter, "(&(objectClass=posixAccount)(uid=%u))},
        {ldap_gfilter, "(&(objectClass=posixGroup)(cn=%g))"},
        {ldap_groupattr, "cn"},
        {ldap_groupdesc, "cn"},
        {ldap_memberattr,"memberUid"},
        {ldap_memberattr_format, "cn=%u,ou=People,dc=dvpem,dc=org"},
        {ldap_useruid, "uid"},
        {ldap_userdesc, "cn"}
        ]},
 ]}.
El ejemplo está armado pensando en un servidor OpenLDAP, pero es fácilmente adaptable a AD, sólo hay que cambiar los nombres de los atributos.
Veamos cada uno de los atributos:
  • ldap_base: indica a partir de donde buscar los grupos para popular el roster.
  • ldap_rfilter: filtro que utilizará para popular el roster, y como los grupos del roster son los mismos de LDAP, pues ahí va. Dado que el base ya apunta a los grupos, no sería estrictamente necesario ya que no debería haber otra cosa que grupos en esa OU, pero por las dudas... En este caso se asume que los grupos son Posix, si usan AD tendrán que cambiar por el fitro que mejor les quede.
  • ldap_ufilter: filtro para obtener el atributo que contiene el nombre "humano" del usuario. Préstese atención que con este filtro obtenemos el nombre del atributo, no el valor del atributo, para esto último está ldap_user_desc. 
  • ldap_gfilter: filtro para obtener el nombre "humano" de los grupos. Misma idea que con ldap_ufilter.
  • ldap_groupattr: nombre del atributo LDAP que tiene el nombre del grupo.
  • ldap_groupdesc: nombre del atributo que tiene el nombre "humano" del grupo. Se usa en conjunto con ldap_gfilter, obteniendo del resultado de este filtro su valor.
  • ldap_memberattr: nombre del atributo LDAP que apunta a los miembros del grupo (member también es común).
  • ldap_memberattr_format: especifica el formato en que se guardan los miembros de un grupo. Por ejemplo, pueden tener cn=vektor,ou=People,dc=dvpem,dc=org. El %u le indica cuál es el nombre del usuario.
  • ldap_useruid: nombre del atributo que contiene el ID de usuario (en AD samAccountName).
  • ldap_user_desc: nombre del atributo que contiene el nombre "humano" del usuario. Se utiliza en conjunto con ldap_ufilter, obteniendo del resultado de este filtro su valor.

Instalar certificado propio

Para habilitar TLS/SSL ejabberd utiliza un sólo archivo que contiene clave privada, certificado y cadena de certificados. Por defecto, se genera uno al instalar ejabberd, denominado ejabberd.pem. Para no tener que editar el archivo de configuración, lo más simple es reemplazar este archivo con uno generado por nosotros a partir de nuestros certificados y clave. Este super archivo debe contener los datos en el siguiente orden:
  1. Clave privada
  2. Certificado
  3. Cadena certificante
De modo que, si por ejemplo tenemos los archivos private.key, certificado.crt y CA.crt, podemos unirlos fácilmente utilizando cat de la siguiente manera:
# cat private.key certificado.key CA.crt > /etc/ejabberd/ejabberd.pem

Timeouts

Un problema que surgió en uno de los servers que instalé, es que después de un rato de inactividad, las conexiones TCP de ejabberd con LDAP mueren. Buscando encontré que si no hay actividad durante un dado período de tiempo, algunos equipos de red pueden "desconectar" las sesiones TCP sin notificar al software que las está usando. En este caso, desde ejabberd se sigue viendo como que la conexión está activa, y al ver la conexión activa la utiliza pero sin obtener resultados. Desde mi punto de vista, esto es un bug en ejabberd, ya que si al realizar consultas no se obtiene respuesta, debería cerrar esa conexión e intentar conectarse nuevamente al servidor LDAP. En lugar de hacer eso, sólo da un authentication failure, sin loguear siquiera un timeout en los logs :S

Lo importánte aquí es la solución a este problema. El kernel de Linux soporta el envío de paquetes keepalive, para mantener activas conexiones TCP o marcar una conexión como "muerta". Esto lo realiza enviando paquetes keepalive a intervalos definidos de tiempo, esperando respuesta del servidor para decidir si la conexión está muerta. Es decir, cumple dos funciones, por un lado envía paquetes generando tráfico de red para que la conexión no se muera, y en el caso de que la conexión ya esté muerta, lo detecta y le avisa a la aplicación que la está usando.
La configuración se realiza a través de tres variables que se encuentran en /proc/sys/net/ipv4/
  • tcp_keepalive_time: default 7200 segundos, es decir, 2 horas. Especifica el intervalo en segundos entre el primer paquete de una secuencia de pruebas keepalive y el primer paquete de la próxima.
  • tcp_keepalive_intvl: default 75 segundos. Indica cada cuántos segundos enviar paquetes keepalive en una secuencia.
  • tcp_keepalive_probes: default 9. Valor numérico que especifica cuántos paquetes enviar en una secuencia.
El mecanismo es el siguiente: el kernel envía un paquete keepalive, espera el tiempo especificado en tcp_keepalive_intvl y envía otro, espera de nuevo y luego envía otro, así hasta alcanzar la cantidad de pruebas indicadas en tcp_keepalive_probes. Es decir, por defecto enviará 9 paquetes con una diferencia de 75 entre sí. Si no hay respuesta del otro lado, marca la conexión como muerta. Mientras tanto, una vez que se envió el primer paquete de esta secuencia, comienzan a contarse los segundos, y cuando se llega al valor de tcp_keepalive_time, comienza de nuevo con la secuencia mencionada.

Para no tener el problema de conexiones muertas podemo acomodar estos valores, ya que 2hs de espera puede ser demasiado. Según este post (http://start.nwt.fhstp.ac.at/blog/?p=307), los valores que mejores resultado les dieron son los siguientes:
tcp_keepalive_time = 600
tcp_keepalive_intvl = 30
tcp_keepalive_probes = 5
Lo cual se puede setear ejecutando:
# echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time
# echo 30 > /proc/sys/net/ipv4/tcp_keepalive_intvl
# echo 5 > /proc/sys/net/ipv4/tcp_keepalive_probes
Al reiniciar el servidor, estos valores se perderán, pero pueden generar un script en bash que se ejecute al inicio.

Así que ya saben, si ven que las conexiones con el servidor LDAP figuran activas (lsof -Pni), pero los clientes dan authentication failure sin razón, prueben esta solución.


Clustering 

La configuración de un cluster ejabberd, es decir, tener más de un servidor ejabberd sirviendo el mismo dominio, es medio críptica, pero no compleja. Digo críptica porque hay que ejecutar comandos Erlang para que funcione. Básicamente configurar un cluster ejabberd es igual a configurar un cluster mnesia. Erlang utiliza mnesia, un manejador de base de datos distribuido, y lo que hay que hacer es configurar mnesia para que funcione en modo replicación.

Si bien la configuración puede ser multimaster, llamaré Master al primer nodo que damos de alta y Slave al segundo.


Configuración Master

Copiar cookie mágica de Erlang que se encuentra en /var/lib/ejabberd/.erlang.cookie al nodo slave. Esta cookie debe ser igual en todos los nodos.
# scp /var/lib/ejabberd/.erlang.cookie vektor@chat2.dvpem.org:~
O bien hacer un cat de .erlang.cookie y pegar el contenido en el nodo destino.

Editar archivo /etc/default/ejabberd y agregar las líneas:
ERLANG_NODE=ejabberd@chat1
INET_DIST_INTERFACE={192,168,1,1}
donde:
  1. ERLANG_NODE especifica el nombre completo del nodo.
  2. INET_DIST_INTERFACE es la IP en la cual esperará conexiones. Utilizar comas para separar los octetos, es decir, en lugar de utilizar los convencionales puntos, separar con comas.
Reiniciar el master:
# service ejabberd restart

Configuración Slave

Detener el servicio de ejabberd:
# service ejabberd stop
# killall -u ejabberd
Editar archivo /etc/default/ejabberd y agregar las líneas:
ERLANG_NODE=ejabberd@chat2
INET_DIST_INTERFACE={192,168,1,2}
Mover la cookie al directorio de ejabberd y cambiar los permisos para que el usuario ejabberd la pueda acceder:
# mv .erlang.cookie /var/lib/ejabberd/
# chown ejabberd:ejabberd /var/lib/ejabberd/.erlang.cookie
# chmod 400 /var/lib/ejabberd/.erlang.cookie
Iniciar ejabberd:
# service ejabberd start
Asegurarse que ejabberd se está ejecutando:
  # ejabberctl status
Abrir una consola Erlang para conectar al nodo 1 y realizar una copia de la base de datos:
# ejabberctl debug
En la consola Erlang, ejecutar lo siguiente:
(ejabberd@chat2)1> mnesia:stop(),
(ejabberd@chat2)1> mnesia:delete_schema([node()]),
(ejabberd@chat2)1> mnesia:start(),
(ejabberd@chat2)1> mnesia:change_config(extra_db_nodes, ['ejabberd@chat1']),
(ejabberd@chat2)1> mnesia:change_table_copy_type(schema, node(), disc_copies).
(ejabberd@chat2)1> mnesia:info().
Cerrar la sesión precionando Ctrl+c Ctrl+c

donde:
  • mnesia:stop() detiene la ejecución de la BD mnesia,
  • mnesia:delete_schema([node()]) elimina el schema actual del nodo,
  • mnesia:start() inicia nuevamente la BD,
  • mnesia:change_config(extra_db_nodes, ['ejabberd@chat1']) apunta la base de datos al nodo 1
  • mnesia:change_table_copy_type(schema, node(), disc_copies) crea una copia local del schema.
  • mnesia:info() imprime información del nodo. Al ejecutar este comando deberían ver ambos nodos en ejecución:
      ...
      running db nodes   = ['ejabberd@chat1','ejabberd@chat2']
      ...
Esto sólo copia el esquema de la base de datos en el slave. Si bien todo funciona correctamente así, si el master cae, el sistema en teoría deja de funcionar, ya que el slave no tiene copia de las tablas.
Ahora, para tener un entorno multi-master hay que realizar una copia de todas las tablas en el nodo slave... que ya no sería más slave, sino otro master. En este caso los writes serán más lentos, pero tendremos un entorno de alta disponibilidad.
El comando para copiar tablas de otro nodo es mnesia:add_table_copy... pero hacerlo tabla por tabla es tedioso. Encontré en un comentario de StackOverflow como hacer una copia de todas las tablas en un comando:
(ejabberd@chat2)1> [{Tb, mnesia:add_table_copy(Tb, node(), Type)} || {Tb, [{'ejabberd@chat1', Type}]} <- [{T, mnesia:table_info(T, where_to_commit)} || T <- mnesia:system_info(tables)]].
Hay que ejecutarlo en una consola Erlang con "ejabberdctl debug".


Referencias



Crear una CA con OpenSSL y firmar/revocar certificados con ella
Ya es el 4to  artículo (o fueron más?) que escribo sobre certificados digitales, y sin embargo siempre me encuentro con algún requerimiento nuevo. Esta vez necesitaba crear una CA propia para firmar mis certificados, y como siempre, decidí utilizar OpenSSL.

En los siguientes pasos describiré cómo crear la susodicha CA y cómo firmar certificados con la misma.

Si les interesa, pueden dar un repaso a los otro artículos del tema:
- Certificados Digitales
- Firmando una CA propia
- Shortcuts: comandos OpenSSL para generar claves, certificados y testear conexiones


1. Configurar OpenSSL

El primero paso es copiar o editar la información en /etc/ssl/openssl.cnf. Son pocos los campos que es importante/requerido editar. El resto pueden modificarlos también, pero  la idea acá es mostrar los requerimientos mínimos.

En el archivo openssl.cnf buscar y editar los siguientes valores:
[ CA_default ]
dir             = /ca
...
new_certs_dir   = $dir/newcerts
certificate     = $dir/ca.crt
...
private_key     = $dir/ca.key
...
default_days    = 365
donde:
  • dir: directorio que alojará la información de la CA, como certificados firmados, base de datos, número de serie, etc.
  • new_certs_dir: donde se alojarán los certificados firmados.
  • certificate: ubicación del certificado de la CA.
  • private_key: la clave de la CA.
  • default_days: cantidad de días de validez de un certificado por default.
También será de mucha utilidad pegarle una mirada y editar lo siguiente:
[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = AR
countryName_min                 = 2
countryName_max                 = 2
stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = Buenos Aires
localityName                    = Locality Name (eg, city)
0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = Super CA
Estos datos facilitan la vida al generar certificados, ya que se tomarán por default y no habrá que cargarlos cada vez que se genere un nuevo request.

Una vez finalizada la edición, realizar lo siguiente en el directorio default (ver variable dir de la configuración):
  • crear los archivos de texto index.txt y serial:
    # touch /ca/index.txt /ca/serial
    donde:
    index.txt es la base de datos de certificados firmados por la CA.
    serial cotiene el número de serie que debe colocarle al próximo certificado que firme.
  • al archivo serial, agregarle un valor. Este será el número de serie que imprima al primer certificado que genere, luego lo actualizará solo. El valor debe ser de dos dígitos:
    echo "01" > /ca/serial
  • crear el directorio para los certificados nuevos, si es que todavía no existe. Para el ejemplo dado:
    # mkdir /ca/newcerts

2. Generar clave y certificado de CA

Claramente la CA debe contar con su propia clave y certificado. Estos se utilizarán para firmar los certificados que se requieran luego. La forma más rápida es utilizando un sólo comando:
# openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /ca/ca.key -out /ca/ca.crt -config /ca/openssl.cnf
Generating a 2048 bit RSA private key
...+++
..........................................+++
writing new private key to 'ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AR]:
State or Province Name (full name) [Buenos Aires]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Super CA]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:super-ca.com
Email Address []:
Como verán, el archivo de configuración hace que los valores de "Country Name", "State or Province Name", etc se tomen de ahí.


3. Firmar certificados

En los anteriores artículos expliqué cómo generar un request de certificado, por lo que no me explayaré en eso. Les dejo el siguiente comando que crea una clave y CSR, y además utiliza como template el archivo de configuración:
# openssl req -new -newkey rsa:2048 -keyout prueba.key -out prueba.csr -config /ca/openssl.cnf
Generating a 2048 bit RSA private key
......................................+++
....+++
writing new private key to 'prueba.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AR]:
State or Province Name (full name) [Buenos Aires]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Super CA]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:superprueba.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Ok, ahora si a lo bueno, con este simple comando podremos firmar los request de certificados que deseemos:
# openssl ca -cert /ca/ca.crt -keyfile /ca/ca.key -in prueba.csr -out prueba.crt -config /ca/openssl.cnf
Using configuration from /ca/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 2 (0x2)
Validity
   Not Before: Jan  5 15:40:56 2015 GMT
   Not After : Jan  5 15:40:56 2016 GMT
Subject:
   countryName               = AR
   stateOrProvinceName       = Buenos Aires
   organizationName          = Super CA
   commonName                = superprueba.com
X509v3 extensions:
   X509v3 Basic Constraints:
CA:FALSE
   Netscape Comment:
OpenSSL Generated Certificate
   X509v3 Subject Key Identifier:
EE:9C:75:57:66:F6:3E:FA:D9:CF:6F:06:60:E0:97:D1:EE:EC:14:EA
   X509v3 Authority Key Identifier:
keyid:98:7A:32:95:93:72:24:37:B0:16:61:10:8D:E7:51:5F:54:95:C7:62
Certificate is to be certified until Jan  5 15:40:56 2016 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

4. Revocar certificados

Finalmente, y porque seguro les sucederá en algún momento, veamos cómo revocar un certificado. Es tan simple como ejecutar el siguiente comando:
# openssl ca -revoke prueba.crt -config /ca/openssl.cnf
Using configuration from /ca/openssl.cnf
Revoking Certificate 01.
Data Base Updated
Si miran el archivo index.txt, podrán observar una R al principio de la línea del certificado.

Un tip interesante, es qué pasa si no tenemos el certificado que queremos revocar. En este post de stackoverflow explican una forma de hacerlo.
OpenSSL guarda una copia de los certificados que firma en el directorio "newcerts" (o donde lo hayan configurado en openssl.cnf). Los certificados se guardan con el número de serie como nombre, por lo que primero hay que hayar el número de serie del certificado que queremos revocar. Un simple grep puede ayudarnos en este caso:
# grep "prueba" /ca/index.txt
V       160105143331Z           01      unknown /C=AR/ST=Buenos Aires/O=Super CA/CN=prueba
donde vemos que el ID es 01.
Con esta info, ejecutamos el comando anterior de la siguiente manera:
# openssl ca -revoke newcerts/01.pem -config /ca/openssl.cnf

Referencias

How To Setup a CA
FirefoxOS en tu PC
Buscando emuladores de Android, se me ocurrió que sería bueno también probar FirefoxOS, el sistema operativo de la gente de Mozilla para dispositivos móviles. Hacía rato que tenía ganas de probar este sistema, ya que Android me parece extremadamente invasivo, dándo acceso a Google y sus partnets a todo lo que haces con tus dispositivos. Tal vez la gente de Mozilla haga lo mismo, pero es bueno darle una chance y probar. Además en el sentido de la privacidad, confío más en Mozilla que en Google... aunque vale decir que no se puede confiar en nadie jejeje.

Sé que en España y algunos países de Latinoamérica, Telefónica está vendiendo celulares con FirefoxOS instalado. Desgraciadamente estos equipos todavía no llegaron a Argentina, así que no había tenido la oportunidad de probar el sistema.

Por suerte encontré que ejecutar FirefoxOS en una PC es extremadamente simple! tan sólo hay que instalar el add-on del simulador.

Veamos los pasos:
  1. Descargar el add-on para Firefox desde App manager add-ons.
    La versión 2.0 pesa más de 120MB, así que a esperar un poco.

  2. Una vez instalado, es posible acceder al simulador desde el App Manager. Al mismo se llega dando click "botón de menú -> Developer -> App Manager", o bien escribiendo en la barra de navegación la URL about:app-manager

  3. En el App Manager damos "Start Simulator" y aparecerán en la misma barra los simuladores que tengamos instalados.

  4. Clickear el simulador que queramos ejecutar y listo!


Increíblemente simple.

Cabe aclarar que estos pasos funcionan en GNU/Linux, Windows y Mac.

Ahora, si no queremos abrir el firefox para ejecutar el simulador, encontré (mirando la lista de procesos), que se puede acceder ejecutando el siguiente comando (en GNU/Linux) desde la línea de comandos:
$HOME/.mozilla/firefox//extensions/fxos_2_0_simulator@mozilla.org/b2g/b2g-bin -profile $HOME/.mozilla/firefox//extensions/fxos_2_0_simulator@mozilla.org/profile -start-debugger-server 56807 -no-remote
En el comando anterior, reemplazar <perfil> por el nombre del directorio del perfil donde el simulador está instalado.

El simulador me demostró ser muy eficiente. Tan sólo consume 128MB de memoria (residente) y funciona muy fluido. Además la integración con el sistema es espectacular.

A probar FirefoxOS y ver que tal se comporta. Hasta donde ví, me gustó. Obviamente la lista de aplicaciones todavía es limitada, pero a medida que vaya ganando popularidad habrá más y más.

Referencia: Using the App Manager
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
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
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