lunes, 8 de julio de 2013

Tutorial: Restaurar una unidad de RAID con un disco de menor capacidad.

Hace mucho que no escribo, así que decidí agregar un artículo técnico que le dé algo de valor a este intento de blog, haciendo que no parezca abandonado. Acá les dejo un nuevo tutorial entonces. Disfrútenlo.


Siempre que instalo un servidor me gusta poder utilizar hardware de buena calidad, aunque a veces los clientes quieren aprovechar equipamiento que no puede utilizarse con la última versión de ese conocido "sistema operativo de escritorio que ahora pretende convertir un PC en un celular" (practicamente cualquier cosa fabricada antes del 2008), lo cual muchas veces lleva a que se trabaje con equipamiento de cierta edad y/o de confiabilidad dudosa, y en algunos casos cuya obsolescencia representa un riesgo a corto o mediano plazo, dado que es dificil encontrar piezas de reemplazo para efectuar reparaciones básicas y mantener su ciclo de funcionamiento más allá del ya definido por el fabricante.

Supongo que siendo que en Uruguay no se fabrican computadoras ni componentes, no es dificil de entender que todos queramos que nuestro hardware supere su expectativa de vida, limitada por la obsolescencia planificada a la que es sometido por los fabricantes...

Independientemente de la calidad del hardware disponible, siempre exijo que se cumplan ciertos requisitos que disminuyen la probabilidad de fallos terminales en los equipos, como por ejemplo unidades de disco redundantes (RAID).

A pesar de mis intentos de obtener lo que considero esencial siempre, con frecuencia sucede que cuando me dan los equipos para comenzar la instalación, alguien olvidó agregare el disco adicional para armar el RAID, con lo cual a veces se generan esperas innecesarias. En ese caso, suelo crear las unidades de RAID por software en forma independiente a la instalación, e instalar luego, haciendole creer al sistema que está usando una unidad de RAID degradada. Eso me permite instalar el servidor sin esperas, y luego solo agregarle el disco faltante reconstruyendo las unidades de RAID cuando las condiciones así lo permitan (muchas veces estando los servidores en producción).

Para crear las unidades de RAID antes de instalar el sistema operativo, simplemente se carga un CD/DVD de rescate, se crean las particiones y luego se crean las unidades de RAID necesarias con la herramienta mdadm:
mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sda2 missing
Esta línea de comandos permite crear una unidad de RAID de nivel 1 por software, formado por dos unidades de disco (en realidad, formado por particiones de los discos), pero declarando la segunda partición como "no existente". De esa forma, aseguramos la creación de la unidad de RAID sin necesidad de tener los dos discos duros instalados.

Una vez que vamos a instalar el sistema operativo, lo único que tenemos que tener en cuenta es que utilizaremos como particiones las unidades de RAID creadas (sean cuantas sean). Cuando recibimos el disco faltante, simplemente lo particionamos y reconstruimos las unidades de RAID para que las mismas queden en el estado de consistencia que las hace útiles. Si no recibimos el otro disco duro, simplemente podemos dejar el servidor con las unidades degradadas, aunque obviamente la falta de redundancia hará que cualquier fallo físico en el único disco que el servidor tiene sea fatal para el sistema, o por lo menos, genere un downtime no programado, algo que no es precisamente apreciado por clientes y usuarios.

Hace unos días tuve que instalar un servidor que había traído un único disco duro de 80 GB (específicamente un Western Digital WDC WD800BD-22JM, de exactamente 80.026.361.856 de bytes de espacio disponible).

Decidí no esperar por el segundo disco, así que particioné el disco e instalé el sistema operativo, usando la técnica de creación de unidades de RAID L1 por software manualmente. Esta técnica dejó el sistema con este "layout":
srv:~ # fdisk -l
Disk /dev/sda: 80.0 GB, 80026361856 bytes
255 heads, 63 sectors/track, 9729 cylinders, total 156301488 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x4e3acf1a

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048      411647      204800   83  Linux
/dev/sda2          411648     8800255     4194304   fd  Linux raid autodetect
/dev/sda3         8800256   156301487    73750616   fd  Linux raid autodetect
La primera partición la uso para el /boot (cerca de 200MB), y las otras las utilizo como particiones origen para crear dos unidades de RAID separadas, una para el raiz del sistema (75 GB)y la otra como SWAP (4 GB).

Las unidades de RAID, una vez creadas, son estas:
srv:~ # cat /proc/mdstat
Personalities : [raid0] [raid1] [raid10] [raid6] [raid5] [raid4]
md0 : active raid1 sda3[0]
      73749520 blocks super 1.2 [2/1] [U_]
      bitmap: 1/1 pages [4KB], 65536KB chunk

md1 : active raid1 sda2[0]
      4193268 blocks super 1.2 [2/1] [U_]
      bitmap: 1/1 pages [4KB], 65536KB chunk

unused devices: 
srv:~ #
Todo estaba perfecto, hasta que recibí el segundo disco... un Hitachi HDS728080PLA380 (de 80.000.000.000 de bytes de capacidad).

Esto representa un verdadero problema, dado que más allá de las obvias diferencias de marca y modelo, hay una diferencia significativa en la capacidad del disco, lo cual afecta la viabilidad del proceso de reconstrucción. Hacen falta 26361856 de bytes para poder considerar usar ese disco como destino de las unidades de RAID, y mantener el mismo exacto layout, como debería ser el caso ideal.

Otro detalle que cabe tomar en cuenta es que al ser distintos los discos, la performance se podría ver afectada por la diferencia de velocidades de acceso, lectura, escritura y búsqueda entre los discos, sin contar con el ancho de banda y la capacidad de los buffers. Básicamente, al igual que en una red donde participan dos dispositivos con diferentes capacidades de transferencia, el más lento es el que establece los niveles máximos alcanzables, así que la performance global dependerá, obviamente, del disco más lento.

Como prueba base para saber cual de los dos discos es el más lento (suponiendo que eso fuera realmente una condición determinante), se puede usar la herramienta hdparm:
srv:~ # hdparm -tT /dev/sda

/dev/sda:
 Timing cached reads:   5322 MB in  2.00 seconds = 2663.04 MB/sec
 Timing buffered disk reads: 174 MB in  3.02 seconds =  57.65 MB/sec
srv:~ # hdparm -tT /dev/sdb

/dev/sdb:
 Timing cached reads:   5308 MB in  2.00 seconds = 2656.07 MB/sec
 Timing buffered disk reads: 168 MB in  3.03 seconds =  55.49 MB/sec
srv:~ #
Como puede verse, existe una leve diferencia en la velocidad de transferencia, aunque no es tan grave como para ser un factor determinante en cuanto a la viabilidad del disco en sí, o sea que el problema se reduciría solo a la diferencia de capacidad.

Debe notarse que el problema de la diferencia de tamaños en los discos no sería tan importante si se hubiera utilizado LVM, cosa que no se hizo dado que el servicio que este equipo provée es el de interconexión de redes (se trata de un router con capacidades avanzadas de firewalling) y no se espera que el esquema de particionamiento o las necesidades de almacenamiento cambien en el tiempo. LVM provée flexibilidad en el uso de las unidades de almacenamiento, pero para un equipo cuyo sistema de almacenamiento no va a cambiar, no es extremadamente necesario utilizarlo.

Llegado a este punto, pude simplemente descartar el disco y pedir otro que fuera de mayor capacidad, pero preferí hacer de este problema una oportunidad educativa para mi y para otros, así que decidí elaborar un procedimiento que me permitiera utilizar este disco de todas maneras.

ADVERTENCIA: El procedimiento que está a punto de leer asume que el operador tiene sólidos conocimientos técnicos sobre el uso de ciertas herramientas que pueden ser peligrosas para el sistema en caso de un error inadvertido. Niños, no lo hagan en sus casas sin la compañía, el consejo o (cómo mínimo) el teléfono de un sysadmin hábil a mano... y por sobre todas las cosas, si meten la pata, ¡no sucumban al pánico!

Las reglas que decidí que regirían el procedimiento son las siguientes:
  1. Siendo que el servidor está en producción, el procedimiento debe realizarse sin afectar el servicio que el mismo provee.
  2. Como el disco principal es mayor que el nuevo disco, es imperativo modificar el formato de las particiones del disco principal para organizar el espacio disponible y que las particiones queden iguales en los dos discos. Esto ademas proveerá elegancia a la solución, dado que el formato de las particiones quedará lo más parecido posible.
  3. El procedimiento debe poder ser ejecutado en forma remota, de manera de poder ser realizado en cualquier horario, sin representar un problema para mi o para el cliente.
Como el servidor está en producción, no es posible disminuir el tamaño de la partición raiz del sistema para que quede igual al espacio que tendría la partición correlativa del segundo disco (que sería la solución más simple), así que decidí modificar la partición que correspondería a la unidad RAID asignada al SWAP (/dev/md1, la cual utiliza la partición /dev/sda2), haciendo que su tamaño disminuya como para poder compensar la diferencia de tamaño entre los discos y permitir crear una partición en el disco /dev/sdb de tamaño suficiente como para ser capaz de asignarse a /dev/md0, permitiendo la reconstrucción de la unidad.

El procedimiento detallado sería este:

  1. Crear un archivo de SWAP capaz de compensar la falta que hará la desactivación de la unidad de RAID de 4 GB asignada al SWAP actualmente (/dev/md1).
  2. Activar el archivo de SWAP y desactivar el SWAP al que está asociada la unidad /dev/md1.
  3. Desactivar la unidad /dev/md1, para poder modificar el formato de las particiones del disco /dev/sda.
  4. Hacer el cálculo de cual sería la posición (sector del disco) en la que debería terminar la partición /dev/sda2 para permitir la creación de las particiones /dev/sdb2 y /dev/sdb3 con un tamaño apropiado para ser utilizadas como particiones integrantes de las unidades /dev/md1 y /dev/md0 respectivamente.
  5. Eliminar la partición /dev/sda2.
  6. Crear la partición /dev/sda2, con el nuevo tamaño calculado. Esto dejaría un espacio "libre" entre el final de la partición /dev/sda2 y el inicio de /dev/sda3, el cual será igual a la cantidad de bytes faltantes en el disco /dev/sdb para llegar al tamaño de /dev/sda.
  7. Crear las particiones correlativas en el disco /dev/sdb
  8. Crear la nueva unidad de RAID /dev/md1.
  9. Configurar /dev/md1 como SWAP nuevamente.
  10. Insertar la partición /dev/sdb3 en la unidad de RAID /dev/md0, reconstruyendo la partición y obteniendo como resultado final la redundancia que se espera que un sistema como este tenga.
Habiendo definido entonces el procedimiento, ponemos manos a la obra. Todo el proceso lo ejecuté conectado vía SSH al sistema, en forma remota. Cabe notar que he coloreado en amarillo los comandos que ejecuté, de forma de facilitar la lectura:

1) Crear un archivo de SWAP

Primero verificamos el tamaño actual del SWAP y el uso que el sistema le está dando:
srv:~ # free
             total       used       free     shared    buffers     cached
Mem:       2052948    1392436     660512          0     128200     788968
-/+ buffers/cache:     475268    1577680
Swap:      4193264     356468    3836796
Como puede verse, hay poco uso de SWAP, aunque no es despreciable, así que no va a haber necesidad de que el sistema "transvase" demasiada información desde el SWAP actual al nuevo archivo que crearemos una vez que lo configuremos. Debe considerarse que un sistema en producción jamás debe quedar sin SWAP, aunque en un momento dado se observe que el mismo no lo está utilizando.

