OSSIM: alertas arpwatch por mail que incluyan MAC origen y destino
Desde hace varias semanas vengo peleando con OSSIM y el plugin que utiliza para parsear logs de arpwatch. En el artículo anterior les conté cómo modifiqué el código de arpwatch para que reporte sólo el cambio de MAC de hosts específicos, y no todos los cambios de MACs. Ahora mi meta era hacer que OSSIM me envíe un mail cada vez que detecte el cambio de MAC de estos hosts.

El envío de este tipo de alertas por mail es muy simple y lo describiré luego. Primero veamos qué información brinda el plugin de arpwatch y entenderán por qué tuve que crear un nuevo plugin.

El plugin original (/etc/ossim/agent/plugins/arpwatch.cfg o /etc/ossim/agent/plugins/arpwatch_eth0.cfg) utiliza el tipo de evento host-mac-event, un tipo de evento que posee un conjunto fijo de atributos y no se pueden agregar, ni quitar, ni modificar, a menos que modifiquemos el código C del servidor OSSIM. Los atributos que brinda este tipo de evento, según la documentación oficial, son:
    host: IP del host que cambio su MAC
    mac: nueva dirección MAC en hexadecmal
    vendor: fabricante de la placa
    sensor
    interface
    date
    plugin_id: el ID del plugin, el cual es siemrpe 1512 (arpwatch)
    plugin_sid: sin importancia ya que el servidor OSSIM asignará el que corresponda
    log: contiene una copia del cambio de MAC
    userdata1: copia de la nueva dirección MAC nueva
    userdata2: copia del nombre fabricante
Si prestan atención, pueden ver que la MAC anterior sólo figura en el atributo log. Cuál es el problema? que el atributo log no se puede utilizar en las acciones (y presupongo que tampoco en las correlaciones, pero no puedo asegurarlo).
Entonces, si no se puede utilizar en las acciones, no es posible enviar mails que incluyan la MAC de origen en ellos, algo que, al menos para mi, es de mucha utilidad.
Supongan que arman una política que les envíe una alerta por mail cada vez que un host importante cambia su MAC. Con el plugin original sólo tendrían la nueva MAC y deberían ir a revisar la larga lista de eventos SIEM para encontrar cual era la MAC anterior y ver la diferencia.


Nuevo plugin para arpwatch

En fin. Para arreglar esto, definí un nuevo plugin para arpwatch, denominado arpwatch_new.cfg (oh si, muy original):
[DEFAULT]
plugin_id=51512

[arpwatch-changed-address]
event_type=event
src_ip={resolv($1)}
host={$1}
interface={$4}
mac={$2}
userdata1={$2}
userdata3={$3}
plugin_sid=2
regexp="arpwatch.*?: changed ethernet address (\IPV4) (\MAC) \((\MAC)\) (\S+)"
vendor=unknown

[arpwatch-flipflop]
event_type=event
src_ip={resolv($1)}
host={$1}
interface={$4}
mac={$2}
userdata1={$2}
userdata3={$3}
plugin_sid=2
regexp="arpwatch.*?: flip flop (\IPV4) (\MAC) \((\MAC)\) (\S+)"
vendor=unknown

[arpwatch-new-station]
event_type=event
src_ip={resolv($1)}
host={$1}
interface={$3}
mac={$2}
plugin_sid=1
regexp="arpwatch.*?: new station (\IPV4) (\MAC) (\S+)"
vendor=unknown

[arpwatch-reused-address]
event_type=event
src_ip={resolv($1)}
host={$1}
interface={$4}
mac={$2}
userdata1={$2}
userdata3={$3}
plugin_sid=2
regexp="arpwatch.*?: reused old ethernet address (\IPV4) (\MAC) \((\MAC)\) (\S+)"
vendor=unknown

[config]
create_file=true
enable=yes
interface=eth0
location=/var/log/ossim/arpwatch-new.log
process=/usr/sbin/arpwatch_eth0
restart=no
restart_interval=\_CFG(watchdog,restart_interval)
shutdown=killall %(process)s
source=log
start=yes
startup=%(process)s -d -d -i %(interface)s -f /var/lib/arpwatch/arp-eth0.dat -N >> %(location)s 2>&1 &
stop=yes
type=detector
Como verán, cambié el identificador a 51512 para no colisionar con el anterior (1512) y utilicé el tipo de evento genérico "event", que permite flexibilidad en los atributos a utilizar. Gracias a esto, ahora puedo ver la MAC origen en el atributo userdata3, mientras que la nueva MAC está en userdata1, como antes.
Para habilitar este nuevo plugin, hay que ingresarlo en las tablas plugin y plugin_sid de la base de datos OSSIM. Esto se hace a través del siguiente archivo sql (arpwatch_new.sql):
-- uncomment the following lines to delete old arpwatch plugin
-- DELETE FROM plugin WHERE id = "1512";
-- DELETE FROM plugin_sid WHERE plugin_id="1512";
-- delete old entries of this plugin
DELETE FROM plugin WHERE id = "51512";
DELETE FROM plugin_sid WHERE plugin_id = "51512";

INSERT INTO plugin (id, type, name, description) VALUES (51512, 1, 'arpwatch_new', 'Ethernet/FDDI station monitor daemon');
INSERT INTO plugin_sid (plugin_id, sid, category_id, class_id, name) VALUES (51512, 1, NULL, NULL, 'arpwatch_new: Mac address New');
INSERT INTO plugin_sid (plugin_id, sid, category_id, class_id, name) VALUES (51512, 2, NULL, NULL, 'arpwatch_new: Mac address Change');
INSERT INTO plugin_sid (plugin_id, sid, category_id, class_id, name) VALUES (51512, 3, NULL, NULL, 'arpwatch_new: Mac address Deleted');
INSERT INTO plugin_sid (plugin_id, sid, category_id, class_id, name) VALUES (51512, 4, NULL, NULL, 'arpwatch_new: Mac address Same');
INSERT INTO plugin_sid (plugin_id, sid, category_id, class_id, name) VALUES (51512, 5, NULL, NULL, 'arpwatch_new: Mac address Event unknown');
Inluir esto en la base de datos es tan simple como ejectutar:
  cat arpwatch_new.sql | mysql -u root -p ossim

Luego deben modificar la configuración del agente OSSIM para que incluya este plugin, es decir, comentar la línea del plugin de arpwatch anterior y agregar el nuevo en el archivo /etc/ossim/agent/config.cfg, en la sección plugins:
  #arpwatch_eth0=/etc/ossim/agent/plugins/arpwatch_eth0.cfg
  arpwatch_new=/etc/ossim/agent/plugins/arpwatch_new.cfg

Finalmente reinicien los servicios de ossim server y agent:
  /etc/init.d/ossim-server restart
  /etc/init.d/ossim-agent restart
y verifiquen que se encuentre cargado en la  pestaña Collections de la interfaz web.


Reporte de cambios por mail

Con el nuevo plugin ya es posible crear una política que ejecute una acción que envíe mails. Las políticas y las acciones se pueden crear fácilmente desde la interfaz web. Para hacerlo, hay que dirigirse a la opción Intelligence -> Policy & Actions.

Primero crearemos la acción que ejecutará el envío de mail, para luego poder seleccionarla en la política. La acción se crea desde la pestaña Actions y dando al botón New. Una acción puede ser la creación de un ticket, o, como deseamos nosotros, el envío de un mail. Este tipo se elige en el desplegable Type. Es obligatorio colocar una descripción de la acción.
El resto de los campos son muy intuitivos, el originario del mail, el destinatario, el asunto y el mensaje. Se pueden utilizar palabras claves especiales tanto en el contenido como en el asunto del mail, las cuales OSSIM reemplazará por el valor correspondiente. En la parte superior de la acción estan los atributos elegibles, entre los que se cuenta con las IPs de orígen y destino, puertos, protocolos y varios campos más. Para el caso en cuestión, lo importante es que el reporte contenga la IP del host y las MACs anterior y nueva, las cuales se encuentran en los atributos userdata1 y userdata3, según lo definimos en el plugin.

