30 diciembre 2008

Electronic vaulting: Mashup con fuse-sshfs, truecrypt y qdsync

¿Quieres vulnerar la política de seguridad de tu organización para robar información crítica y vendérsela a la competencia para poder pagar la hipoteca de una forma más cómoda?

Si además de poder pasar las fronteras árabes con PDFs más pesados de lo normal decides que según se haga un cambio en un directorio concreto, quieres ser el primero en enterarte de qué es lo que se ha modificado, sigue este post y sacia tu curiosidad.

Decir que la idea inicial era sincronizar un directorio "en tiempo real" con un espacio que físicamente se encuentra en otra localización. Sentadas las bases, lo deseable es lograr que cada vez que se realice un cambio en un directorio, queden reflejados en un lugar remoto (la finalidad puede ser como un backup online o electronic vaulting para evitar catástrofes como las del edificio Windsor, replicar logs de forma remoto para que sirvan de evidencia para propósitos forenses, robo selecto de información, etc,...)

Importante es que la información quede almacenada de forma cifrada en el destino remoto, con controles de acceso sólidos, así como que el canal de comunicación y sincronización también sea cifrado y autenticado.

Manos a la obra y planifiquemos (como nos decían los compradores de Auna) cómo hacerlo. Necesitamos un repositorio remoto accesible 24 horas (en este caso un servidor linux con el servicio SSH funcionando), un canal de comunicación cifrado y autenticado (SSH cumple perfectamente los requisitos), para guardar los datos de forma segura en la localización remota utilizaremos un contenedor cifrado con TrueCrypt (hablamos en su día de la confidencialidad que aporta el contenedor cifrado aquí), para sincronizar directorios utilizaremos QdSync (podríamos haber utilizado rsync y sería más POSIX).

Sé positivamente que a golpe de scp podríamos haber copiado y movido ficheros, sin embargo, pienso que es mucho más cómodo utilizar un módulo fuse llamado fuse-sshfs, que permite montar un sistema de ficheros remoto mediante SSH y utilizar ese espacio para almacenar información. Ni que decir tiene que el servicio SSH no tiene por qué estar en el puerto TCP 22 sino que puede ser cualquier otro (se especifica en el momento del montaje)

Por partes:

1.-) Instalamos el módulo fuse. En mi caso en una CentOS 4.7 instalamos el paquete fuse-sshfs-2.0-1.el4.rf.i386.

2.-) Descargamos y descomprimimos QdSync (en mi caso en /opt/qdsync)

3.-) Decidimos qué directorio vamos a sincronizar puesto que hay que establecer una "marca" inicial para comparar el estado del directorio con el actual (Esto se entenderá mejor más adelante). En nuestro caso he elegido el directorio /var/motion. Para hacer la primera "marca" ejecutamos un "du -ah /var/motion > /var/index_motion"

4.-) Creamos el contenedor cifrado en local con truecrypt (importante elegir el tamaño y el sistema de ficheros que mejor se adecúen a nosotros) y lo copiamos a la ubicación remota de forma manual.

5.-) Añadimos al fichero .ssh/authorized_keys2 del directorio remoto para añadir nuestra clave pública SSH. La idea es poder comunicarnos entre ambas localizaciones con SSH with Keys de manera que sea siempre de forma no interactiva

6.-) Creamos un script como el siguiente, que realice de forma automatizada todo el proceso teniendo en cuenta posibles problemas (que la localización remota esté ya montada, que no sea accesible por SSH, etc...). En mi caso el directorio a sincronizar es /var/motion. Hemos elegido /mnt/remote para hacer el primer montaje con el sistema de ficheros SSH y /mnt/cifrado como punto de montaje para el contenedor cifrado con truecrypt desde el propio sistema de ficheros remoto.

#!/usr/bin/perl
#Script que sincroniza /var/motion con contenedor cifrado en ubicación remota
#1.- Compruebo que no está montado ya /mnt/remote

if ( `mount | grep -i remote` || `mount | grep -i cifrado`)
{
system "logger \"Algo habia montado, no hago nada mas\n\"";
}
else
{
#2.- Validamos si algo ha cambiado con lo anterior
my $temp="/tmp/syncing";
$temp.=rand(100);
system "du -ah /var/motion > $temp";
if (`diff $temp /var/index_motion` != '') #Si ha cambiado algo nos interesa sincronizar
{
my $tries=0;
while ( (`mount | grep -i remote` eq '') && ($tries < style="font-style: italic;"> `sshfs root\@200.XX.YY.ZZZ:/root/Lawrence /mnt/remote`;
#montamos el sistema de ficheros remoto
$tries++;
}

if (`mount | grep -i remote` eq ''|| $tries==10) {die "no he podido montar /mnt/remote";}
# Generamos de nuevo fichero index_motion
system "du -ah /var/motion > /var/index_motion";
#montamos el contenedor como sistema de ficheros también
system "truecrypt --non-interactive -p securitybydefault /mnt/remote/Lawrence.tc /mnt/cifrado";

#Sincronizamos
system "/opt/qdsync/src/qdsync /var/motion/ /mnt/cifrado/";

#TO DO: valida tamaño que queda en contenedor sea menor que lo que hay que sincronizar
system ("truecrypt -d /mnt/cifrado");# Desmontamos el contenedor
sleep "5";
system ("fusermount -u /mnt/remote");# Desmontamos el sistema de ficheros remoto
}
unlink ($temp);


7.-) Añadimos una línea en el cron que cada minuto ejecute el script anterior. También se puede ejecutar dicho script como demonio y controlar el tiempo cada X segundos de forma manual


De esta manera, cada minuto se ejecutará el script anterior y, si ha habido algún cambio en el directorio seleccionado (o alguno de sus subdirectorios) se montará y sincronizará de forma segura.

6 comments :

Anónimo dijo...

Muy interesante. Hace poco yo también hablé sobre cómo utilizar sshfs para montar directorios remotos de una forma 'automática', aunque vuestro artículo es mucho más completo ya que incluís la parte de sincronización.
Saludos!

Lorenzo Martínez dijo...

@dGil, efectivamente, acabo de leer el artículo que escribiste al respecto sobre Mac OS X.

Muy interesante también las opciones de optimización que añades a la hora de hacer el montaje "-o auto_cache,reconnect" lo añadiré a mi script.

Evidentemente me queda por añadir otras opciones como el que envíe un correo diciendo que ha sido necesario hacer una sincronización por haber cambios en los ficheros (realmente me llega igual puesto que se ejecuta con cron :-D). También se puede hacer un índice de cada fichero y con MD5 para cuando un fichero existente es modificado incluso en un sólo bit...

En fin... por añadir funcionalidad que no quede:-D

Anónimo dijo...

Interesantísimo!!!
Salu2

FErArg dijo...

Buenísimo e Impecable artículo!

lain dijo...

Interesantísimo!!!
Salu2

dGil dijo...

Muy interesante. Hace poco yo también hablé sobre cómo utilizar sshfs para montar directorios remotos de una forma 'automática', aunque vuestro artículo es mucho más completo ya que incluís la parte de sincronización.
Saludos!