Creamos el archivo que utilizaremos como SWAP momentáneamente. Para este caso en particular, viendo que no se estaba utilizando la totalidad del SWAP, lo hacemos de 2G de capacidad. Adicionalmente, lo formateamos como tal:
srv:~ # dd if=/dev/zero of=/swap.dat bs=2G count=1
0+1 records in
0+1 records out
2147479552 bytes (2.1 GB) copied, 155.499 s, 13.8 MB/s
srv:~ # mkswap /swap.dat
Setting up swapspace version 1, size = 2097144 KiB
no label, UUID=12105ad3-d781-478f-a967-d1597b92ea78

2) Activacion del SWAP del archivo y desactivación del SWAP provisto por la unidad /dev/md1

srv:~ # swapon /swap.dat
srv:~ # free
             total       used       free     shared    buffers     cached
Mem:       2052948     560468    1492480          0       3388     482876
-/+ buffers/cache:      74204    1978744
Swap:      6290408     356468    5933940
Llegados a este punto, podemos desasociar la unidad de RAID /dev/md1 del SWAP:
srv:~ # swapoff /dev/md1
srv:~ # free
             total       used       free     shared    buffers     cached
Mem:       2052948     890400    1162548          0       3448     458016
-/+ buffers/cache:     428936    1624012
Swap:      2097144          0    2097144
srv:~ #
Ahora que liberamos la unidad de RAID, podemos trabajar tranquilos de que no hay ningún proceso en el sistema que la esté utilizando.

4) Desactivar la unidad /dev/md1

srv:~ # mdadm -S /dev/md1
mdadm: stopped /dev/md1
srv:~ # cat /proc/mdstat
Personalities : [raid0] [raid1] [raid10] [raid6] [raid5] [raid4]
md0 : active raid1 sda3[0]
      73749520 blocks super 1.2 [2/1] [U_]
      bitmap: 1/1 pages [4KB], 65536KB chunk

unused devices: 
srv:~ #
En este momento, solo quedó activa la unidad /dev/md0, la cual contiene el sistema raiz, el cual no debe ser perturbado de ninguna forma, dado que el funcionamiento del sistema depende de ello.

3) Cálculo del tamaño (y posición de comienzo y final) de la partición /dev/sda2

Una vez desactivada la unidad correspondiente, podemos hacer el cálculo del tamaño que tendría que tener la partición correspondiente a esta unidad para compensar la diferencia de espacio que falta en el disco /dev/sdb, para poder crear luego las particiones /dev/sdb2 y /dev/sdb3, y que específicamente /dev/sdb3 tenga el mismo exacto tamaño que /dev/sda3, condición indispensable para que sea posible reconstruir /dev/md0. Es cuestión de aplicar las matemáticas para obtener el resultado.

El tamaño de la partición /dev/sda3 es de 147501231 sectores (73750616 bloques), y suponiendo que intentásemos crear la partición /dev/sdb3 con el espacio que nos queda después de crear las particiones /dev/sdb1 y /dev/sdb2 (idénticas a sus correlativas en /dev/sda), dicha partición nos quedaría de 147449743 sectores (73724872 bloques), lo cual nos dá una diferencia de 51488 sectores (25745 bloques) con respecto al tamaño de /dev/sda3. Entonces, si disminuímos el tamaño de la partición /dev/sda2 en 51488 sectores, debería quedarnos suficiente espacio para que fuera posible crear las particiones /dev/sdb2 y /dev/sdb3 con exactamente las mismas características que las particiones /dev/sda2 y /dev/sda3.

Si bien podríamos tomarnos la molestia de usar un programa de cambio de tamaño de particiones (como gpart), en este caso vamos a decantarnos por eliminar la partición /dev/sda2 y crearla de nuevo con el nuevo tamaño calculado (8337119 sectores, obtenido al restarle 51488 sectores al tamaño de la partición original, la cual finaliza en el sector 8800255). De estas operaciones obtenemos la nueva posición del extremo final de la partición, en el sector 8748767.

5) Eliminación de la partición /dev/sda2

La operación entonces se reduce primero a eliminar la partición /dev/sda2 anterior con fdisk:
srv:~ # fdisk /dev/sda
Command (m for help): d
Partition number (1-4): 2

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

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.

srv:~ #
Obsérvese que aparece una advertencia al grabar la nueva tabla de particiones. Esto es normal para un sistema en producción y no debe producir pánico. Ejecutar partprobe o kpartx no resuelve el problema, dado que las particiones siguen en uso. Lo único que "resuelve" este "problema" es un simple reboot, que podrá ser ejecutado cuando el momento sea apropiado. A los efectos de mantener el funcionamiento normal del servidor, esta advertencia puede perfectamente ser ignorada sin consecuencias de ningún tipo durante todo el tiempo que sea necesario.

6) Creación de la nueva partición /dev/sda2 con el tamaño apropiado.

Posteriormente a crear la partición /dev/sda2 de esta manera:
srv:~ # fdisk /dev/sda
Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4, default 2):
Using default value 2
First sector (411648-156249999, default 411648):
Using default value 411648
Last sector, +sectors or +size{K,M,G} (411648-156249999): 8748767

Command (m for help):
Nótese que usamos el valor 8748767 para indicar cual es el sector final de la partición. Pudimos también especificar el tamaño de la partición en sectores, indicando el valor que calculamos anteriormente y anteponiéndole un signo de "+": +8337119. Cualquiera de las dos formas son válidas.

7) Creación de las particiones necesarias en /dev/sdb

srv:~ # fdisk /dev/sdb

Command (m for help): p

Disk /dev/sdb: 80.0 GB, 80000000000 bytes
255 heads, 63 sectors/track, 9726 cylinders, total 156250000 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4, default 1): 1
First sector (2048-156249999, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-156249999, default 156249999): 411647

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4, default 2): 2
First sector (411648-156249999, default 411648):
Using default value 411648
Last sector, +sectors or +size{K,M,G}(411648-156249999): 8748767

Command (m for help): t
Partition number (1-4): 2
Hex code (type L to list codes): fd
Changed system type of partition 2 to fd (Linux raid autodetect)

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4, default 3): 3
First sector (8748768-156249999, default 8748768):
Using default value 8748768
Last sector, +sectors or +size{K,M,G} (8748768-156249999, default 156249999):
Using default value 156249999

Command (m for help): t
Partition number (1-4): 3
Hex code (type L to list codes): fd
Changed system type of partition 3 to fd (Linux raid autodetect)

Command (m for help): p

Disk /dev/sdb: 80.0 GB, 80000000000 bytes
255 heads, 63 sectors/track, 9726 cylinders, total 156250000 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048      411647      204800   83  Linux
/dev/sdb2          411648     8748767     4168560   fd  Linux raid autodetect
/dev/sdb3         8748768   156249999    73750616   fd  Linux raid autodetect

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

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.
srv:~ #
En el proceso debe notarse que el tipo asignado a las particiones que formarán parte de las unidades de RAID fueron declarados como "fd" (Linux raid autodetect). También se puede observar que la partición /dev/sdb3 tiene exactamente 73750616 bloques (que era nuestro objetivo principal), y la partición /dev/sdb2 tiene exactamente 4168560 bloques, lo cual indica que los cálculos fueron correctos.

8) Crear la nueva unidad de RAID /dev/md1.

Llegados a este punto podemos crear nuevamente la unidad de RAID que desactivamos anteriormente, con el propósito de manipular los tamaños y las posiciones en los discos. Esta es una tarea simple, usando mdadm:
srv:~ # mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sda2 /dev/sdb2
mdadm: /dev/sda2 appears to be part of a raid array:
    level=raid1 devices=2 ctime=Fri Jun 21 16:11:35 2013
mdadm: Note: this array has metadata at the start and
    may not be suitable as a boot device.  If you plan to
    store '/boot' on this device please ensure that
    your boot-loader understands md/v1.x metadata, or use
    --metadata=0.90
mdadm: /dev/sdb2 appears to be part of a raid array:
    level=raid1 devices=2 ctime=Fri Jun 21 16:11:35 2013
Continue creating array? yes
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md1 started.
srv:~ # 
Como puede observarse, aparece una advertencia, dado que la partición /dev/sda2 cree pertenecer a una unidad de RAID previa (lo cual es cierto). Podemos ignorar esta advertencia sin problema, porque sabemos que esta partición formaba parte de la unidad original y no correremos riesgos recreandola, así que la respuesta correcta a la pregunta "Continue creating array?" es presionar la tecla "y".

A continuación verificamos que la unidad se creó correctamente:

srv:~ # cat /proc/mdstat
Personalities : [raid0] [raid1] [raid10] [raid6] [raid5] [raid4]
md1 : active raid1 sdb2[1] sda2[0]
      4167524 blocks super 1.2 [2/2] [U_]
      bitmap: 1/1 pages [4KB], 65536KB chunk
      [>....................]  resync =  4.6% (193792/4167524) finish=1.0min speed=64597K/sec

md0 : active raid1 sda3[0]
      73749520 blocks super 1.2 [2/1] [U_]
      bitmap: 1/1 pages [4KB], 65536KB chunk

unused devices: 
Aquí podemos apreciar que la unidad fué inicializada correctamente y que comenzó el proceso de reconstrucción.

Como el proceso se lleva a cabo en forma totalmente independiente del funcionamiento del sistema, podemos seguir con el procedimiento sin esperar que haya problemas de importancia. La sincronización llevará un tiempo, pero no es necesario desperdiciar ese tiempo esperando a que el sistema termine de ejecutarlo.

9) Configurar /dev/md1 como SWAP nuevamente.

srv:~ # mkswap -f /dev/md1
Setting up swapspace version 1, size = 4167520 KiB
no label, UUID=1b6613f9-dd0b-42ab-bfe7-b9cf8fb385e8

srv:~ # swapon /dev/md1
srv:~ #
Ya habiendo activado la unidad de RAID en el SWAP, podemos desactivar el archivo de SWAP que creamos originalmente y eliminarlo.

srv:~ # swapoff /swap.dat
srv:~ # rm -f /swap.dat
srv:~ #

10) Insertar la partición /dev/sdb3 en la unidad de RAID /dev/md0

srv:~ # mdadm --add /dev/md0 /dev/sdb3
mdadm: added /dev/sdb3
srv:~ # cat /proc/mdstat
Personalities : [raid0] [raid1] [raid10] [raid6] [raid5] [raid4]
md1 : active raid1 sdb2[1] sda2[0]
      4167524 blocks super 1.2 [2/2] [UU]
      bitmap: 1/1 pages [4KB], 65536KB chunk

md0 : active raid1 sdb3[2] sda3[0]
      73749520 blocks super 1.2 [2/1] [U_]
      [>....................]  recovery =  0.2% (194560/73749520) finish=31.5min speed=38912K/sec
      bitmap: 1/1 pages [4KB], 65536KB chunk

unused devices: 
srv:~ # 
Llegado este punto, podemos decir que el procedimiento ha concluído con éxito. Si el tamaño de la partición /dev/sdb3 fuera inapropiado, mdadm no permitiría su inclusión en la unidad de RAID, con lo cual este procedimiento hubiera sido en vano.

Ahora solo cabe esperar que la unidad /dev/md0 se reconstruya, proceso que puede si bien se estima que puede tardar una media hora, puede tardar mucho más que eso. Y una vez terminado, las unidades quedarán así:

srv:~ # cat /proc/mdstat
Personalities : [raid0] [raid1] [raid10] [raid6] [raid5] [raid4]
md1 : active raid1 sdb2[1] sda2[0]
      4167524 blocks super 1.2 [2/2] [UU]
      bitmap: 1/1 pages [4KB], 65536KB chunk