La política se crea de forma bastante intuitiva, en la pestaña Policy, dando New y siguiendo los pasos. Los primeros pasos describen atributos que deben tener los paquetes para que esta política se aplique, como IPs orígen y destino, y Ports destino.
Uno de los pasos relevantes es la definición del "DS Groups", donde se elige el grupo de plugins a tener en cuenta a la hora de analizar los paquetes. OSSIM trae algunos grupos de plugins ya armados, pero para nuestro caso, hay que insertar uno nuevo, dandole al link "Insert new DS Group?". En este punto hay que ingresar un nombre y una descripción, acompañado por el plugin a utilizar, que se selecciona dando en el +

En el listado debería aparecer el nuevo plugin que creamos anteriormente con ID 51512. Una vez seleccionado es posible elegir que tipos de evento, del mencionado plugin, deben tenerse en cuenta. Es así como podemos reportar sólo eventos de cambio de MAC y no cuando se ve un host nuevo. El tipo de evento que nos interesa es el que tiene el identificador 2.
Cuando el grupo DS ya está ingresado, es posible seleccionarlo y continuar con la definición de la política.
El otro paso relevante es la elección de las consecuencias que tiene la política. Es decir, qué acción tomar cuando detectamos un evento que cumple con las características descriptas en la política. Para este caso, elegiremos la acción que creamos anteriormente, y además podríamos elevar la prioridad del evento a 5.


En fin

Con estos cambios ya es posible recibir por mail reportes de cambios de MACs en hosts importantes, que incluyan la MAC anterior y la nueva, gracias a la nueva definición del plugin y la política creada.


Referencias

- OSSIM Sensor - The Agent
- Creating a Custom OSSIM 3 policy
Arpwatch con seguimiento de hosts específicos
Desde que instalé arpwatch en la red de la empresa donde trabajo, me encontré con una necesidad imperiosa. Nuestra red otorga las IPs de las workstations por DHCP, pero en la misma red existen host importantes que tienen IPs fijas.
Arpwatch no se desempeña demasiado bien en redes con DHCP, dado que con este esquema las IPs de las máquinas suelen cambiar cada tanto, generando reportes sin utilidad para quien revisa los logs de seguridad. Entre tantos reportes sin utilidad pueden quedar escondidos reportes que si nos interesan, como por ejemplo ver que la IP de un proxy, gateway, server, cambió su MAC, algo que es en extremo sospechoso y muy importante para detectar intrusos.
De esta manera tenemos una herramienta muy simple y poderosa, pero que al generar tantos reportes molestos, resulta poco útil en este tipo de redes.

Para obtener lo mejor de esta herramienta contaba con dos opciones:
  1) desarrollar un script que parsee los logs buscando sólo las IPs que me interesan,
  2) agregar al código de arpwatch la funcionalidad necesaria para poder filtrar ciertas IPs.

La primera era más rápida y simple, pero la segunda mucho más interesante. Por fin esta semana conté con tiempo libre, así que puse manos a la obra y actualicé el código de arpwatch para que incluya esta funcionalidad. Esta es una de las grandes ventajas de utilizar software libre, si necesitas más funcionalidad, podes agregarla vos mismo!

Por lo que encontré, arpwatch no se actualiza desde 2006, pero hay parches como el de debian, que agregaron cierta funcionalidad. Como ya sabrán, utilizo debian para todo y es la base de una gran porción de distribuciones, así que decidí partir del paquete de debian. Este paquete incluye opciones como ignorar una red entera, o enviar reportes por mail, y pueden verlas marcadas con el prefijo "(Debian)" en la man page.

Yendo al grano, qué provee el código que desarrolle?
  - la posibilidad de reportar cambios de MAC sólo de IPs específicas
  - una nueva opción en la línea de comandos (-H <filename>) para activar esta funcionalidad e indicar el archivo donde se encuentran los hosts a seguir
  - configuración simple del archivo de hosts a seguir:
    - se puede especificar un host según su IP (ej: 192.168.0.2), hostname (mihost.mired.com), o red entera (192.168.0.0/24),
    - es posible dejar líneas en blanco para separar grupos de host visualmente
    - permite la adición de comentarios utilizando el símbolo # al comienzo de cada línea.
  - man page actualizada explicando la nueva funcionalidad.

Si por ejemplo quisiéramos seguir sólo los hosts 192.168.0.2, www.miempresa.com, y la red 192.168.10.0/24, el archivo de hosts (denominado hosts.dat) podría ser:
  #ip interna
  192.168.0.2

  #web de la empresa
  www.miempresa.com

  #red de compras
  192.168.10.0/24

Luego bastaría con ejecutar arpwatch de la siguiente manera:
  # arpwatch -H hosts.dat

La instalación de esta nueva versión debe hacerse de la siguiente manera:
  1) descargar el código de arpwatch original
  2) descargar el parche de debian
  3) descargar mi parche
  4) desomprimir el código original y los parches:
      $ tar -xzvf arpwatch_2.1a15.orig.tar.gz
      $ tar -xzvf arpwatch_2.1a15-1.1.diff.gz
      $ tar -xzvf arpwatch-2.1a15-2-diff.diff.gz
  5) parchar el código original con el parche de debian, parados en el directorio del código original:
      $ cd arpwatch_2.1a15
      $ patch < ../arpwatch_2.1a15-1.1.diff
  6) parchar lo anterior con la extensión que programé:
      $ patch < ../arpwatch-2.1a15-2-diff.diff
  7) compilar:
      $ ./configure
      $ make
  8) instalar:
      $ make install

Algo a tener en cuenta es que deberán tener las fuentes de pcap para poder compilar arpwatch. En debian el paquete se denomina libpcap-dev.

Si tienen alguna duda o encuentran algún fallo en el programa, por favor reportenmelo. Contacté al maintainer del paquete en debian y espero le interese incorporar este parche para ampliar la funcionalidad de esta excelente herramienta.
Espero les resulte tan útil como a mi!

Que tengan un feliz año nuevo y arranquen el 2012 con todo. Recuerden que, según los mayas, será el último =P
Mucho boom tecnológico pero la ignorancia en seguridad sigue igual...
Una vez más me veo sorprendido por la ignorancia que existe en el mundo TI acerca de conceptos básicos de seguridad. En los casi tres años que llevo trabajando en seguridad informática, toda aplicación que audité (desktop o web) poseía vulnerabilidades críticas y muy básicas.

Cuando recién empecé a trabajar en el rubro, creía que vulnerabilidades como buffer overflow, SQL Injection, XSS, eran raras de encontrar debido a la gran difusión que poseen y lo fáciles que son de evitar, sin embargo, tres años de experiencia y trato con una cantidad considerable de desarrolladores y empresas (más de 15), me demostraron lo contrario.
Lo peor no es encontrar que toda aplicación que analizo es vulnerable a ataques simples, sino que al tratar con los desarrolladores me encuentro con una ignorancia espeluznante. Muy pocos de los programadores con los que traté conocían al menos de nombre los ataques, y la gran mayoría no tenía ni idea de cómo solucionar los problemas.
Es así como me encuentro una y otra vez explicando ataques, explicando métodos para mitigarlos, demostrando dónde están los errores. Cada proveedor de software con el que tengo contacto tengo que volver a explicar lo mismo. Lo más indignante es que la gran mayoría te termina tratando como que lo que pedís es exagerado, que controles así no se utilizan, que la seguridad no se encuentra en los requerimientos! (WTF!) La defensa de las empresas de desarrollo es atacar en lugar de reconocer su ignorancia. Pedir más dinero por lo que debería haber estado contemplado desde el principio, culpar al auditor de retrasar la puesta en producción de productos incompletos y de baja calidad, porque recuerden amigos, la seguridad forma una parte esencial del software de calidad.

Al principio creía que la falta de conocimiento era local en la ciudad donde vivo, pero luego de tratar con muchas empresas de Buenos Aires y, recientemente, extranjeras, me terminaron de demostrar que la ignorancia es general.
El catalizador de este post es que en estos días me tocó auditar una aplicación web provista por una importante empresa de Brasil. Lo raro no fue encontrar que el sitio era vulnerable a distintos ataques, sino que al entablar conversaciones con los desarrolladores encontré la mayor ignorancia en seguridad que vi en estos tres años. No tenían absolutamente idea de nada relacionado a seguridad web, no habían escuchado ni nombrar ataques de SQL Injection, XSS, XSRF, ni OWASP, ni mucho menos prepared statements o como escapar caracteres HTML, NADA! En la conferencia que tuvimos tuve que improvisar una suerte de cátedra en seguridad Web. Realmente se hace muy muy difícil que alguien entienda los riesgos de lo que estas exponiendo si no tienen idea de lo que estás tratando. Decían que yo era un genio por lo que había descubierto y que el 99.9% de la gente no podría encontrar esos errores... si bien me sentí alagado, me causó mucha gracia, dado que las técnicas que emplee eran tan simples que cualquiera siguiendo un tutorial de la web podría hacerlo.