md0 : active raid1 sda3[2] sdb3[0]
      73749520 blocks super 1.2 [2/2] [UU]
      bitmap: 1/1 pages [4KB], 65536KB chunk

unused devices: 

Conclusión.

En definitiva, el procedimiento cumplió con los objetivos y con las reglas que lo rigeron. No hubo downtime, y la manipulación de las particiones y unidades no representó un riesgo significativo para el funcionamiento del sistema en ningún momento.

Cabe agregar que si bien es muy posible que este procedimiento haya sido una solución muy específica para un caso muy puntual, esto no significa que no presente un punto de vista distinto e interesante a tomar en cuenta cuando se nos presenta una situación fuera de lo común, con dificultades adicionales que lo hacen más entretenido aún (como por ejemplo que se deba hacer remotamente, que el servidor permanezca en producción, etc.).

Adicionalmente a este procedimiento que podríamos dar "por terminado" (y para completar como es debido este tutorial), deberían tomarse los recaudos del caso y copiarse el contenido de la partición montada en /boot (/dev/sda1) en /dev/sdb1 y asegurarse que el sistema puede bootear de ese disco en forma independiente de la existencia del otro (una de las razones por las cuales suelo instalar los discos de esta manera), así que ejecutamos algunos comandos más y ya dejamos todo como debe ser:

srv:~ # dd if=/dev/sda1 of=/dev/sdb1
409600+0 records in
409600+0 records out
209715200 bytes (210 MB) copied, 13.7615 s, 15.2 MB/s
srv:~ # fsck -f /dev/sdb1
fsck from util-linux 2.19
e2fsck 1.41.14 (22-Dec-2010)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/sdb1: 46/51200 files (10.9% non-contiguous), 35815/204800 blocks

srv:~ # grub

    GNU GRUB  version 0.97  (640K lower / 3072K upper memory)

 [ Minimal BASH-like line editing is supported.  For the first word, TAB
   lists possible command completions.  Anywhere else TAB lists the possible
   completions of a device/filename. ]

grub> find /boot/grub/stage1
 (hd0,0)
 (hd1,0)

grub> root (hd1,0)
 Filesystem type is ext2fs, partition type 0x83

grub> setup (hd1)
 Checking if "/boot/grub/stage1" exists... yes
 Checking if "/boot/grub/stage2" exists... yes
 Checking if "/boot/grub/e2fs_stage1_5" exists... yes
 Running "embed /boot/grub/e2fs_stage1_5 (hd1)"...  17 sectors are embedded.
succeeded
 Running "install /boot/grub/stage1 (hd1) (hd1)1+17 p (hd1,0)/boot/grub/stage2 /boot/grub/menu.lst"... succeeded
Done.

grub> exit
Con estos comandos, copiamos la partición /dev/sda1 sobre /dev/sdb1, asegurando que son exactamente iguales, pasamos un fsck para verificar que el filesystem contenido en /dev/sdb1 está en buenas condiciones, y por último ejecutamos GRUB para configurar el MBR en el disco /dev/sdb y asegurar así que va a ser capaz de bootear, independientemente de que el disco /dev/sda esté presente.

Por último, ejecutamos un nuevo scan de las unidades de RAID para actualizar el archivo /etc/mdadm.conf y listo.

srv:~ # echo "DEVICE containers partitions" > /etc/mdadm.conf
srv:~ # mdadm --detail --scan >> /etc/mdadm.conf
srv:~ # cat /etc/mdadm.conf
DEVICE containers partitions
ARRAY /dev/md0 metadata=1.2 name=srv:0 UUID=70578b13:6c3c1bc1:ace1d531:78764029
ARRAY /dev/md1 metadata=1.2 name=srv:1 UUID=4920c932:ddd10dfe:b97b79b8:5275b4a5

Como les dije antes, esta "solución" podría ser muy específica, pero espero que quienes lleguen a este artículo lo consideren como lo que es realmente, un punto de vista diferente y una solución alternativa a un problema relativamente infrecuente, y además le encuentren algo de utilidad.

Pido disculpas por lo extenso del artículo, pero me pareció interesante publicarlo de la forma más detallada posible para evitar errores que puedan hacer de un entretenido procedimiento, una pesadilla. Espero que sea de provecho para quienes visiten este aburrido rincón de Internet... :-)

:wq

martes, 30 de octubre de 2012

Hasta siempre, abuelo.



  Se fué mi abuelo.

  Se fué mientras estaba con el, acompañándolo en la emergencia de la sociedad médica, esperando verlo despertar para después, en algún momento, llevarlo de nuevo a casa. La suerte o el destino quiso que se fuera sin dolor, sin sufrimiento y sin pena. Se dejó llevar, cansado de la vida y de su cuerpo, cada vez más dificil de tener en pié.

  Me tomó por sorpresa el momento de su partida y no me dió tiempo a pensar o sentir nada. No pude reaccionar de ninguna forma. Cuando el médico se apartó de la camilla y se acercó para decirme lo que yo ya sabía, era evidente que la realidad todavía no me había golpeado como lo hizo un momento después.

  Me quedó grabado lo que repitió tantas veces en los días previos, que el se quería "ir", que ya había sido suficiente, que había vivido bien y que no quería seguir siendo "una molestia". ¿Como iba a ser una molestia realmente, si el había estado yendo y viniendo por si solo y decidiendo sobre su vida como si nada pasara, como si todavía tuviera mi edad? ¿Acaso se privaba de tomarse su whisky o fumarse su cigarrillo, o andaba pidiendo ayuda para todo? Por supuesto que no. ¿No se había ganado acaso el derecho de enojarse por lo que quisiera o reírse de lo que fuera? Claro que sí.

  Molestia hubiera sido si nadie lo hubiera querido, pero ninguno de los que quedamos acá después de que se fué lo quería poco, sino todo lo contrario.

  Desde mis adentros, ardió el dolor de la pérdida, de la desoladora confirmación de que ya no volvería a verlo de nuevo, y desde ese momento el mundo ya no volvió a ser el mismo. Hubiera querido decirle tantas cosas, compartir tanto más con él, pero ya no había tiempo. Ya hacía meses que se había entregado, había dejado de comer, de cuidarse, de tomar sus medicamentos. Visitaba a la cardióloga porque lo llevábamos prácticamente obligado. La última vez se negaba a ir, y luego de un rato de conversarlo, me mostró que era porque ya no podía calzarse y eso lo enloquecía. Para alguien que tiene una vida de ir y venir, activa y vibrante, no poder hacer eso que cualquiera hace todos los días era un suplicio. Lo ayudé a calzarse y le dije que lo tomara como un paseo y que íbamos a pasar por el Parque Rodó a comprar unos churros, que tanto le gustaban. Se lo veía cansado, abatido y no dejaba de repetir que "ya no servía para nada". De todas maneras no se privó de hacerle el clásico chiste del gusanito en el vaso de alcohol a la doctora, como siempre que iba. Me dolía verlo así, y yo sabía que el momento estaba cerca, pero no quería aceptar que el día llegaría tan pronto. Cuando tuviste una vida como la de él, en la que muy pocas cosas te quedaron pendientes, ya diste todo de vos y recibiste tanto amor y cariño, ya no hacía falta nada más.


  Me quedaron recuerdos imborrables, detalles que no voy a olvidar. Algunos son vagos instantes de mi niñez, otros son las historias que él contaba, pero todo lo tengo presente. Me acuerdo como en un sueño de como salíamos a caminar tomados de la mano y me "enseñaba a hablar" usando todo un repertorio digno de Jorge Corona. O cuando me sacó del agua aquella vez en que una ola me tapó en Cuchilla Alta e hizo que me diera cuenta de lo peligroso que puede ser el mar cuando tenés apenas tres años y medís medio metro de altura. O cuando usando algún super-poder que nunca pude entender, detuvo a tiempo aquella hamaca de la que yo me había tirado, antes de que me golpeara en la nuca, seguramente dejándome inconsciente. O cuando nos llevó al Parque Rodó a mi primo y a mi, en la época en que todavía estaba aquel inflable "enorme" en el que te podías meter y saltar como loco, y que ahora cualquiera puede alquilar para el cumpleaños de sus hijos. Me acuerdo de cómo lloré cuando se iban todos juntos a Costa Azul y yo me tenía que quedar en casa porque estaba haciendo fiebre producto de la varicela, y el se acercó a la cama a tratar de tranquilizarme. Me acuerdo de cuando iba a casa trayendo chocolatines "Águila", de como cada vez que venía a casa era una fiesta, y de cuando nos hacía aquellas tortas de cumpleaños adornadas con fondán de colores que tanto nos gustaba. Me acuerdo de los Ricarditos que repartía cuando íbamos de visita. Me acuerdo de aquella tarde en que en una torpeza mía crucé corriendo y sin mirar hacia los dos lados la Avenida Millán, y un grito de él hizo que me detuviera a escasos centímetros de la trayectoria de un enorme camión que intentaba frentar sin lograrlo. Me acuerdo de cómo me acompañaba para que aprendiera a andar en bicicleta, de los caramelos que me daba todas las noches, de las idas a los juegos del Prado y las visitas al museo Blanes.

  Cuando fui creciendo, me acuerdo de las conversaciones en las que intentaba convencerme de que estudiara y creciera siendo una buena persona, porque según decía, yo era su nieto preferido, un privilegio que nunca merecí pero que llevé con una mezcla de pública vergüenza y secreto orgullo durante toda mi vida. Me acuerdo de cuando me iba a quedar algunos días a su casa y al caer la tarde el me preparaba aquellos sandwiches de pan marsellés, con butifarra y ajíes picantes. Me acuerdo de cuando me llamó emocionado para que fuera a leer una carta de respuesta a una petición de trabajo que él me había incentivado a hacer a un laboratorio, que finalmente resultó ser una carta de rechazo, y de su cara triste y avergonzada a pesar de mis intentos de darle poca importancia al asunto. Me acuerdo de cuando se tomó la  molestia de coleccionar aquel Manual de Windows 98 que salía con el diario "El observador", y que yo no sabía cómo explicarle que parte de mi trabajo consistía en enseñarle a la gente a programar, una tarea para la cual había que saber mucho más de lo que ese manual jamás podía llegar a tener.

  Me acuerdo del taller de relojería, al que él le había puesto el nombre "Diasfi", en honor a un amigo fallecido que se llamaba "Fidias". Recuerdo las tardes que pasamos jugando a la conga "los hombres" contra "las mujeres", y mientras la abuela nos hacía trampa contándose puntos de menos, yo amenazaba con "cortar", y el abuelo cortaba de verdad, dejándome casi siempre con demasiados puntos en la mano. Me acuerdo de las pizzas que hacía cuando íbamos de visita, de las cazuelas de mondongo que organizaba en invierno, de los pasteles hojaldrados y el pan dulce de fin de año.

   No me olvido de lo contento que se quedó cuando fuí a la feria a visitarlo con mi novia, quien ahora es mi mujer y le mostré las alianzas que yo mismo había hecho cuando cumplimos 10 años de noviazgo y de cómo me amenazó de que si dejaba a "Anita" iba a tener lío con él. Me acuerdo de lo orgulloso que estaba cuando pusimos en sus brazos a Valeria, mi primera hija, y de lo feliz que estaba cuando supo que Tatiana, mi segunda hija, había nacido el mismo día de su cumpleaños.

  Me acuerdo de las veces que fuí a su casa y las que vino a la mía, que lamento cada segundo que no hubieran sido más, y como el me palmeaba la espalda y me decía "¡Vos sos mi nieto!", como si no tuviera ninguno más.

  Sabía ser dificil cuando quería, terco e inflexible y no se puede decir que era una persona intachable sin faltar a la verdad. Tenía defectos y debilidades como tenemos todos, pero como sus zapatos me quedan demasiado grandes y no viví todo lo que él vivió, no lo juzgo ni lo reprocho, ni lo haré jamás. Para mí fué todo lo que podía pedir de un abuelo, y yo lo amaba como a nadie más, con un amor de familia que no he sido capaz de sentir siquiera por mis propios padres.

  Aquella mañana lluviosa, el médico salió del box 23 de emergencias de la sociedad, me apartó al pasillo e intentando ser amable, condescendiente y respetuoso, me dijo que era muy dificil que hubiera podido salir adelante, que tenía el corazón muy grande y que no lo había soportado... ¿Cómo no iba a tener un corazón grande si tenía que querer a tanta gente y si todos lo queríamos tanto?.


  La noche anterior a su partida tuve un sueño extraño, que solo le comenté a mi mujer. Soñé que sentado en una silla, maniatado, había alguien (que en el mundo "real", también se fué de esta vida), rodeado de personas que lo juzgaban, como si fuera culpable de algún crimen atroz. Él no hacía nada por defenderse, sino que simplemente aceptaba el castigo que le impondrían, que en el sueño era la muerte. Yo, desesperado ante la dócil sumisión y aceptación del acusado, le pregunté finalmente: "¿Es esto lo que vos querés?", a lo cual él se paró delante de la silla, libre al fin, como si hubiera podido desatarse inmediatamente, me miró directo a los ojos y me dijo sin titubeos "Si". En ese momento todo se terminó, el juicio y las acusaciones, como si hubiera sido una actuación que finalizaba, y yo desperté perplejo y desorientado. No lo entendí en el momento, y me confundieron quienes estaba en el sueño y la situación, pero después de lo que pasó esa mañana, creo haber entendido el verdadero significado, como si hubiera tenido una epifanía. Realmente eso, la muerte, es lo que mi abuelo quería. No era un castigo, era la libertad. Estaba cansado de que lo juzgaran, de que lo acusaran de no tomar los medicamentos, de no comer y de dejarse vencer. Y a pesar de todo, el haber tenido ese sueño me tranquilizó y me ayudo a aceptar la realidad más serenamente, aunque aún ahora no puedo explicarlo de ninguna forma, y quienes me conocen sabrán que para mí es muy dificil aceptar que ese sueño y lo que pasó la mañana siguiente tienen la relación que hoy creo que tienen.

  Y esa fué finalmente la única frase que pude dar y repetir como consuelo a todos los que como yo, lo querían y sufrían. "Es lo que él quería".

  En el velorio, que él también hubiera querido que fuera una fiesta, nos reunimos alrededor de aquel cajón de madera y brindamos con un whisky por él. Mientras apenas pude murmurar un adiós ahogado, no sé de donde sacó entereza mi tío, el hijo que mi abuelo nunca tuvo, para ponerse a cantar y dedicarle una última canción, "De puro curda", y yo me escondía en la cocina para que no me vieran devastado por la emoción y por la bronca, por no saber entera la maldita letra para poder acompañarlo.

  Hoy traté de terminar de escribir este post (cuya finalización hace días que postergo) sin sucumbir a la emoción otra vez, pero no pude. De nuevo se me anudó la garganta y se me nubló la vista por las lágrimas que aún ahora trato de contener, pero no quiero que quede sin terminar esto que es el cierre de una etapa de mi vida que recordaré para siempre con nostalgia, cariño y orgullo.

  Quiero creer que ahora está en una gran fiesta, pasándola bien, disfrutando. El no hubiera querido vernos a todos sufriendo, y menos siendo que terminar de esta forma talvéz fué su decisión. Parecía que me hubiera estado esperando para poder irse tranquilo...

  Donde quiera que estés, abuelo, quiero decirte que aprendí muchas cosas de vos, me enseñaste a ser una mejor persona y que lo realmente importante en esta vida no es tener cosas, sino tener a quien amar y tener a alguien que te ame. Te deseo lo mejor en ese nuevo viaje y quiero que sepas que estoy agradecido de haberte tenido en mi vida todo este tiempo.

  Te quiero y te voy a extrañar mucho.

jueves, 17 de mayo de 2012

Y empezamos otra vez...

Otra vez se "acercan" las elecciones.

Otra vez voy a tener que tomarme la molestia de trasladarme hasta la mesa de votación que me toque, a cumplir con la obligación que me impone la ley. Y otra vez, como muchas otras veces antes, voy a poner papel higiénico en el sobre de votación.

Lo malo no es sólamente que yo tenga que hacerlo, es que muchos otros van a ir a "votar de verdad"...

Como siempre, debo ser yo el que está equivocado, naturalmente. Desde mi punto de vista, ya "probaron" todo lo que había para probar, y ya comprobaron que nada sirve. Entonces ¿porqué siguen convencidos de que votar es una solución viable?

Puedo entender a los militantes, esos personajes que votan "con el corazón", aunque la razón demuestre que en realidad lo que hacen es irracional e injustificado. Los más convencidos votan por "coherencia ideológica" y los otros por fanatismo. Ninguno vota por los resultados obtenidos por el partido en cuanto al bienestar global, que debería ser el verdadero objetivo. El medio se convirtió en más importante que el fin. Ese tipo de votantes son los que todavía creen que los líderes que eligen luchan con ellos y a la par de ellos para mejorar el país. Son gente convencida de que es posible una realidad alternativa y utópica, en la que ellos van a ser considerados como ellos creen que se merecen. Sus ideales son tan importantes que no se dan cuenta de que su fanatismo los tiene ciegos ante una realidad inmutable, basada en reglas que no comprenden del todo, creidos de que cuando sus líderes lleguen al poder, harán lo necesario para cambiarla. No se puede siquiera discutir con ellos, porque han llegado a un punto tal en el que atacan a cualquiera que piense distinto igual que los leucocitos atacan a una enfermedad...

Pues bien, señores militantes, les tengo una noticia: Por si no se dieron cuenta, llevamos casi 30 años de democracia, con participación de los tres principales partidos políticos, y todavía no se resolvieron los principales problemas que nos aquejan desde siempre.

¿Y saben porqué no se resolvió nada? Porque como ya dije antes, nadie va a hacer lo que realmente hay que hacer para resolver los problemas que nos aquejan. Y por eso estoy convencido de que votar no sirve para absolutamente nada. Todo tiene un costo político infranqueable, y nadie va a arriesgarse por la gente que los pone en el poder realmente.

Militar por un partido político hoy día se podría decir que es inmoral, como lo sería defender a un delincuente confeso que no siente ni sentirá nunca ningún arrepentimiento. Es muy probable que muchos de los que militan tengan sus propias agendas también, sus propios intereses, su vista enfocada en una parte de la gran torta que se reparte entre los ganadores. Sino, ¿como puede explicarse que sigan intentando "ganar"? ¿Me van a discutir que es por los principios o por el bienestar de los que están mal? Si este último es el caso, ¿están seguros de que esos objetivos son alcanzables si se asegura y perpetúa la hegemonía del grupo que defienden y que ha demostrado que son tanto o más incompetentes y corruptos que todos los demás?

Los partidos políticos son empresas con su propia agenda, sus propios intereses y sus propias motivaciones, totalmente independientes de lo que sus seguidores creen que representan. Sus líderes salvaguardan y protegen al dios dinero y a sus verdaderos dueños. Un ejemplo claro lo tenemos hoy mismo en nuestro gobierno actual. La izquierda uruguaya se llenó la boca durante cuarenta años con las cosas que iban a hacer cuando estuvieran en el poder, y ahora que están ahí con ámplia mayoría en las cámaras, se "dieron cuenta" como en una epifanía de que no es tan fácil como se lo estuvieron diciendo a sus seguidores durante décadas. Dos períodos de consistencia y continuidad en las cuestiones importantes y solo "mejoras" marginales en algunos otros ámbitos demuestran una hipótesis que era obvia. Sus votantes, ¿no se sienten traicionados acaso?

Seamos realistas. Ya probaron de todo. Todos prometieron y ninguno cumplió. Todos mintieron, abierta y descaradamente, algunos de forma tan incisiva y deliberada que es increíble que aún tengan adeptos (¿Se acuerdan de aquel comercial de radio en el que aparecía Luis Hierro López afirmando "Los colorados, no vamos a devaluar"? ¿O  cuando las primeras elecciones en las que ganó el FA la dirección de la Intendencia de Montevideo con la promesa de Mariano Arana de bajar en un 50% el precio del boleto, y una vez que estuvieron en el poder, hicieron rebajas de porcentajes mínimos en varios tipos de boletos, los cuales "juntos" sumaban "50%" (su primerísima mentira piadosa) y aún hoy día, a pesar de haberse llenado la boca contra la corrupción, ahora se comprueba que son iguales que sus antagonistas blancos y colorados? ¿Y se acuerdan de los blancos, con Lacalle al frente, cuyos tejes y manejes hicieron que el Banco Comercial pasara a manos de los Rohm (delincuentes que efectuaron estafas en varios países durante décadas) y le vendieron también el Banco Pan de Azucar a Stephan Benhamou (quien se exilió al saberse implicado en la obvia estafa del vaciado de dicho banco y murió en el exterior, a salvo de la justicia), ganándose él y su secretario (luego procesado por haber coimeado ineptamente) varios millones de dólares en la transacción?). Votar otra vez a estos (o a otros) políticos para darles otra oportunidad es ilógico. Continuar dándoles soporte es insensato cuando menos.

Mi propuesta: Anular el voto y preparanos para hacer lo mismo que se hizo en Islandia. ¿No saben qué pasó en Islandia? Bueno, averígüenlo y después me vienen a comentar.

Ah, y no me digan que hace falta una crisis económica para hacer lo que se hizo en Islandia... porque esa crisis ya está afectando a todo el planeta actualmente, y no deberíamos esperar a empeorar visíblemente como en el 2002 para poder hacer las cosas bien.

Podemos empezar hoy. ¿O nadie se dió cuenta de que por más que te quieran convencer de lo contrario, los precios SIEMPRE suben y NUNCA bajan y los sueldos NECESARIAMENTE tienen que subir para compensar la diferencia? ¿Nadie se dió cuenta de que es antinatural e innecesario este proceso, ya que los recursos con los que cuenta el país son practicamente los mismos y que la cantidad de gente que vive en él no ha aumentado, sino todo lo contrario? ¿No entienden que los recursos monetarios son irreales y que va a llegar el momento en el que el dinero solo será lo que realmente es, solo papel, ya que hace años que no existe la cantidad necesaria de oro que se supone que debería respaldar a la moneda? ¿Cabe alguna duda de que el sistema bancario de reserva fraccionaria y el neoliberalismo están dejando al mundo al borde del colapso y arrastra a nuestro país hacia el mismo destino, y que la institución que debería velar por la establidad, el Banco Central, ha sido manejado históricamente por gente corrupta que ha permitido a delincuentes como la familia Peirano y los Rohm abrir bancos una y otra vez, aún después de haber defraudado repetidamente a ahorristas y accionistas?