En una era donde todo está informatizado y poco a poco todo se va moviendo hacia servicios cloud, tener tanta información en la web en manos de desarrolladores que no tienen ni idea de cómo protegerla, o peor aún, no les interesa, realmente da miedo.

Por favor, si estás leyendo esto y sos desarrollador, toma conciencia, capacitate en seguridad, como mínimo date una vuelta por la web de OWASP. La seguridad es MUY fácil de implementar, y aprender, sólo necesitas saber conceptos básicos, no necesitas ser un experto en el tema, basta con estar interesado en mejorar como programador.

Yo seguiré aportando mi granito de arena desde este blog y dando conferencias donde pueda, espero lograr aunque sea un pequeño cambio. Algo es seguro, ninguna empresa que haya desarrollado para la empresa que trabajo se olvidará de los conceptos que les enseñé y sabrán que mientras esté ahí no podrán obviar la seguridad en sus programas, así me hayan odiado por ello =)
Montar shares SMB/CIFS + Automontar shares SMB/CIFS en redes kerberizadas
Si son seguidores del blog, saben que utilizo un GNU/Linux unido a un dominio AD desde hace tiempo. Algo que siempre estuve por configurar es el automontaje de los shares para no tener que escribir las direcciones una y otra vez. Hoy llegó el momento =D
A continuación describiré un poco cómo acceder y montar shares SMB en GNU/Linux y luego les mostraré cómo hacer para que un share se monte automáticamente al inicio de sesión, utilizando el ticket kerberos que nos entrega el controlador de dominio en el login.


Montar shares

Para los que trabajan con GNU/Linux es muy común acceder sistemas de archivos Windows a través del protocolo SMB (CIFS es el nombre actual del protocolo). Samba posee una excelente compatibilidad con el protocolo y provee diversas herramientas para el acceso.
Una vez que Samba está instalado, acceder un servidor de archivos es tan simple como escribir la siguiente URL en su navegador de archivos favorito (Dolphin, Nautilus, Krusader, etc):
  smb://server1.ejemplo.com/
donde server1.ejemplo.com es el nombre del servidor.
En una red hogareña, sin AD, la autenticación con el servidor se realiza utilizando el viejo NTLM, con lo cual, al tipear la URL anterior, el navegador les pedirá que ingresen las credenciales de un usuario válido (desde la visión del servidor).

Otra forma de acceder a los archivos es montar el sistema remoto en un directorio local. El paquete smbfs provee soporte para el sistema de archivos smb/cifs, el cual se puede utilizar en el comando mount de la siguiente manera:
mount -t cifs //server1.ejemplo.com /media/samba -o user=pepe
Al ejecutar el comando anterior, aparecerá un prompt solicitando el password del usuario en cuestión.
Por supuesto que también es posible agregar una entrada en /etc/fstab para hacer el montaje más rápido y/o automático. La entrada en fstab correspondiente al ejemplo anterior es la siguiente:
//server1.ejemplo.com    /media/samba    cifs    user,auto,username=pepe    0    0
donde las opciones son:
user -> para que lo pueda montar un usuario común (sin ser root)
auto -> debe montarse automáticamente al iniciar el sistema
username=pepe -> especifica el nombre del usuario a utilizar
Claro que al intentar montar el sistema solicitará el password correspondiente. Hay dos formas de evitar que esto pase, aunque ninguna es muy atractiva:
- utilizar la opción password=
- crear un archivo (por ejemplo /home/pepe/cred.smb) que contenga las líneas:
      username=pepe
      password=elpassword
y luego utilizar la opción credentials=/home/pepe/cred.smb en fstab.
Digo poco atractivas porque en ambos casos es necesario colocar las credenciales en texto plano. Con la segunda opción se evita que otro usuario abra el fstab y vea el password, pero igualmente no es del todo satisfactoria.


Automontar shares en redes corporativas

En una red corporativa con servidores Windows, es muy probable que se utilice Active Directory. La autenticación en estos entornos se lleva a cabo utilizando kerberos, aunque por defecto (al menos hasta Windows 2003) los servidores de archivos soportan NTLM por compatibilidad. Incluso en redes corporativas con servicios integrados con kerberos provistos por servidores GNU/Linux se está utilizando bastante Samba como protocolo para la compartición de archivos, lo que hace doblemente atractiva la siguiente explicación.

Ahora, gracias a Samba y PAM, es posible mejorar el esquema de clientes Linux dentro de la corporación. Algo muy común es que los usuarios de workstations con Windows tengan mapeos automáticos al realizar un login, como por ejemplo el disco F:\ apuntando al servidor server1.ejemplo.com. Un cliente GNU/Linux puede tener esta misma comodidad, con mapeos automáticos de shares de red al árbol de directorios de su máquina.

La siguiente configuración tiene en cuenta que la workstation GNU/Linux autentica usuarios contra Domain Controllers (o servidores kerberos de GNU/Linux) con PAM y kerberos, como se explicó en el artículo Configurar PAM para utilizar kerberos.
Utilizando el entorno descripto en el artículo, los usuarios contarán con un ticket kerberos luego de que se autentiquen. Como Samba es compatible con kerberos, no es necesario seguir ingresando las credenciales al montar o acceder un share, Samba hará la autenticación de forma transparente utilizando el ticket correspondiente.

No existe una alternativa segura para hacer que un usuario monte un share que no figure en el fstab, sólo un administrador puede hacerlo. Claro que no sirve colocar una entrada en fstab que intente montar automáticamente un share, dado que se hará a nombre de root y root no posee un ticket kerberos... es decir, access denied!

La solución entonces consta de dos pasos. Agregar la línea en el fstab, y luego configurar kde, gnome, o el desktop que utilicen, para que realice el mount cuando el usuario se loguea.
Teniendo en cuenta el ejemplo con el que venimos trabajando, deberá agregarse la siguiente línea en fstab para utilizar kerberos:
//server1.ejemplo.com    /media/samba    cifs    user,noauto,sec=krb5    0    0
las opciones relevantes aquí son:
noauto -> no montar automáticamente
sec=krb5 -> indica a samba que utilice kerberos en la autenticación
Para el automontaje se crea un script en bash (o su shell favorito) con el siguiente contenido:
#!/bin/bash
mount //server1.ejemplo.com
y se coloca en el directorio correspondiente (dándole ejecución con chmod +x) para que desktop lo ejecute al iniciar la sesión del usuario. Por ejemplo:
- en kde deberá colocarse en $HOME/.kde/Autostart/
- en gnome debe abrirse el "Gnome Control Center" ir a "aplicaciones al inicio" y agregar la ruta al script.
De esta forma, una vez que el usuario se validó contra kerberos, el sistema automáticamente montará sus shares en el lugar correspondiente, una verdadera comodidad, y un paso más para extender el uso de GNU/Linux en las corporaciones =)

El siguiente paso es agregar un script que desmonte los shares una vez que el usuario ejecuta logout, porque si la misma workstation es compartida por diferentes usuarios, dejar el acceso a los shares de otro usuario no es buena idea. Esta tarea debe realizarse con un script similar al anterior:
#!/bin/bash
umount //server1.ejemplo.com
y colocarlo en el directorio correspondiente al desktop que utilicen. Por ejemplo:
- en kde existe el directorio $HOME/.kde/shutdow destinado a tal fin
- en gnome ??? (avísenme si lo encuentran)

To Do

Como bien dije, no es posible que los usuarios monten los shares que no se encuentren definidos en fstab. Es decir, en fstab deben figurar todos los shares disponibles para los usuarios de una dada workstation, porque sino no podrán montarlos. Esto es un inconveniente bastante molesto, dado que si el usuario puede acceder a los shares, no tiene mucho sentido restringir para que no pueda montarlo en el árbol de directorios local.
Existe, claro, una forma indirecta y que en general es considerada insegura. La misma se basa en otorgar setuid root al ejecutable mount.cifs. Con esto, cuando un usuario ejecute el comando mount.cifs, éste se ejecuta con permisos de root, y por consiguiente puede montar los shares, aunque en este caso, probablemente no funcione el ticket kerberos (no lo probé). Queda en ustedes si se deciden por esta alternativa.