Discúlpenme si me río, pero a la vista están las pruebas... Todos sabemos de los manejes oscuros de los políticos, así que ¿porqué se los sigue votando? Hay que despertar y entender que los políticos y el bienestar de la gente gobernada por ellos son incompatibles entre sí. Son capaces de todo tipo de mentiras y arreglos sucios destinados a ponerse a ellos mismos en el poder, sin otro propósito, sin objetivos globales fuera de esos. Quien hoy día crea que votar tiene algún otro propósito que no sea engordar el bolsillo de algún político, está franca y defiitivamente equivocado. ¿Por qué se creen que aún hoy es obligatorio ir a votar? Porque si no lo fuera, la "lucha" se reduciría a los militantes, los fanáticos (esos que votan "con el corazón", como si se tratara de un partido de futbol), los que tienen intereses y apuestas fuertes dependientes de decisiones tomadas por gobernantes corruptos, y los políticos mismos. El resto se quedaría en casa disfrutando de un domingo en familia, algo que tiene mucho más valor que la política y el "manejo" del país.

¿Qué importa quien gane, si el dinero es el que gobierna realmente?

Como decía Edward R. Murrow, "Good night, and good luck"

jueves, 1 de marzo de 2012

El caso Miami-Box

Hace tres años que soy cliente de esta empresa, Miami-Box. Su servicio consiste en ofrecer direcciones físicas en Miami a residentes de Uruguay, de forma tal que cuando uno compra artículos en USA, (u otros lugares del mundo), estos se envíen a dicha dirección, desde la cual ellos se encargan de hacer el flete hacia Uruguay. Simple y conciso.

Traigo un promedio de dos o tres paquetes por mes, mayormente repuestos, artículos que no se consiguen acá, CDs o DVDs, libros, etc. Todo funcionó bien, hasta que en Febrero de 2012, la empresa cambió la forma en que factura a sus clientes. A partir de Febrero, todo paquete que llegue a través de su servicio y que no sea despachado por ellos mismos, deberá pagar un extra de U$S 15 por concepto de "Validación de Guía". ¿De qué se trata este concepto? Bueno, supuestamente consiste en la "validación" de la documentación necesaria para hacer el despacho del paquete... o sea, le dieron un nombre y un costo a un simple movimiento de papeles que no le cambia absolutamente nada al usuario, y que de hecho no existe como trámite en el mundo de las importaciones, por lo menos del lado del "fletero".

Básicamente, a partir del 1 de Febrero de 2012, Miami-Box le agregó un "peaje" a los paquetes despachados directamente por sus clientes, seguramente como forma de controlar la creciente demanda de servicios y la explosión de trabajo que los está desbordando (como ejemplo, tengo un paquete que fué entregado el 31 de Enero en las oficinas de Miami-Box, según el tracking del flete local, y todavía no llegó a la Aduana de Uruguay).

Más allá de que Miami-Box está en todo su derecho al cambiar su política de precios, el problema reside en que no le avisaron previamente a sus clientes habituales de este cambio, con lo cual, estos se han encontrado con la sorpresa de tener que desembolsar U$S 15 adicionales al costo que ya tenían calculado pagar.

Cualquier empresa seria habría avisado con suficiente anticipación (digamos, un mes) que iban a cambiar su política de precios, de manera de que los usuarios pudieran decidir si les valía la pena traer ciertos artículos de bajo costo y que muchas veces no ameritan un desembolso extra de más de un 100% del costo, en un trámite administrativo inexistente. Pues en Miami-Box decidieron que no era necesario tomarse la molestia de poner sobre aviso a sus clientes, sino que silenciosamente empezaron a cobrar este adicional en las facturas, y las quejas que se les hacen son respondidas de forma despectiva, o ignoradas cuando mucho. Y talvéz las empleadas fueron instruídas para desestimar quejas mandando a los usuarios a leer el sitio web, donde oportunamente publicaron el cambio en la facturación en un párrafo perdido en una página , como "al pasar", sin ningún tipo de énfasis que ayude a aclarar fácil y rápidamente la duda.

La "calculadora de costos" (un programa que publican para que la gente pueda hacer el cálculo de cuanto cuesta traer algo usando sus servicios) no tiene la capacidad de permitir el cálculo más aproximado posible, sino que omite claramente el costo de los "honorarios" de Miami-Box por el despacho (información que figura en otra página y que no queda claro porqué no está incluído en el calculador), y directamente carece de una opción para quienes desean hacer los despachos por sí mismos. Veamos un ejemplo, con datos ingresados y calculados usando el software que tienen disponible para dicho menester:


Costo en Miami (en U$S): 99.99
Der. de Internación U$S: 73.18
D.U.A U$S: 0.00
T.C.U U$S: 15.00
Despachante de aduana U$S: 15.00
Flete Internacional U$S: 12.60
Flete Nacional U$S: 0.00
Manejo U$S: 5.00
Total de Gastos U$S: 120.78


Acá faltan los "honorarios" de Miami-Box (U$S 10, indicados en otra página) y si uno hace el despacho uno mismo, debería reemplazar el concepto "Despachante de aduana" por el de "Validación de guía", ya que cuestan lo mismo. Esta gente se escuda poniendo un mensaje que indica que los "valores podrían sufrir pequeñas variaciones de costo", aunque en un paquete que vale U$S 10, esa variación ahora es del 150%, así que lo de "pequeña" le queda "corto"...

Paquetes comprados en Enero, cuando este costo no existía, fueron facturados en Febrero con el sobrecargo de la "validación de guía", con el agravante de que dichos paquetes fueron recibidos en Febrero porque "se atrasaron los vuelos", o sea que además de tener que esperar tres o cuatro semanas por algo que debería tardar solo una, tenemos que pagarles extra por un trámite que básicamente no existe, lo que es claramente un agravio a quienes somos clientes habituales.

En definitiva, Miami-Box está tratando a sus clientes de forma totalmente irrespetuosa. Se podría decir que una vez fueron pioneros en un servicio que hacía falta, pero ahora, con este cambio en la política, totalmente furtivo y sin notificación previa a los clientes, se han hecho acreedores de un grado inmenso de desconfianza y de mi más acérrimo repudio. A mi me perdieron como cliente, y estoy seguro de que a muchos otros también, por exactamente el mismo asunto. Ahora voy a ir a una empresa competidora y de mucho mayor renombre a nivel internacional, quienes seguramente me va a cobrar más caro, pero por lo menos no me van a "sorprender" con costos extra que aparecen de la nada y sin avisar. Prefiero pagar más por un servicio serio, que pagarle a alguien deshonesto y que cambia sus precios sin avisarme siquiera.

Ya está hecha la denuncia en Defensa del Consumidor, así que espero que les haya hecho provecho.

domingo, 9 de octubre de 2011

La solidaridad en Facebook

Facebook es indiscutíblemente la red social más importante actualmente. Tiene sus cosas buenas y sus cosas malas, como todo. Lo bueno es que ayuda a unir a las personas, brindando un medio de comunicación que permite acercar virtualmente a gente que está geográficamente lejos. Entre las cosas malas, está el uso indiscriminado del servicio, tanto por parte de delincuentes como de instituciones, como herramienta para rastrear personas, obtener información sensible (ofrecida en forma inadvertida por los usuarios) y obtener lucro mediante el fraude.

El fraude más común en Facebook era el de ofrecer una aplicación que afirma poder brindar información sobre quién visitó tu perfil. Siendo que Facebook NO ofrece acceso a esa información mediante el API que permite crear aplicaciones para el mismo, es evidentemente imposible que alguien pueda escribir una aplicación así. ¿Como funciona este fraude? Simple: Alguien publica el acceso a la aplicación, y le avisa a otros que la misma existe. Por lo general la propagación de la noticia de la existencia de esta aplicación es viral, ya que a los incautos usuarios se les dan instrucciones para que reenvíen la invitación a la aplicación a todos sus contactos, facilitando el esparcimiento de la misma y su rápida expansión en cuestión de horas.

Las instrucciones siempre exigen presionar el botón "Me gusta", el cual supuestamente activa la funcionalidad o permite el acceso a la aplicación. También se exige que se le envíe el enlace a toda la lista de contactos, esparciendo el fraude. Aquí radica el propósito del mismo, ya que al presionar el botón, lo que se hace es inadvertidamente cargarle el "Me gusta" a algún sitio web o a alguna página que realmente no es interesante ni está relacionado con la función que supuestamente la "aplicación" provée, y además se le hace propaganda gratuíta entre todos los contactos a quienes se le envíe. De esta manera, a los incautos usuarios les queda "gustando" algo que realmente NO les gusta ni les interesa. La popularidad de ciertas páginas se debe jústamente a este tipo de fraudes.

Como los mismos usuarios se tornan en vehículos promocionales del sitio, el esquema del "Me gusta" se vuelve fructífero en pocas horas, dándole cierto prestigio popular y atrayendo a más víctimas. Esta es la forma más simple de fraude en Facebook.

Como Facebook plantea una filosofía conceptuamente benigna (somos "amigos", las cosas "nos gustan", etc.), es fácil que los usuarios se confundan y piensen que TODO lo que hay en Facebook lo es, lo cual alimenta la idea de que todo lo que allí aparece es creíble y confiable. Y jústamente por eso es que algunas personas inescrupulosas utilizan las herramientas que Facebook provée para obtener lucro engañando a los usuarios que visitan sus páginas.

Afortunadamente, Facebook provée un enlace en todas las páginas que permite "avisarles" que dicha página es fraude o spam, con lo cual podemos rápidamente "deshacer" la acción simplemente entrando en la página y presionando el enlace que dice "Ya no me gusta", y el que dice "Denunciar esta página". No siempre la gente de Facebook desactiva la página en cuestión inmediatamente, sino que hay un procedimiento de verificación que puede tomar algunos días, por lo cual hay que ser pacientes. Lo importante es avisarle al resto de los contactos a quienes se les haya "promocionado" el sitio que es un fraude, así ellos también podrán hacer su aporte y eliminar rápidamente la página fraudulenta.

La gran mayoría de estas páginas "solidarias" muestra alguna fotografía shockeante, generalmente de bebes o niños con enfermedades o deformaciones visibles, fotos que tienen como cometido generar compasión y pena. Esto produce en la mayoría de las personas, sobre todo en los que somos padres, el impulso de tratar de ayudar a los afectados, lo cual termina decantándose en seguir las instrucciones que la página indique como forma de ayuda. Por lo general, la ayuda que se pide consiste en hacer click en uno o varios botones "Me gusta", los cuales, tal y como indican las instrucciones, harán que "alguien" done una cierta cantidad de dinero (a veces especificada, a veces no) a los damnificados. Y esta es la primera señal de alerta que debería todo el mundo tomar en cuenta cuando se entra a alguna de estas páginas.

Es cierto, no cuesta "nada" hacer un click en un botón "Me gusta", y como no cuesta nada, casi todo el mundo sigue ciegamente las instrucciones sin preguntarse si quiera a qué le está haciendo click realmente. Además, la mayoría de los pedidos tiene frases como "Si no nos ayudas, no tienes corazón", o "Dios te ayudará por ayudarnos a salir adelante", o "Solo te pido que hagas un click para salvar una vida", etc., lo cual tiene como propósito generar culpa y remordimiento, lo que finalmente se traduce en clicks en los botones mencionados. Es necesario aclarar que la gente que hace este tipo de fraudes tiene claro cual es su público objetivo y que tienen entrenamiento en marketing e ingeniería social, así que no es dificil darse cuenta de porqué estos fraudes abundan y tienen éxito. Saben engañar y saben qué "botones" presionar en nuestro interior para generarnos la necesidad de ayudar.

Lamentablemente, el público en general no tiene idea de cómo distinguir entre un fraude y algo real, así que me dió por escribir este artículo, con la finalidad de ayudar a entender cómo funciona este tipo de fraude y cuales son los indicadores importantes que hay que tener en cuenta para poder saber si son fraudes o no.

¿Como darnos cuenta de si es un fraude?

1) Normalmente, estas páginas no tienen ninguna dirección de contacto real. ¿Qué podemos aceptar como dirección de contacto real? Nunca una dirección de correo electrónico. Tiene que ser una dirección física, calle y número, localidad, teléfono, etc. Si no tiene ninguna de estas cosas, ya se puede estar 99% seguro de que es un fraude. ¿Porqué? Porque si realmente necesitas ayuda, no tendrás reparos en darle a la gente una dirección donde poder hacer una donación o simplemente acercarse a "dar una mano", o un teléfono donde comunicarte y poder coordinar la ayuda. Una dirección de correo electrónico no es aceptable, y menos cuando se trata de una dirección de un servicio gratuíto, o de un servicio que no permite conocer el origen real del mensaje (como Gmail, por dar un ejemplo claro).

2) Mayormente, las páginas de fraude indican que por cada click que hagas en algún enlace, "alguien" les donará una cantidad de dinero. Estos esquemas solo funcionan en los casos en que el tráfico puede ser cuantificado en forma controlada y confiable, lo cual no es el caso en Facebook. Acuerdos de donación de este tipo están debidamente identificados y son extremadamente raros. Los fraudes generalmente citan empresas de gran envergadura (Microsoft, Hotmail, Yahoo, Facebook, Google, etc.) como benefactores, aunque esto se hace con el fin de dar a entender que se trata de una situación reconocida por instituciones de renombre, tratando de aprovecharse del prestigio de las mismas para proveer realismo al fraude. Es raro que estas instituciones accedan a ser parte de un esquema de "pago por click", así que si la única forma de ayudar consiste en eso, está claro que se trata de un fraude.

3) No suele haber más de una o dos fotos en un fraude, y tampoco hay información de estado de la situación, ni forma de hacerle un seguimiento a la misma. Los fraudes suelen tener "vida corta", aunque gracias a la velocidad de propagación en las redes sociales, ese poco tiempo les reditúa en forma inmediata y efectiva. Para el defraudador, es importante que ese único disparo surta efecto inmediatamente y luego sea olvidado sin más. Dado que la responsabilidad que le implica a las víctimas se reduce a hacer un click y la mayoría de las veces pide reenviarle el pedido original a todos sus contactos, estas creen haber ayudado con esas simples acciones y tienden a creer que "cumplieron" con las condiciones indicadas (y con su conciencia), olvidando rápidamente el asunto. Si no hay forma de hacer un seguimiento, es otro indicativo claro de que la situación planteada no es real.

4) El fraude suele tener incongruencias, faltas de ortografía, de redacción y de detalles. Nunca hay referencias importantes en otros sitios web confiables, y raramente hay fechas concisas en el texto, lo cual es importante para los defraudadores porque nos impide saber si estamos "a tiempo" de llegar con ayuda. Suele haber inconsistencias y hasta contradicciones en la historia, lo cual es otro factor a tomar en cuenta. Si la situación es real, habrá referencias reales e información precisa y confiable. Si no las hay, es un fraude.

5) Por último, si tenemos conocimiento técnico de la web, podemos hacer el análisis del código fuente de las páginas implicadas, lo cual nos dará a ciencia cierta indicadores inequívocos del verdadero propósito de las mismas. Esta suele ser la forma más segura de darnos cuenta, pero se sobreentiende que por lo complejo de su comprobación no será la forma más común de descubrir el fraude. Si Usted tiene dudas, puede consultar con un experto que le indique claramente la veracidad de lo que se plantea en una página. Ese puede ser el factor definitivo en la decisión de brindar "ayuda" o no.

Todo esto que planteo en este artículo es simplemente una herramienta para los interesados en estar informados a la hora de "dar ayuda". Como dicen ellos, hacer click no cuesta nada, y si les es más fácil hacer click que tomarse la molestia de leer estas indicaciones, no hay problema. A mi en lo personal no me gusta que haya gente que se aproveche de la bondad de otros, y menos utilizando fraudes que impliquen niños, así que aconsejo que tomen en cuenta lo que aquí expuse y se tomen el trabajo de analizar y verificar el destino y el tipo de "ayuda" que se plantean en este tipo de situaciones. ¡Ojalá ayudar fuera tán fácil como hacer click en el botón de una página web!

Como les digo eso, también les digo que si sienten la necesidad de ayudar sin mirar a quien ni cómo, están en todo su derecho, sin importar si los beneficiarios son reales o defraudadores. Si hacer click en una página les ayuda a dormir mejor, no me hagan caso. Como siempre les digo, puedo estar equivocado :-)



Addendum: Análisis de un fraude

Hace unos días apareció una página en Facebook invitando a los usuarios a un evento denominado "Ayuda a salvar a Carlitos". Esta es la URL original:

http://www.facebook.com/event.php?eid=273817502649634

Aquí les pongo una captura de pantalla para que vean cómo se veía la página, la cual ya denuncié y espero que quiten en breve.

Pido disculpas a mis lectores por hacerles ver la foto a continuación, pero creo que es necesario para que tomen conciencia de la dimensión que tiene el engaño y de la poca tolerancia que tenemos que tener ante gente que hace este tipo de cosas:



En la página de información del evento están los botones de "Me gusta" que supuestamente le redituarán a la familia del niño 5 centavos de dolar por cada vez que se haga click en ellos. Nótese que en la descripción del evento dice "5 centavos de dolar", mientras que en la página del usuario que creó el fraude dice "$$5". El texto describe la dolosa situación de una madre de 27 años cuyo hijo nació con un cancer en la lengua. El pedido termina con la frase "Si no ayudas honestamente no tienes corazón".

En la página se muestra el enlace "para ayudar", el cual lleva a la página
http://www.facebook.com/pages/Ayuda-A-Salvar-a-Carlitos/180327365381094, la cual en este momento se vé así:



Noten que en "Informacion" de la página no hay nada.

Como puede apreciarse, hay 9 botones "Me gusta", y supuestamente al hacer click en ellos, estamos ayudando. Examinando el código fuente de la página, podemos ver a donde apuntan estos enlaces realmente:



Esta es la lista de enlaces de los botones "Me gusta":

1) http://www.facebook.com/yo.tambien.miro.tuperfil.JAIROJDC
Si miran con atención, esta es una página que nada tiene que ver con una donación a Carlitos, ni nada que se le parezca. Es una página de negocios de una empresa denominada "Team Admin", que provée páginas de ocio y juegos, como hay miles en internet. Actualmente esta página tiene 535.097 seguidores, y 88.310 personas están "hablando" de ella. Resulta obvio de donde sale tanta "popularidad".

2) http://www.facebook.com/by.jairo.castillo
Esta página tiene nombre y apellido, y como podrán ver si entran, es otra página de la misma empresa anterior. A 433.398 personas les "gusta esto", y 44.852 están hablando de ella. Veo dificil que tanta gente disfrute al saber que sus clicks para Ayudar a Carlitos terminen alimentando los números de esta "empresa".

3) http://www.facebook.com/tipico.byJAIRO
Otra página más de la misma empresa. A 274.291 personas les "gusta esto" y 46.801 están "hablando de ella". Naturalmente, dudo que esas personas sepan realmente que esta página les gusta.

4) http://www.facebook.com/Verr.maass
Otra página más de esta "gente" (si se les puede llamar así). 223.302 incautos presionaron el botón me gusta en alguna página fraudulenta y 40.301 personas comentan la misma.

5) http://www.facebook.com/pages/ByJairo/240157339354570
Este enlace apunta al perfil de la persona que inició el fraude. Un tal "Jairo Castillo". Le escribí dos veces en su muro y el borró los comentarios. UPDATE: Acaba de aparecer otro perfil de este personaje: http://www.facebook.com/profile.php?id=100002294694471&sk=wall. Esta vez protegió su muro para evitar que le siga "mandando saludos". Naturalmente no me voy a hacer amigo de él para seguir publicándole lo que pienso.

6) http://www.facebook.com/pages/Yo-tambi%C3%A9n-quiero-ser-un-ni%C3%B1o-de-nuevo/281117895247003
Otra página más de este personaje. 164.921 usuarios engañados, y 37.964 comentando.

7) http://www.facebook.com/diariodiez
Es la página de un diario deportivo, seguramente un cliente de Jairo o un asociado. ¿Sabrán que parte de su popularidad se debe a un fraude? 90.805 víctimas y 12.475 usuarios comentandola.

8) http://www.facebook.com/pages/Prefieron-Un-minuto-Con-tigo-que-una-eternidad-sin-ti/223831821010906
Otra página tonta, que solo pone una frase en el muro de los usuarios a quienes les gusta. Otra vez se vé la referencia al creador del scam: Jairo Daniel Castillo. 14.706 víctimas engañadas y otros 7.765 comentando.

9) http://www.facebook.com/Amas.a.perry.By.AndreexD
Otra página más, aunque no está claro de quien es, ya que no hay referencias. Probablemente sea un "amigo" de Jairo, el cual le pidió una "mano" para popularizar su página. 167.191 usuarios engañados, y otros 88.413 comentando.

Bueno, como puede verse, los "Me gusta" terminan en páginas que está comprobado que no tienen nada que ver con Carlitos y su horrible enfermedad, sea cual sea.

Rastreamos al verdadero culpable, un defraudador llamado Jairo Daniel Castillo, hondureño, quien aparentemente basa parte de su negocio en el engaño, y podemos decir que ahora debe estar escondido en algún rincón de su casa tratando de evitarnos.

UPDATE: Este personaje, Jairo Daniel, me acaba de enviar una solicitud de amistad a través de Facebook, hoy 18 de noviembre de 2011. Me cuesta creer que sea tan arrogante como para creer que se la voy a aceptar. Acá está el perfil desde el cual quiere contactarme: http://www.facebook.com/Mr.Jairo.daniel. Si alguien quiere enviarle "saludos", ahí lo tienen. El "evento" que invita a ayudar a Carlitos fué dado de baja (no sé si hoy), pero NO la página principal, así que volví a denunciarla. Se vé que como en todos lados, la burocracia se toma su tiempo para arreglar las cosas que están mal. Por lo menos se bajó el evento... algo es algo.

Y por si queda duda de que este pedido de ayuda es falso, acá les posteo el lugar del cual sacaron la foto original, con datos reales y referencias:

http://patoral.umayor.cl/enfgen/enfgen.html

http://casodelmespatoral.blogspot.com/2008/02/caso-6-marzo-2008.html

Resulta que "Carlitos" es una niña africana después de todo.

Este tipo de personas son las que hacen lucro con nuestra solidaridad, así que ya saben, tengan cuidado y si quieren ayudar, busquen medios alternativos y ayuden a quien realmente lo merece.

Cambio y fuera.
:wq

sábado, 8 de octubre de 2011

¿Como no van a salir caros los lentes importados?

Hace unos días, perdí los lentes de práctica de tiro. Eran unos Guarder C3 Tactical Shooting Glasses, los cuales cumplieron su función perfectamente durante el tiempo que los tuve. Para peor, los usaba para andar en la calle ya que tenían un buen filtro solar y me quedaban cómodos como para conducir con ellos puestos. Después de todo, no necesitaba nada más complicado que un par de lentes de sol, y la protección extra que pudieran proveer me resultaba en un doble beneficio.

La cosa es que los perdí y no tengo idea de donde pudieron quedar, así que me puse en campaña para conseguir otro par de lentes con iguales o mejores características. Averiguando por lentes de buena calidad y alta protección balística (ya tuve un par de "accidentes" con armas y me quedó claro que la vista es el punto más vulnerable en estos casos), las mejores referencias siempre fueron para ESS (Eye Safety Systems), en cualquiera de las líneas que produce. Sus productos ofrecen una excelente protección balística, y cumplen (en exceso) con las especificaciones ANSI Z87.1+, OSHA y MIL-V-43511C, y son utilizados por las fuerzas de la ley, el ejercito y la marina en USA, así que decidí comprarme unos para probarlos.