Referencia

- Samba HowTo: Mount a CIFS Network Share [Mapped Drive] in openSUSE
Migrar mails locales de Evolution a Thunderbird/Icedove
Luego de utilizar Evolution durante un par de años en el trabajo, encontré la forma de integrar Thunderbird con Exchange, y como este cliente siempre me gustó mucho más que el primero, decidí migrar. El problema es que había acumulado miles de mails en carpetas locales de Evolution y los necesitaba en Thunderbird.
Por suerte, ambos clientes utilizan el mismo formato para almacenar los mails (formato mailbox), así que son totalmente compatibles y lo único que hay que hacer es copiar los archivos de un directorio a otro.
En Evolution, los mails locales pueden estar almacenados, dependiendo la distribución y/o versión, en:
/home/<usuario>/.evolution/mail/local
o en:
/home/<usuario>/.local/share/evolution/mail/local_mbox/
Debian almacena los mails en la segunda opción, así que mostraré los comandos en base a este directorio, aunque es lo mismo si está en el otro.
Por su parte, Thunderbird almacena los mails locales en:
/home/<usuario>/.thunderbird/<valor random>.default/Mail/Local\ Folders
o si utilizan Icedove (debian y algunos derivados):
/home/<usuario>/.icedove/<valor random>.default/Mail/Local\ Folders/
Para migrar los mails de uno a otro, simplemente basta con copiar el contenido de una carpeta en la otra:
cp -R /home/demasiadovivo/.local/share/evolution/mail/local_mbox/* /home/demasiadovivo/.icedove/3uomqof5.default/Mail/Local\ Folders/
Ahora, cada cliente almacena distintos metadatos sobre los mailboxes, así que si hacen un copy como el de recién y abren Thunderbird, verán que, además de las carpetas personales tendrán un montón de carpetas vacías con nombres que terminan en .cmeta, .data y .index. Esto se debe que son metadatos para Evolution, son interpretados por Thunderbird como directorios. Por ello hay que eliminarlos.
La forma más rápida de hacerlo es con un find que ejecute un rm:
find /home/demasiadovivo/.icedove/3uomqof5.default/Mail/Local\ Folders/ -type f \( -name '*.cmeta' -o -name '*.data' -o -name '*.index' \) -exec rm -r {} \;
El comando anterior busca todos los archivos de extensión .cmeta, .data e .index que estén en el directorio de mails de Thunderbird y luego ejecuta un rm.

Con esto, al iniciar Thunderbird verán que tienen sólo los directorios originales, con todos sus mails adentro.


Referencias

- How To Migrate From Evolution To Thunderbird In Ubuntu Intrepid
- Migrar de Evolution a Thunderbird
- Linux or Unix find and remove files with one find command on fly
Autenticar con kerberos y almacenar información de usuarios con LDAP en GNU/Linux
En los artículos anteriores se explicaron las bases del funcionamiento y utilización de kerberos, LDAP y PAM. Además se explicó cómo autenticar usuarios de GNU/Linux utilizando kerberos. Con esta información en mente, ahora somos capaces de armar un servicio de autenticación centralizada para hosts GNU/Linux, que utilice estos ampliamente aceptados y utilizados servicios.

Para lograr que toda la información de usuarios y grupos se almacene y administre en servidores LDAP, debemos encontrar la forma de que las workstations GNU/Linux se comuniquen con LDAP para obtener los datos que comúnmente se encuentran en los archivos /etc/passwd, /etc/shadow y /etc/group.

En /etc/passwd tenemos los datos concernientes a los usuarios del sistema. Cada entrada representa un usuario y los campos almacenados son los siguientes:
  • credenciales (sólo el nombre de usuario se almacena en /etc/passwd, cuestiones de contraseña se encuentran en /etc/shadow)
  • ID, identificador de usuario
  • grupos a los cuales pertenece
  • nombre real
  • directorio home (ej: /home/demasiadovivo)
  • shell a utilizar (opcional)
Como ya adelanté en el punto anterior, /etc/shadow contiene información de contraseñas. Las contraseñas se almacenan hasheadas (o encriptadas en soluciones antiguas) utilizando un salt. Los campos que se almacenan para cada usuario son:
  • nombre de login
  • hash del password o el password encriptado.
  • fecha del último cambio de password.
  • edad mínima de un password, es decir, el número de días que el usuario debe esperar entre cambios de passwords.
  • edad máxima de un password. Duración del password, es decir, cuanto tiempo podemos usar un password como máximo.
  • período de advertencia. Cuántos días antes de que el password expire, el sistema debe avisar al usuario que esto sucederá.
  • período de inactividad de un password. La cantidad de días que un password debe ser aceptado para generar uno nuevo, luego de que el password expiró. Una vez que este período expira, el usuario no podrá loguearse más y deberá contactar al administrador.
  • fecha de expiración del usuario, en formato timestamp Unix.
Por su parte /etc/group contiene los datos de los grupos, donde para cada grupo se almacena lo siguiente:
  • nombre de grupo
  • contraseña de grupo encriptada (opcional)
  • GID, o identificador de grupo
  • lista de los usuarios que pertenecen al grupo
Cambiar el mecanismo de autenticación de usuarios en GNU/Linux es simple gracias a PAM (ver artículo anterior).
El problema con PAM, es que no permite acceder el resto de la información del usuario almacenada en un LDAP, es decir, información comúnmente almacenada en passwd, shadow y group. Para ello debemos valernos de otra herramienta, llamada NSS (Name Service Switch).
NSS permite utilizar distintas fuentes para obtener diferentes tipos de datos comunes, como los datos de usuario citados anteriormente. Es decir, agrega transparencia al resto de los programas a la hora de acceder dinstinta información. NSS es la capa que permite a un administrador configurar los sistemas para que obtengan de fuentes remotas datos que normalmente se buscarían en archivos locales en /etc (como passwd, group, hosts, etc).
Gracias a NSS, ahora podremos almacenar los datos que nos interesen, como los de usuarios y grupos, en LDAP, simplemente configurando el archivo /etc/nsswitch.conf


Creación de usuarios en kerberos

Para autenticar usuarios con kerberos, primero debemos agregar los principals correspondientes en la base de datos. Agregar un principal para un usuario es tan fácil como ejecutar addprinc utilizando kadmin:
# kadmin.local
Authenticating as principal root/admin@DEMASIADOVIVO.ORG with password.
kadmin.local: addprinc demasiadovivo
WARNING: no policy specified for demasiadovivo@DEMASIADOVIVO.ORG; defaulting to no policy
Enter password for principal "demasiadovivo@DEMASIADOVIVO.ORG":
Re-enter password for principal "demasiadovivo@DEMASIADOVIVO.ORG":
Principal "demasiadovivo@DEMASIADOVIVO.ORG" created.
Podemos checkear que el usuario se creó correctamente ejecutando kinit y klist:
# kinit demasiadovivo
Password for demasiadovivo@DEMASIADOVIVO.ORG:
# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: demasiadovivo@DEMASIADOVIVO.ORG
Valid starting Expires Service principal
06/22/11 14:07:18 06/23/11 00:07:18 krbtgt/DEMASIADOVIVO.ORG@DEMASIADOVIVO.ORG
renew until 06/23/11 14:07:14
Lo que hicimos fue obtener un ticket para el usuario demasiadovivo (con kinit), y luego listar los tickets cacheados en la máquina (klist). Como pudieron ver, /tmp/krb5cc_0 es nuestro ticket. Con klist se pueden ver varias propiedades de los tickets, como algoritmos de encripción (-e), direcciones en las credenciales (-a), etc. kinit también acepta varios parámetros, como tiempo de vida (-l), hora de inicio (-s), renovar un ticket (-R), etc.


Creación de usuarios en LDAP

Si bien podríamos utilizar la autenticación LDAP para autenticar los usuarios, lo mejor es utilizar el confiable kerberos, y dejar LDAP para almacenar los datos de usuarios, grupos y demás.
Como vimos anteriormente, debemos almacenar ciertos atributos del usuario que normalmente estarían en /etc/passwd. Dado que la autenticación la realizamos con kerberos, no es necesario almacenar el password del usuario, aunque esto podría hacerse si se quisiera autenticar con LDAP.

Existe un RFCs (RFC 2307), que describe un mecanismo para mapear entidades UNIX al estándar X.500, para que los atributos se puedan resolver utilizando LDAP. Si bien este documento es experimental, se utiliza ampliamente en el mundo UNIX.
La librería NSS-LDAP utiliza este mapeo para resolver los atributos del usuario, por lo tanto es el formato que debemos adoptar para crear las entradas en el LDAP. OpenLDAP trae esquemas predefinidos para este mapeo, los cuales pueden encontrar en /etc/ldap/schema/nis.schema. Los objectClass que utilizaremos comúnmente son posixAccount, shadowAccount y posixGroup.

Veamos cómo se mapea cada campo del /etc/passwd en atributos LDAP:
  • login name = uid
  • user ID = uidNumber
  • group ID = gidNumber
  • nombre de usuario = cn para el nombre y sn para el apellido.
  • directorio home = homeDirectory
  • shell = loginShell (opcional)
Los usuarios que deseemos autenticar con Kerberos y LDAP deberán tener definida una entrada con estos datos, en la unidad organizativa (OU) People, y con posixAccount como objectClass. El Distinguished Name (DN) de cada usuario tendrá el formato uid=,ou=People,dc=demasiadovivo,dc=org.

Por su parte, el equivalente de atributos para cada grupo es el siguiente:

  • nombre del grupo = cn
  • contraseña = userPassword (opcional)
  • group ID = gidNumber
  • lista de usuarios = memberUid
Los grupos deben situarse en la OU Group y con posixGroup como objectClass. El DN se arma utilizando cn=,ou=Group,dc=demasiadovivo,dc=org.

Ahora que contamos con los datos suficientes para crear un usuario, creemos el archivo user1.ldif donde pondremos la definición de nuestro primer usuario y grupo.

dn: cn=Administrador_Seguridad,ou=Group,dc=demasiadovivo,dc=org cn: Administrador_Seguridad gidNumber: 2000 objectClass: top objectClass: posixGroup
dn: uid:demasiadovivo,ou=People,dc=demasiadovivo,dc=org uid: demasiadovivo uidNumber: 2000 gidNumber: 2000 cn: Victor objectClass: top objectClass: person objectClass: posixAccount objectClass: shadowAccount loginShell: /bin/bash homeDirectory: /home/demasiadovivo
En la definición encontramos varios objectClass. Para el caso de grupos, utilizamos la ya mencionada posixGroup, mientras que para usuarios usamos person, posixAccount, y shadowAccount. La clase person nos permite agregar información atributos como número de teléfono y descripción. Por su parte, shadowAccount permite agregar atributos concernientes al tratamiento de passwords, como el password en si, fecha de último cambio, y resto de información que se encuentra en /etc/shadow. Si bien no almacenaremos passwords en LDAP, sí resulta útil guardar el resto de la información referente al mismo.

Para agregar el usuario, ejecutamos ldapadd de la siguiente manera:
ldapadd -c -x -D cn=admin,dc=demasiadovivo,dc=org -W -f user1.ldif
Podemos verificar los datos recien ingresados con:

ldapsearch "(uid=demasiadovivo)" -x
y
ldapsearch "(cn=Administrador_Seguridad)" -x


Configurar PAM para utilizar kerberos

Este paso ya se explicó en el artículo del mismo nombre que pueden encontrar aquí


Configurar NSS para utilizar LDAP

Como ya adelante en las secciones anteriores NSS (Name Service Switch) es una funcionalidad provista por la librería GNU C para independizar a las aplicaciones de la ubicación de los servicios.
Antíguamente los datos se buscaban en archivos locales como /etc/passwd, /etc/group, /etc/hosts, etc, pero con el crecimiento de tecnologías de base de datos centralizadas como DNS, NIS, LDAP, etc, se hizo evidente la necesidad de contar con un servicio que abstraiga al programa de la ubicación de los datos. Por ello se creó NSS, basándose en un método utilizado por Sun en Solaris 2.
NSS permite al administrador configurar dónde se encontrarán los datos de diferentes bases de datos a través del archivo nsswitch.conf. Incluso se puede establecer un orden sobre qué base de datos consultar primero. El programa sólo utiliza una llamada al sistema y se olvida de donde se encuentran los datos. Gracias a esto, cambiar de base de datos es muy simple. Este caso es muy similar al de PAM.
Entre las bases de datos que podemos configurar tenemos:
  • password: información de usuarios. Default /etc/passwd
  • group: información de grupos de usuarios. Default: /etc/group
  • shadow: contraseñas de usuario. Default: /etc/shadow
  • hosts: nombres de computadoras. Default: /etc/hosts
  • network: nombres de redes. Default: /etc/networks
 Algunas posibles fuentes de datos son:
  • files: archivos, por ejemplo /etc/passwd
  • compat: se puede usar para traer información de usuarios y grupos en archivos con nueva sitaxis como /etc/passwd, /etc/shadow, /etc/group
  • dns: obtener la información de hosts de servidores DNS
  • ldap: traer los datos del directorio LDAP
 Para utilizar LDAP como base de datos de usuarios, deberemos instalar la librería NSS correspondiente. Antes de hacer este paso, es recomendable hacer un backup de los archivos /etc/pam.d/{common-auth,common-account,common-password,common-session}:
cp /etc/pam.d/{common-auth,common-account,common-password,common-session} /root/backup
Luego entenderán porque es necesario este backup.
Ahora si, instalamos la librería libnss-ldapd que provee servicios LDAP para NSS, y el demonio nslcd que es el encargado de realizar las búsquedas LDAP para los procesos que quieran información de usuarios, grupos, etc:
# apt-get install libnss-ldapd nslcd
NOTA: Algo a tener en cuenta aquí es utilizar libnss-ldapd y no libnss-ldap. Con la segunda no pude realizar autenticación de usuarios utilizando GSSAPI, a pesar de mucho intentarlo. libnss-ldapd es más nueva y mejora varias cuestiones de libnss-ldap.

En la instalación, debconf requerirá algunos datos de configuración.
Para el paquete libnss-ldapd:

  • Servicios a configurar para que utilicen LDAP. Los valores por defecto sirven para la mayoría de los casos: passwd, shadow, y group.
 Por su parte, el paquete nslcd solicita:
  • URI del servidor LDAP: ldap://ldap.demasiadovivo.org/
  • DN base para las búsquedas ldap: dc=demasiadovivo,dc=org
El siguiente paso es configurar NSS para que utilice LDAP para buscar información de usuarios. Para esto, hay que editar el archivo /etc/nsswitch.conf para que quede de la siguiente manera:
passwd: files ldap group: files ldap shadow: files ldap
hosts: files dns networks: files
protocols: db files services: db files ethers: db files rpc: db files
netgroup: nis
Se puede observar que el sistema intentará resolver los datos de usuario localmente, y si no puede, consultará al servidor ldap.
Como el demonio nscd cachea los valores, es necesario reiniciarlo:

# /etc/init.d/nscd restart
Para testear la configuración, se puede utilizar el comando getent. Este comando permite obtener entradas de la base de datos administrativa, esto incluye passwd, group, hosts, services, protocols y networks.
La mejor forma de ver que todo está funcionando es obtener los datos de un usuario que esté declarado en el servidor LDAP, pero que no esté localmente. Si por ejemplo el usuario demasiadovivo no se encuentra declarado en el /etc/passwd local y si en el LDAP, pueden probar el siguiente comando:

$ getent passwd demasiadovivo demasiadovivo:x:2000:2000:Victor:/home/demasiadovivo:/bin/bash
Pueden corroborar que el usuario no existe localmente mirando /etc/passwd.
Si ejecutan "getent passwd" sin un nombre de usuario, pueden ver la base de datos completa de usuarios, que incluye a los locales y a los de LDAP.


Prueba de login

Bien, ya tenemos todo lo necesario para ver si nuestro sistema centralizado de usuarios está funcionando correctamente. Veamos los pasos que seguimos hasta aquí:

  • instalamos kerberos
  • instalamos LDAP
  • dimos de alta al usuario demasiadovivo en kerberos y configuramos un password
  • dimos de alta al usuario demasiadovivo en LDAP, donde pusimos toda la información necesaria del /etc/passwd
  • configuramos PAM en la máquina cliente para que autentique utilizando kerberos. Incluso agregamos una regla en common-session para que se cree un directorio home para los usuarios que no existan localmente.
  • configuramos NSS en la máquina cliente para busque los datos del usuario en LDAP
Ufff, fue mucho trabajo, pero si todo fue bien, estamos al borde de la gloria (?!). La prueba? loguearnos con el usuario demasiadovivo en la máquina cliente y ver si anda =D
machine login: demasiadovivo Password: Linux machine 2.6.32-5-amd64 #1 SMP Mon Mar 7 21:35:22 UTC 2011 x86_64
The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Creating directory '/home/demasiadovivo' machine@demasiadovivo:~$ id uid=2000(demasiadovivo) gid=2000(Administrador_Seguridad) grupos=2000(Administrador_Seguridad)
yeah! como se puede observar, el sistema automáticamente creó el directorio home y asignó los IDs correspondientes al usuario, como se declaró en la correspondiente entrada LDAP.

CUIDADO!
Algo que hay que tener muy en cuenta es que kerberos utiliza verificación de host resolviendo el nombre de la máquina desde donde nos conectamos. Por ello es necesario tener definido el nombre de la máquina y el mapeo IP-nombre (registro PTR) en el servidor DNS. Caso contrario, pueden encontrarse con el siguiente error en /var/log/auth.log:

pam_krb5(login:auth): (user demasiadovivo) credential verification failed: Hostname cannot be canonicalized

Referencias

- Authentication against LDAP servers
- PADL Software Pty Ltd - nss_ldap
- OpenLDAP installation on Debian
- MIT Kerberos installation on Debian
- OpenLDAP provider with MIT Kerberos V on Debian squeeze
- OpenLDAPServer
- SingleSignOn
- The POSIX API
- Linux NSS (libnss) and nss_ldap problems and possible solutions
- LDAPClientAuthentication
- LDAP Implementation HOWTO - 2. LDAP authentication using pam_ldap and nss_ldap
- opensolaris - About the Name Service Switch
- NSS Wiki
- Linux Authentication Using OpenLDAP, Part One
- ZYNTRAX - Chapter 5. OpenLDAP Samples - 5.2 Securing the Directory
- SEAM Error Messages and Troubleshooting
- Kerberos and LDAP
- Replacing NIS with Kerberos and LDAP HOWTO
LDAP System Administration - A.2 Name Service Switch (NSS)
Configurar PAM para utilizar kerberos
En artículos anteriores se explicó cómo funciona kerberos y la forma de utilizarlo en GNU/Linux. Las workstations con Linux instalado pueden autenticar sus usuarios contra servidores de este tipo, ya sea que los mismos utilicen Linux, Windows (Active Directory), o cualquier otro SO que implemente el estándar. La configuración descripta a continuación es la misma sin importar sobre qué plataforma se implemente el servicio kerberos. Es decir, se puede utilizar, por ejemplo, para autenticar clientes Linux contra el servicio Active Directory de Windows.

Para la autenticación con kerberos, hay que instalar el módulo de PAM correspondiente, en todos los clientes. En debian, el paquete se denomina libpam-krb5:
# apt-get install krb5-{config,user} libpam-krb5
Durante la instalación, debconf requerirá algunos datos para continuar:
- el nombre del realm: DEMASIADOVIVO.ORG
- servidores kerberos para el realm, separados con espacios.
- servidor administrativo para el realm, para administrar cambio de contraseña.
Estos son los mismos datos que configuramos al instalar el servidor kerberos. Toda esta configuración se puede cambiar en el archivo /etc/krb5.conf.
En este archivo, como se explicó en la instalación del servidor, pueden eliminar todos los realms que aparecen en la instalación default (athena, mit, etc), y deberán agregar el dominio de su realm en la sección domain_realm:
[domain_realm]
.demasiadovivo.org = DEMASIADOVIVO.ORG
demasiadovivo.org = DEMASIADOVIVO.ORG
Luego de que se instala el módulo de kerberos, debian automáticamente establece en PAM que la autenticación de usuarios debe utilizar este protocolo. Si no están utilizando debian, tal vez requieran una configuración adicional para empezar a utilizarlo.

Veamos entonces cómo deberían quedar cada uno de los archivos de PAM, y el significado de cada configuración:

/etc/pam.d/common-account
account [success=1 new_authtok_reqd=done default=ignore] pam_unix.so
account requisite pam_deny.so
account required pam_permit.so
account required pam_krb5.so minimum_uid=1000
Se puede observar que este archivo es muy similar a cuando se utiliza sólo autenticación Unix. Para agregar la autenticación de kerberos, se agrega una línea final que invoca el módulo pam_krb5 con el argumento minimum_uid=1000.
En este caso, el sistema invoca tanto el módulo pam_unix como pam_krb5 como required, lo cual implica que si alguno de estos falla, la operación falla. El argumento "minimum_uid=1000" hace que la autenticación kerberos se aplique a los usuarios cuyo user ID sea mayor a 1000. Esto permite tener cuentas locales como la de root (uid=0), la cual no autentica contra kerberos.

/etc/pam.d/common-auth
auth [success=2 default=ignore] pam_krb5.so minimum_uid=1000
auth [success=1 default=ignore] pam_unix.so nullok_secure try_first_pass
auth requisite pam_deny.so
auth required pam_permit.so
En este archivo podemos ver como funciona la autenticación propiamente dicha. Primero se intenta autenticar con kerberos a los usuarios cuyo uid es mayor o igual a 1000. Si esto tiene éxito, se salta a la línea pam_permit (success=2) y el usuario puede entrar. Si la autenticación kerberos falla, se intenta con la autenticación unix tradicional, permitiendo password en blanco (nullok_secure), y utilizando el mismo password que se utilizó en la autenticación kerberos (try_first_pass). Esto último se hace para que el sistema no requiera el password dos veces cuando la autenticación kerberos falla. Si ninguna de las autenticaciones es exitosa, se niega el acceso (pam_deny).

/etc/pam.d/common-pasword
password requisite pam_krb5.so minimum_uid=1000
password [success=1 default=ignore] pam_unix.so obscure use_authtok try_first_pass sha512
password requisite pam_deny.so
password required pam_permit.so
Para el cambio de password se utiliza como requisito pam_krb5 con uid mayor igual a 1000. Si esto falla, el password no se actualiza. Si el password kerberos se actualiza correctamente, se intenta actualizar el password local, utilizando el mismo pass ingresado para kerberos (use_authtok). El resto de los argumentos de pam_unix son los mismos que cuando se utiliza autenticación tradicional, donde obscure checkea fortaleza del pass, y sha512 es el algoritmo para hashear el pass.
Algo a tener en cuenta aquí es que si la actualización del password local falla, la operación falla aunque el password kerberos no haya tenido problemas.

/etc/pam.d/common-session
session [default=1] pam_permit.so
session requisite pam_deny.so
session required pam_permit.so
session optional pam_krb5.so minimum_uid=1000
session required pam_unix.so
Finalmente en el archivo de session encontramos una regla adicional y opcional que es la de kerberos. Algo interesante que podemos hacer en este archivo es agregar una regla para la creación del directorio home del usuario.
Si creamos un usuario en kerberos y no en la máquina cliente, cuando éste intente ingresar, el sistema arrojará error si el home no existe, porque este directorio no se crea al agregar el usuario.
Para esto, existe un módulo denominado pam_mkhomedir. Este módulo crea el directorio home del usuario cuando éste se loguea por primera vez. Si el directorio ya existe, no hace nada. Un argumento interesante para este módulo es skel, que permite especificar el esqueleto del directorio home.
Podemos modificar el archivo anterior para agregar esta funcionalidad, de la siguiente manera:
session [default=1] pam_permit.so
session requisite pam_deny.so
session required pam_permit.so
session required pam_mkhomedir.so skel=/etc/skel/
session optional pam_krb5.so minimum_uid=1000
session required pam_unix.so
Con esto, la próxima vez que se autentique un usuario en el cliente configurado, éste utilizará kerberos en lugar del tradicional sistema Unix. Claro que el usuario a utilizar debe estar previamente creado en el servidor kerberos.
Una vez autenticados, se puede ver el ticket generado ejecutando klist:
$ klist
Ticket cache: FILE:/tmp/krb5cc_1000_s6uumi
Default principal: demasiadovivo@DEMASIADOVIVO.ORG

Valid starting Expires Service principal
09/24/11 08:08:07 09/24/11 18:07:57 krbtgt/DEMASIADOVIVO.ORG@DEMASIADOVIVO.ORG
renew until 09/24/11 18:08:07
Bug en script perl al intentar actualizar debian testing
Al intentar actualizar la librería libc6 en debian testing (wheezy) encontré un problema, el cual ocasionó que todo el sistema quede inestable. apt ciclaba arrojando el error:
Use of uninitialized value $text in concatenation (.) or string at /usr/share/perl5/Text/WrapI18N.pm line 101, line 5. substr outside of string at /usr/share/perl5/Text/WrapI18N.pm line 130, line 5.
Como el proceso no se detenía, la solución fue matarlo, pero dejando varias inconsistencias en el camino.Al parecer el script en cuestión tiene un bug con una variable sin inicializar, lo que ocasiona que el proceso de actualización falle.
Al quedar libc6 roto, muchos paquetes del sistema quedaron rotos y no es posible instalar ni borrar nada hasta que el problema no se arregle. Para salvar el problema y poder terminar la instalación, mi solución fue comentar la línea problemática (101 del archivo /usr/share/perl5/Text/WrapI18N.pm):
$text = $top2 . $c . $text;
Claro que si la línea esta ahí, para algo es, pero preferí tener un problema menor a tener un sistema que posiblemente al reiniciar no arrancaría.
Una vez comentada la línea hay que reparar los paquetes rotos, lo cual se realiza con:
apt-get install --fix-broken
Al haber matado el proceso apt, puede que algún proceso haya retenido los archivos de lock y que apt se reuse a actualizar. Si este es el caso, ejecutar fuser para obtener el id de los procesos que quedaron colgados, y luego matarlos:
fuser -v /var/lib/dpkg/lock
fuser -v /var/cache/debconf/config.dat
Con esto pude terminar la instalación de libc6 sin problemas y el sistema volvió a un estado estable. Según lo que encontré en diferentes foros, este es un bug del paquete perl y varios que han intentado actualizar lo han sufrido:
http://www.linuxquestions.org/questions/debian-26/error-configuring-libc6-898757/
http://www.facepunch.com/threads/1116926-Error-when-trying-to-dist-upgrade
Por ello me pareció interesante postear mi solución, que si bien no es elegante, me salvó de una reinstalación completa. Ojalá los salve a ustedes también!
Armar servidor de logging con rsyslog y configurar dispositivos para logging remoto
Todo sistema operativo cuenta con funcionalidad para almacenar logs del sistema, aplicaciones, dispositivos, etc. Los sistemas tipo *nix cuentan con el demonio syslog, encargado de recoger los logs y almacenarlos en el lugar indicado. El servicio syslog es tan potente que, además de realizar la tarea de logging local, permite almacenar logs de dispositivos remotos a través de un protocolo propio llamado del mismo nombre y que funciona sobre UDP y TCP. La mayoría de los sistemas operativos poseen facilidades para almacenar logs en un servidor remoto.
Centralizar los logs en un servidor facilita la tarea de análisis de logs a administradores y auditores, ya que deben acceder a sólo un repositorio.
La obvia desventaja es que si hackean el servidor de logs, pueden ver los logs de toda la red. Por ello es muy importante que el servidor de logging posea una buena configuración de seguridad. Igualmente, como se detallará al final del artículo, existen varias desventajas de seguridad adicionales al utilizar este esquema.
Los sistemas *nix modernos, utilizan una versión mejorada del antiguo syslog denominada rsyslog, más confiable que el anterior y con capacidades extendidas. La siguiente explicación muestra cómo armar un servidor de logging con rsyslog, que puede aplicarse a cualquier sistema *nix. Además se incluyen los comandos para habilitar el logging remoto en dispositivos Cisco.
Toda la configuración de rsyslog se realiza a través del archivo /etc/rsyslog.conf.


Servidor rsyslog

Para convertir el demonio rsyslog en un servidor de loggeo de red debe utilizarse el plugin imudp (si se desea utilizar UDP) y/o imtcp (para TCP). Estos plugins reemplazan la opción -r de syslog ya obsoleta. El port utilizado por defecto por este servicio es el 514 para ambos protocolos.
Las líneas que se deben agregar (o descomentar) en /etc/rsyslog.conf para habilitar el logging remoto son las siguientes:
$ModLoad imudp
$UDPServerRun 514

$ModLoad imtcp
$InputTCPServerRun 514

Para que la nueva configuración entre en vigencia, debe recargarse el demonio. Una manera de no cortar el logging de forma abrupta matando el proceso (clásico restart), lo mejor es enviar una señal HungUp:
killall -HUP rsyslogd

Con esto, cualquier dispositivo de red puede enviar sus logs al servidor recién configurado, y este los añadirá a los locales del servidor. Claro que lo mejor es no mezclar logs locales con logs remotos, por lo cual se pueden configurar distintas entradas en la configuración que redirijan estos logs a otros archivos.
Las reglas para separar logs se arman en base al facility y al nivel de criticidad que va de 0 (emergencias) a 7 (debugging). Las facilities permiten indicar el origen del mensaje, y existe un número fijo de ellas. Algunos demonios y procesos del sistema operativo tienen asignados valores de facilities (por ej: kern, mail, daemon, user, etc), y aquellos que no, deben utilizar alguna de las definidas como "uso local" (local0 a local7). El usuario puede utilizar las facilities local0 a local7 para sus logs, y estas son las que se suelen utilizar para separar logs de dispositivos remotos.
El formato de las reglas es:
<facility>.<criticidad> <archivo log destino (ej /var/log/syslog)>
Tanto el facility como la criticidad pueden ser asterisco (*), indicando que abarque todo. Por ejemplo, "kern.*" envía todos los logs del kernel al archivo especificado. En el caso de utilizar asterisco en el facility, es posible utilizar la prioridad none para indicar qué facilities no incluir. Por ejemplo, existe la siguiente regla default en la configuración de rsyslog:
*.*;auth,authpriv.none -/var/log/syslog
la cual hace que todo se envíe al archivo syslog. En esa misma regla se puede observar que se agregó auth,authpriv.none para evitar que los logs de auth y authpriv se almacenen en dicho archivo. A la regla anterior se puede agregar local4.none, para luego utilizar la facility local4 en dispositivos remotos y así separar esos logs de los locales:
*.*;auth,authpriv.none;local4.none -/var/log/syslog

Además de las reglas "facility.priority", se pueden armar reglas en base a filtros, basados en distintas propiedades como IP origen, mensaje, hostname, y varias más que se pueden ver en la sección de propiedades del manual oficial de rsyslog.
Las reglas con filtros se arman de la siguiente manera:
:<propiedad>, <operación de comparación>, "valor" <archivo log destino (ej /var/log/syslog)>
donde la operación de comparación puede ser isempty, isequal, startswith, regex y eregex, como se puede observar en el manual oficial, en la sección de filtros.
Esto permite, por ejemplo, separar los logs provenientes de la dirección IP 192.168.1.15 en un archivo propio para el host con la siguiente regla:
:fromhost-ip, isequal, "192.168.1.15" /var/log/remote/192.168.1.15.log

Una vez completadas las reglas, debe recargarse el demonio rsyslogd para que tome la nueva configuración.


Separación de logs

Conociendo las bases para la configuración del servidor, es posible armar una que reciba logs de diferentes fuentes y los separe en distintos archivos.
Dado que por defecto todo va a parar a syslog, lo mejor es eliminar las facilities local* de dicha configuración y después utilizarlas en los dispositovs de red. El primer paso es editar la regla correspondiente (en /etc/rsyslog.conf) para que quede como sigue:
*.*;auth,authpriv.none;\
local0.none;\
local1.none;\
local2.none;\
local3.none;\
local4.none;\
local5.none;\
local6.none;\
local7.none -/var/log/syslog
También hay que evitar que info, notice y warning terminen en /var/log/messages
*.=info;*.=notice;*.=warn;\
auth,authpriv.none;\
cron,daemon.none;\
mail,news.none;
local0.none;\
local1.none;\
local2.none;\
local3.none;\
local4.none;\
local5.none;\
local6.none;\
local7.none -/var/log/messages
y que los mensajes de debugging terminen en /var/log/debug
*.=debug;\
auth,authpriv.none;\
news.none;mail.none;
local0.none;\
local1.none;\
local2.none;\
local3.none;\
local4.none;\
local5.none;\
local6.none;\
local7.none -/var/log/debug
La separación se puede realizar de varias maneras, una es basándose en las facilities. Para ello, a cada tipo de dispositivo se asigna una facility de las "local use" y luego se arma la configuración en base a esto, de la siguiente manera:
local3.* /var/log/remote/firewalls.log
local4.* /var/log/remote/routers.log
local5.* /var/log/remote/APs.log
local6.* /var/log/remote/switches.log
Como se ve, se utiliza local3 para firewalls, loca4 para routers, local5 para access points y local6 para switches. A esta separación se la puede mejorar utilizando distintos archivos para diferentes prioridades, pero sigue siendo muy simple y no demasiado agradable para quien revisa los logs.

Una mejor forma de separar logs es colocar los logs de cada host en un archivo separado. En la sección anterior se mostró que es posible ver de qué dirección IP viene la información y armar un archivo en base a esto, pero es muy ineficiente colocar una regla por cada host. Una forma más simple de hacerlo es utilizar templates. Con un template es posible definir el formato del nombre del archivo log a partir de alguna propiedad del mismo, como por ejemplo el hostname o IP. Para usar una propiedad es necesario colocarla entre signos de porcentaje "%".
La siguiente línea crea un template que luego se puede utilizar para especificar el nombre del archivo:
$template LogsRemotos,"/var/log/remote/%fromhost-ip%.log"
donde fromhost-ip especifica que se utilice la IP como nombre del archivo.
Para lograr que cada dispositivo loggee en un archivo separado, sólo debe agregarse lo siguiente:
:fromhost-ip, isequal, "127.0.0.1" ~
*.* -?LogsRemotos
y con ello rsyslog generará automáticamente los nombres de archivos y almacenará los mensajes en el lugar correcto. En la primer línea se descartan los logs locales, dado que los mismos se almacenan en otros archivos y no deseamos generar uno nuevo. El descarte se realiza utilizando caracter "~" en lugar de un nombre de archivo. El signo de pregunta "?" de la segunda línea indica que se utiliza un nombre de archivo dinámico, a partir del template LogsRemotos, y el guión "-" que no escriba en el archivo inmediatamente (buffering), para mejorar la performance.

Para no "ensuciar" el archivo de configuración global, es posible crear archivos dentro de /etc/rsyslog.d/ con las configuraciones deseadas. En el último ejemplo, sería posible tener un archivo denominado remote.conf con las líneas:
$template LogsRemotos,"/var/log/remote/%fromhost-ip%.log"

:fromhost-ip, isequal, "127.0.0.1" ~
*.* -?LogsRemotos


Configuracion en dispositivos Cisco con IOS

Todos los dispositivos Cisco poseen la capacidad de loggear en un servidor remoto a través de syslog. La configuración de los mismos es muy simple, sólo debe indicarse la dirección del servidor, el nivel de información a enviar y el facility a utilizar. Esto se lleva a cabo en el modo de configuración con privilegios de administrador, ejecutando los siguientes comandos (lo que se encuentra luego del // son comentarios):
(config)#logging on
(config)#logging host <IP syslog server>
(config)#logging trap informational // es el nivel de mensajes a loguear. Cada nivel incluye a todos los niveles inferiores (informational incluye error, critical, alerts, etc).
(config)#logging facility local5 // usar el facility local5 (local0... local7 son para códigos definidos por el usuario).


Configuración de clientes *nix

Lograr que un máquina que ejecuta algún sistema *nix loggee remotamente es muy simple. Sólo debe agregarse la línea mostrada a continuación en su archivo /etc/rsyslog.conf (o /etc/syslog.conf si no posee rsyslog):
*.* @<IP remota>
El @ indica que deben enviarse los mensajes a un host remoto en lugar de almacenarlos en un archivo local. Con un sólo @ rsyslog utiliza UDP como protocolo de transporte, y si se desea utilizar el más confiable TCP deben colocarse dos:
*.* @@<IP remota>


Restringir el acceso

El protocolo no posee un mecanismo de autenticación que restrinja qué dispositivo puede almacenar logs en el servidor, permitiendo que cualquiera pueda escribir en el mismo, con el riesgo de que un atacante genere un Denial of Service si el disco se llena o la cantidad de datos transmitida satura el ancho de banda.
Una forma de limitar el acceso es utilizando un firewall y rechazar toda conexión que no venga de una dirección de red autorizada. Esta mejora no es la panacea, dado que suplantar una dirección de red es muy simple, pero al menos es algo.


Conclusiones

rsyslog es un sistema muy flexible, simple y consolidado. El protocolo se encuentra en prácticamente todo dispositivo decente, por lo cual la compatibilidad está garantizada. Lo que se describió en este artículo muestra sólo una parte de la potencia de esta herramienta, por lo cual se recomienda una atenta lectura de su manual oficial.
Probablemente su problema más grave es la pobre seguridad que provee. Entre algunos de los problemas más graves se encuentran:
  • Posibilidad de DoS, como se explicó en la sección anterior.
  • UDP es poco confiable: los paquetes se pueden perder y nadie se enteraría. syslog por TCP mejora este aspecto, pero no todos los dispositivos lo implementan.
  • No hay autenticación, permitiendo que cualquiera envíe logs al servidor.
  • No existe confidencialidad de los datos enviados.
  • No hay integridad de los datos (alguien podría modificarlos en el camino - MITM)
Algunos de estos problemas pueden solucionarse si se utiliza IPSec en la capa inferior, pero no es una solución que forme parte del protocolo.


Referencias

- rsyslog doc - rsyslog.conf configuration file
- Syslog Configuration and /etc/syslog.conf
- How To Set Up A Debian Linux Syslog Server
- FreeBSD Handbook - 29.11 Remote Host Logging with syslogd
- Catalyst 2950 - Configuring System Message Logging
- Practical UNIX & Internet Security - 10.5 The UNIX System Log (syslog) Facility
- Softpanorama - Centralised Syslog Server
- PIX 501 Logging to Syslog Server
Interfaz wireless desactivada al utilizar power injector en APs Cisco
Cuando se utiliza el AP con power injector instalado, puede suceder que la interfaz wireless se encuentre deshabilitada. Esto se puede observar en los logs del dispositivo ejecutando el comando:
#show logging
El error que se encontrará será similar al siguiente:
*Feb 28 21:00:10.622 GMT-3: %LINEPROTO-5-UPDOWN: Line protocol on Interface Dot11Radio0, changed state to down
*Feb 28 21:01:09.497 GMT-3: %CDP_PD-2-POWER_LOW: All radios disabled - LOW_POWER_CLASSIC_NO_INJECTOR_CONFIGURED WS-C2924-XL (00d0.bbd6.1b4e)
*Feb 28 21:01:09.497 GMT-3: -Verify the required power-injector is installed on this port: WS-C2924-XL(Fas 0/13).
*Feb 28 21:01:09.497 GMT-3: -If a power-injector is installed, issue the command:"power inline negotiation injector installed"
En este caso, el AP indica que no cuenta con la energía necesaria y por eso deshabilita la interfaz wireless. El problema es que no detecta que se encuentra energizado mediante power injector.

Para solucionar el problema, el AP necesita que se explicite la MAC address del port del switch en el que se encuentra conectado el power injector. Dicha MAC se puede observar en el log anterior, en la línea:
%CDP_PD-2-POWER_LOW: All radios disabled - LOW_POWER_CLASSIC_NO_INJECTOR_CONFIGURED WS-C2924-XL (00d0.bbd6.1b4e)
La dirección en que el injector se encuentra conectado se debe ingresar a través de la configuración del switch, ejecutando el siguiente comando:
(config)#power inline negotiation injector 00d0.bbd6.1b4e

Luego de esperar un minuto o dos, la interfaz de radio debería encontrarse habilitada nuevamente. Para checkearlo se puede ejecutar el comando:
#show interfaces dot11Radio 0
y la respuesta debe ser:
Dot11Radio0 is up, line protocol is up