He visto fotos de esos lentes, incluso después de un disparo directo de escopeta a 7 metros, y es increíble que las municiones no hayan podido atravesarlos. Hay varias historias de soldados que les envían cartas agradeciendo a ESS por sus productos, porque en incontables casos les ha salvado la vista. Mejores referencias no he visto en ningún otro lugar, ni con respecto a ningún otro producto.

De todos los que ESS fabrica, los que me parecieron más apropiados para mi caso fueron los ESS EyeShield ICE (Interchangeable Component Eyeshield) 2.4, ya que son modulares, cómodos y ofrecen un campo visual extendido, ideal para mantener una buena visibilidad (imperativo para situaciones de stress o ambientes en rápido movimiento, como la calle cuando uno maneja), así que preparé el pedido y los compré. No había muchas opciones para el shipping, así que el envío se hizo a través de FedEx.

Hace pocos días me llegó el aviso de que los lentes habían quedado retenido en Aduanas, así que tuve que hacer el trámite correspondiente. No es que no me lo esperara... son lentes muy específicos, aunque con los Guarder no me había pasado lo mismo. Esos habían venido directo por El Correo Nacional y no hubo misterios. Simplemente los trajo un cartero a la puerta de mi casa.

Como el paquete vino por FedEx, tuve que pasar por la oficina de ellos primero. A pesar de que el shipping ya estaba pago, tuve que desembolsar $ 950 por "gastos terminales y administrativos", lo cual me indignó hasta límites insospechados, sobre todo porque estos gastos únicamente me dieron acceso a una pequeña etiqueta autoadhesiva, sin la cual simplemente no podía siquiera iniciar los trámites de importación. ¿Como puede ser posible que FedEx me cobre en Uruguay algo que se supone que ya pagué en el país de origen?... Sinceramente, no lo entiendo. Considero que es un robo descarado, y debería ser delito, pero bueh... Vivimos en un país generoso. Hasta ahora, esta es la etiqueta más cara que he pagado...

Una vez con los papeles en regla, fuí a la oficina de Aduana, inicié el trámite y finalmente llegó el momento de verificar la carga. Esta tarea fué llevada a cabo por una agente verificadora de Aduanas, quien una vez que vió los lentes, dijo "Ah, son lentes de sol. Tienen que pasar por el Ministerio de Salud Pública."... Traté de explicarle que eran lentes de protección balística, y que como pensaba usarlos al aire libre, para evitar tener que usar lentes de sol encima o por debajo los pedí directamente de tinte oscuro. La verificadora me hizo ver lo fútil de mi explicación, ya que "obviamente son lentes de sol, y los tiene que ver el M.S.P.". Claro, debí suponer que explicarle a esta señora que esos lentes tenían características especiales más allá del simple filtro solar, era como tratar de enseñar a una ameba a hablar en griego...

Como sea, tuve que dejar los lentes en Aduana e irme al Ministerio de Salud Pública, donde hay una oficina que se dedica a la comprobación de la calidad de los productos, incluídos los lentes. Para mi sorpresa, allí me atendió una amable señora que me explicó la mecánica del trámite, los detalles, el costo y por si fuera poco, se solidarizó conmigo por la situación ridícula que estaba enfrentando. Todos conocen mis opiniones al respecto de los empleados públicos, así que fuí predispuesto a una larga sesión de espera infructuosa y a un desagradable período de tortura de manos de personas a quienes les pago el sueldo con mis impuestos... pero no, estaba equivocado. El trámite fué fácil y la atención un lujo, algo digno de una excelente empresa privada.

¿Porqué tuve que ir al Ministerio de Salud Pública?... Resulta ser que desde el año 2006 hay una ley que exige que todos los lentes que ingresen al país, cumplan con el requisito de tener filtro ultravioleta. El porcentaje de filtrado debe ser mayor al 95% para ser considerado aceptable. Para mis adentros pensé "¿Y qué pasaría si además se exigiera que dichos lentes soportaran un impacto de munición de .22 a 170 m/s?"... Estoy seguro de que muchos lentes no lo soportan.

Bueno, después de ir al M.S.P., fuí al aeropuerto de nuevo, a la fecha y hora que me dijeron que iba la persona que revisa los lentes y de nuevo pensé que iba a esperar horas, pero NO, apenas minutos después de entrar yo, aparecieron dos personas del M.S.P., portando una caja de 80x50x50 centímetros, conteniendo el equipo necesario para probar el filtro solar de los lentes. Entraron a la jaula (el depósito de la Terminal de Cargas del Uruguay) y me llamaron inmediatamente(!). Entré, abrimos el paquete (después de hacer el trámite de "apertura previa" en la Aduana), revisaron los lentes y me dijeron que fuera en unos días de nuevo al M.S.P. a buscar el certificado.

Fuí al M.S.P. cinco días después y me dieron el dichoso papel. Otra vez me atendió la misma persona, quien se acordaba de mi y me trató igual de bien que la vez anterior. Lo mejor de todo, es que no me cobraron el trámite (que suele costar una UR). Con ese papel volví a ir a la Aduana y finalmente pude hacerme de los lentes.

Como nota al margen, cabe destacar que el mismo día que fuí a buscar los lentes por primera vez, también me había llegado otro ítem que adquirí en el exterior (unos protectores auditivos Peltor de 26 db), y lo fuí a buscar a las oficinas del Correo Uruguayo, donde el trámite fué simple y fácil, y cuando le comenté a la persona que estaba a cargo del despacho la situación con los lentes, me dijo "Ah, no... acá si vienen lentes para particulares, los dejamos pasar. Si nosotros seguimos al pié de la letra todas las reglamentaciones del M.S.P., no podemos tampoco dejar entrar ni jabones, ni perfumes, ni shampoo, nada que toque la piel, así que imaginate..." (!!!).

Todo este tramiterío, idas y vueltas (tres veces a la Aduana, y dos veces al M.S.P.) sucedió en el correr de aproximadamente una semana. La verdad, me gustaron mucho los lentes, y no he visto acá en Uruguay ningunos que cumplan con todas las especificaciones de la misma manera, así que de alguna forma valió la pena... pero creo que no voy a volver a traer más, salvo que vengan por el correo uruguayo.

Y así ahora sabemos porqué los lentes importados salen tan caros...

:wq

jueves, 4 de agosto de 2011

There is no place like 127.0.1.50: Una historia de error

Hace tiempo que no escribo en el blog... pido disculpas a mis lectores, pero estuve inmerso en una maraña de sucesos que han hecho interesante mi vida más allá de todas mis expectativas... evitando que pudiera usar la computadora para otra cosa que no fuera trabajar (sin contar pequeñas pausas para no perder contacto vía FB...).

--

Muchas veces sucede que cuando estamos trabajando en algo y empiezan a aparecer problemas, tendemos a tratar de resolverlos lo más rápidamente posible para poder seguir adelante. Ya antes he hablado del "síndrome del sysadmin", y no me enorgullezco de decir que a veces aflora gracias a la eventual simultaneidad de ciertos problemas informáticos que parecen ser causados por diversos factores como el viento solar, la diferencia horaria generada por el tsunami asiático, la caída de las bolsas en Wall Street o quién sabe por qué otras esotéricas razones exactamente... Así es que uno a veces busca respuestas o soluciones de la forma más complicada, talvéz también debido a la estructura mental que caracteriza a los idiotas que hacemos de la administración de sistemas nuestro modo de vida (no se sientan agredidos, colegas... sé que no todos son idiotas como yo).

Hace un par de días me llamó un cliente para decirme que tenía problemas con su correo electrónico. Siendo que este cliente es una persona inteligente, versada y acostumbrada a las cuestiones tecnológicas e informáticas, cuando me dijo que tenía dificultades con el servicio de envío, asumí que NO se trataba de un usual y mero problema de capa 8 (situación también conocida como "PEBKAC", "PIBCAK", "PICNIC", o según la jerga militar yanquee "One Delta Ten Tango problem"). Referencias y alusiones ilustrativas pueden buscarse en Google.

Pedí detalles sobre el problema y el cliente me dijo que no podía enviar mensajes desde ningún equipo, y que el servidor tardaba mucho en responder, en el mejor de los casos. Las descargas de mensajes y el webmail funcionaban bien, así que el servicio que fallaba parecía no afectar a los otros servicios en el sistema.

Entré al servidor y comencé el diagnóstico standard. Pude ver que había varias conexiones abiertas desde una IP externa a la red, enviando mensajes a través de una conexión debídamente autenticada (esto es, usando SMTP-AUTH y con credenciales de acceso válidas). Como sabía que no había nadie de viaje en la empresa del cliente, y como esta dirección de origen correspondía a algún lugar en la China, parecía evidente que este "usuario" conectado no era trigo limpio. Examinando los mensajes encolados en el servidor y que este usuario estaba enviando, veo que se trata de SPAM, así que desactivé la cuenta y limpié la cola de mensajes para evitar más daños (más tarde tendría que hacer los trámites de salida de las blacklists correspondientes y también tendría que implementar políticas más restrictivas al respecto de las credenciales de acceso al servicio). Habiéndome asegurado de que el spammer no podía volver a conectarse desde esa red, ni siquiera con nuevas credenciales de acceso, me puse a verificar otros parámetros del servicio, dado que aún no funcionaba como debía.

Así fué que ví que había una serie de conexiones abiertas desde y hacia la dirección IP 127.0.1.50...

En este punto estoy seguro de que muchos lectores experimentados en las artes del manejo de redes y servicios estarán sospechando cual es el problema en realidad... pero dejaré igual que sigan leyendo, esperando que de esta historia salga una moraleja útil para alguien.

Como la concurrencia de conexiones al servicio SMTP está limitada (como forma de controlar los recursos del servidor), una vez que se llegaba a la cantidad máxima de conexiones permitidas, el servicio simplemente dejaba de responder, hasta que las conexiones se resolvieran (se cerraran).

Mi primer impresión fué que algo o alguien había logrado ejecutar un claro spoofing de la dirección IP 127.0.1.50, inyectando paquetes desde la red e iniciando conexiones en el servicio SMTP. Lo primero que hice fué ejecutar una captura de tráfico en el enlace externo para verificar el verdadero origen de los paquetes. Me contrarió no encontrar nada en el tráfico externo, así que capturé paquetes en las otras interfaces para ver si el "ataque" provenía de la red lan. Tampoco vi nada. Razonando la situación, me dí cuenta de que es simplemente imposible que existan conexiones establecidas desde una dirección perteneciente a la red 127.0.0.0/8 "spoofed" sobre una interfaz externa, porque un paquete SYN con ese origen debería ser contestado entregando el SYN/ACK a través de la ruta local del sistema hacia la dirección origen de la conexión, con lo cual el destino de dichos paquetes debería ser invariablemente la interfaz loopback... evitando que las conexiones pudieran establecerse en primer momento. Si bien se puede instruir al kernel para que entregue respuestas a través de la misma interfaz que las recibe, bypasseando las rutas de la tabla de encaminamiento de paquetes, yo estaba seguro de que este NO era el caso. Ojalá hubiera seguido razonando sobre esa misma línea, en vez de echarme a perseguir fantasmas durante el resto del "evento", hubiera ahorrado tiempo y recursos valiosos. En cambio, asumí que el ataque tenía que provenir desde el "interior" del servidor entonces, mediante alguna técnica posíblemente menos sutil.

Todos sabemos que esa dirección forma parte del bloque de direcciones 127.0.0.0/8, el cual está asociado a la interfaz loopback (ver RFC3300), lo cual me hizo sospechar que se trataba de algún tipo de ataque de ejecución remota, el cual había logrado utilizar la dirección de la loopback como origen. Supuse que de alguna manera habían podido subir un script y lo habían ejecutado para hacer spam (que es el propósito más común de este tipo de ataques hoy día). Antes de cortar las conexiones, exploré el sistema en busca del script, pero para mi sorpresa, no encontré nada.

Revisé logs de servicios, sobre todo el del servicio web (Apache) y si bien ví intentos de acceso a software que no tengo ni uso (como el phpBB, el phpMyAdmin, etc.), no encontré nada que demostrara que alguien había subido un programa o script y lo había ejecutado. Verifiqué los ejecutables básicos del sistema mediante checksums y comparación con los de otros sistemas "sanos", revisé los módulos cargados en el kernel (en busca de rootkits de tipo LKM), listé los archivos abiertos en el sistema, las conexiones activas, examiné los subdirectorios de procesos en el directorio /proc en busca de ejecutables eliminados, procesos con nombres cambiados o indicios de invocaciones extrañas, revisé el filesystem para ver si había archivos con nombres extraños o en directorios donde no debería haberlos, el /tmp, el /dev, directorios o archivos que comienzan con "." o que se llaman "...*", etc... y seguí sin encontrar nada...

Descargué y ejecuté rkhunter y chkrootkit, y aunque ya había hecho manualmente los chequeos que estos dos softwares hacen, decidí intentarlo a ver si se me había escapado algo inadvertidamente. Nuévamente, NADA.

En este momento empecé a preocuparme seriamente... ya que si alguien había tomado posesión de ese servidor y estaba ejecutando algo, su método de ocultación era, para todo propósito, simplemente perfecto.

Opté por cerrar las conexiones y hacerle un seguimiento intenso con el fin de descubrir algo que me llevara a encontrar al atacante. Talvéz algún cracker había subido, ejecutado y eliminado toda traza de algún software en un movimiento único... lo cual era improbable, pero "posible". Tal atacante se merecería más que respeto de mi parte, así que decidí no dejar nada al azar y vigilar la actividad del servidor muy de cerca, más de lo que el tiempo del que dispongo para dicha tarea me lo permite.

Una hora después, el problema volvió a aparecer. Otra vez intenté dar con el causante sin poder hacerlo, lo cual me inquietó más aún. Esta vez terminé las conexiones y restauré el servicio en forma inmediata, dado que lo que fuera que pasaba estaba sucediendo tán rápido que evitaba que yo pudiera tomar acciones preventivas a tiempo. Evalué incorporar un bloqueo mediante iptables con el propósito de evitar nuevos intentos de acceso desde/hacia esa dirección, pero asumí que estaba frente a un atacante lo suficientemente habil como para darse cuenta del mismo y naturalmente que su paso siguiente sería probar otra dirección IP. Evalué también poner reglas sobre todo el bloque 127.0.0.1/8, exceptuando el 127.0.0.1 y el 127.0.0.2, que son las únicas dos direcciones necesarias (bueno, la primera al menos) para el correcto funcionamiento del servidor, pero eso daría por tierra con mi intento de encontrar al causante del problema, así que dejé todo como estaba, en espera de poder seguir mi búsqueda. Otros asuntos me llamaron al deber y tuve que dejar de monitorear este servicio para atenderlos, así que a pesar de mi renuencia, me separé de la terminal y fuí a seguir mi rutina diaria.

Horas después, verifiqué el estado del sistema y estaba normal, así que decidí poner manos a la obra y escribir un script que chequeara el sistema de forma constante (con una ventana de un segundo) y que sacara una "radiografía" del servidor en ese preciso instante, en caso de detectar actividad de esa dirección IP, con el propósito de tratar de encontrar el vector de ataque en caso de que la situación volviera a suceder. Esa sería una herramienta invaluable para descubrir al habil atacante. Terminé el script, lo probé y lo dejé en ejecución, esperando que las respuestas fuesen reveladas.

Seguí con otras cosas y en la noche recibí una notificación del script indicando que otra vez estaba sucediendo el "ataque". Con los archivos generados por el script, esperaba obtener una solución definitiva... y finalmente la obtuve, aunque no era lo que yo esperaba.



En los servidores de correo que instalo, utilizo una versión modificada de QMail. Entre las modificaciones y herramientas accesorias que utilizo, tengo un script que escribí y que hace de "proxy" entre los clientes externos y el software que dá el servicio. Dicho script chequea ciertos parámetros de las conexiónes antes de permitir el establecimiento de las mismas directamente con el sistema interno que gestiona el servicio SMTP. Entre los chequeos que hace, se encuentra la verificación del reverso DNS de la IP del cliente, la comparación de la IP y del reverso contra una blacklist interna, la pasada de la conexión por un proceso de "greylisting" (con el propósito también de asegurar que la misma se hace desde un servidor de correo legítimo, el cual volverá a reintentar la conexión más tarde en caso de haber sido rechazado la primera vez), el registro de la conexión y de la sesión, con puertos de origen y destino, con fines de monitoreo y diagnóstico, etc. Este script "escucha" en el puerto 25 del enlace externo (en caso de que haya más de un enlace de acceso al servidor) y decide si la conexión se establece o no dependiendo de los parámetros de la misma. Se supone que no puede haber en Internet un servidor de correo electrónico legítimo ejecutándose sobre una dirección IP dinámica, o sobre una dirección IP que no tiene reverso de DNS, o cuyo reverso DNS indique claramente que se trata de una dirección IP que no está asignada a ningún recurso en particular.

Como muchas veces sucede, algunos servidores de correo legítimos están activos sobre direcciones IP que no tienen reversos de DNS, ya sea porque los ISP a los que pertenecen no permiten o no usan dichos reversos, o porque los administradores de sistemas de dichos servidores ni siquiera saben que semejante cosa existe o se usa, o simplemente porque esos administradores no tienen ganas de asignarle un reverso de DNS a sus IP (hasta hace pocos años, los servidores del dominio "hsbc.com.ar", la sucursal argentina del conocido banco inglés, NO tenían reversos de DNS, por ejemplo).

Como mi script no permite conexiones desde direcciones IP sin reverso DNS, a veces rechazábamos correo emitido desde servidores legítimos pero mal administrados, con las consecuencias obvias para los clientes. Para evitar rechazar mensajes de correo electrónico de servidores legítimos pero cuyas direcciones IP no tienen reversos de DNS, se me ocurrió implementar un chequeo denominado "callback", el cual tiene como propósito verificar que el servidor que se conecta con nuestro servidor y que no tiene reverso de DNS, sí tiene un servicio SMTP activo, lo cual disminuye el riesgo de que se trate de una fuente de spam (en el mundo real, este chequeo no es tán efectivo, dado que cualquier spammer que vaya a usar una dirección IP sin reverso puede crear un servicio SMTP ilegítimo con la capacidad de burlar el método de callback, pero es preferible aceptar diez mensajes de spam que rechazar un mensaje legítimo).

El metodo de callback implica que el servidor que aún espera permitir la conexión desde la dirección IP sin reverso, genere una nueva conexión hacia el puerto 25 de dicha IP y ejecute ciertos comandos SMTP destinados a verificar la fuente. Una vez que la fuente es verificada (o sea que los comandos recibidos por la misma se ejecutan y generan una respuesta acorde con el protocolo), la conexión se permite. El caso contrario, la conexión se cierra y el script bloquea la dirección origen dejando una entrada en el registro del servicio. En este caso, el programa que hace el callback es un simple script en perl que escribí hace unos años para probar conexiones, modificado para agregar el envío de comandos SMTP y procesar la salida. ¿Porqué es importante que mencione esto? Bueno, resulta ser que el "ataque" en realidad se podría decir que fué "autoinflingido"...

En alguna parte del planeta, un malévolo sysadmin creyó que era una buena idea asignar la dirección IP 127.0.1.50 como registro MX (Mail Exchanger) de un dominio real en Internet. O bien es "malévolo" o "estúpido", o talvéz las dos... No está claro. Talvéz sea política standard de la empresa para la que trabaja este "sysadmin" hacer ese tipo de cosas, pero sincéramente no se me ocurre una buena razón para hacer esto (bueno, pensándolo bien, puede ser un retorcido mecanismo antispam...).

¿Qué pasó entonces en realidad? Simplícimo: nuestro servidor (de nuestro cliente en realidad) recibió un spam (enviado por nuestro "amigo chino") con dirección de remitente en un dominio que tenía como registro MX la dirección 127.0.1.50 (hubiera dado lo mismo que tuviera cualquier dirección dentro del rango 127.0.0.0/8), y al intentar enviar el mensaje correspondiente, nuestro servidor inició la conexión SMTP al puerto 25 de esa dirección IP, lo cual hizo que se conectara a sí mismo (dado que todo el bloque 127.0.0.0/8 "contesta" como si las 16.777.214 direcciones que forman parte del bloque estuvieran activas), lo que a su vez disparó el script que chequea las conexiones, el cual al ver que la dirección IP 127.0.1.50 no tenía reverso de DNS, inició el script de callback (para chequear que el origen de la conexión era un servidor de correo legítimo), que inició a su vez otra conexión hacia la dirección origen de la conexión inicial, que al haber sido generada desde la dirección IP 127.0.1.50, volvió a iniciar otra conexión al puerto 25 de la dirección 127.0.1.50, la cual fué atendida nuevamente por el script de chequeo de conexiones, el cual a ver que la dirección no tenía reverso DNS, inició el script de callback, el cual inició otra conexión a la IP de origen, la cual inició el script de chequeo de IP, el cual inició el proceso de callback... y así sucesivamente, entrando en un bucle infinito, el cual se enlenteció cuando se establecieron todas las conexiones posibles como valor máximo permitido. A medida que las conexiones expiraban (por timeout), iban saliendo de la lista de establecidas, permitiendo nuevas conexiones, lamentablemente idénticas.

Esto sucede tán rápido en realidad, que uno no se dá cuenta hasta que todas las conexiones están ocupadas. Es una avalancha de conexiones que parecen simultáneas, y solo se pueden detener matando todas las instancias de los procesos implicados al mismo tiempo.

El descubrimiento de esta situación fué agridulce... De alguna forma sentí haber tenido una epifanía, y al mismo tiempo sentí una terrible vergüenza al darme cuenta de lo torpe que fuí al no ver lo que en otras circunstancias me hubiera resultado obvio. De hecho, sí lo vi al hacer el análisis inicial del que les hablé arriba al respecto de las conexiones desde y hacia direcciones asignadas a la loopback, pero de alguna forma no llegué a hacer la asociación hasta mucho después.

Me metí en una cacería de fantasmas, enceguecido por las ánsias de atrapar a un atacante súmamente hábil y cauteloso, sin darme cuenta de que básicamente estaba persiguiendo mi propio trasero, tal y como lo hacen los perros.

Finalmente, luego de terminar mi análisis, modifiqué el programa de chequeo de conexiones para que esto no vuelva a suceder. Se podría decir entonces que algo bueno surgió de todo esto. Fué lo que se dice "una experiencia educativa", aunque en el estado en el que estoy estos días, lo que menos necesito es otra de estas experiencias. Lo que necesito realmente son vacaciones... y seguramente mi desempeño durante este evento fué un claro indicativo de ello.

:wq

 
Gustavo Castro

Crea tu insignia