Archivo del Autor: phenobarbital

Las bases de datos gritonas: una explicación a Unicode

Cuenta la cultura de Internet que escribir todo en mayúsculas es gritar, parte de la “etiqueta de Internet” (o Netiqueta) surgió de las nuevas formas de comunicación, como los BBS y los foros de discusión que llevaron incluso a la IETF a categorizar dichas reglas de etiqueta en un RFC (RFC 1855).

Es por eso que, ¡SI LES ESCRIBO ASÍ LES ESTOY GRITANDO!, ¡OYERON! …

“El grito” en bases de datos

En los inicios, cuando sólo existía ASCII, las cadenas de texto sólo podían ser representados con algunos de los 127 carácteres de 7-bit representados en la tabla ASCII:

Para los niveles de almacenamiento de la época era más que suficiente, además la cantidad de “idiomas” incorporados a la computación además del inglés era “casi nula”, así que ASCII vivió sus días de Gloria escribiendo bases de datos con simples y hermosas letras (mayúsculas y minúsculas) no acentuadas.

Sin embargo, las computadoras almacenaban bytes de 8-bits, así que nos sobraba “un bit”, muchas personas alrededor del mundo tuvieron ideas “diferentes” de cómo representar más carácteres, en general, la forma más popular fue el estandar ANSI-ISO/IEC 8859, que “más o menos” mantenía intactos los primeros 128 carácteres pero agregaba otros más como “la eñe” y la á acentuada.

Esto creó un grave problema para los “trabajadores” de las bases de datos, que ahora tenían que lidiar entre JOSE, JoSE, JOSé y JOSÉ como derivaciones del mismo escrito (pero a nivel lógico, cadenas completamente diferentes), convenciones como “todo debe escribirse en mayúsculas y sin acentos para evitar problemas” comenzaron a surgir.

Otro punto a favor de este mito ocurrió con los Code-pages, cada “idioma” en ISO-8859 tenía su propia “codificación” (ejemplo: para el alfabeto latino era ISO-8859-1) por lo que el ISO-233 (é latina con acento agudo) en el conocido latin1, representa la letra yā (ي) en ISO-8859-6 árabe lo cual significaba DESASTRE a la hora de mover aplicaciones de datos de un idioma a otro.

En definitiva, el mundo en los 90 eran distintos, apenas “saliendo” de la guerra fría, nadie se le hubiera ocurrido tener más de un idioma en un mismo computador, mucho menos almacenar datos en diversos idiomas.

Y en eso llegó Internet …

Con Internet vino el advenimiento de las comunicaciones globales y de hecho, se “enraizaron” los fundamentalistas que, con más razón, las bases de datos debían almacenar los datos con la menor complejidad posible, incluso, si eran 7-bit ASCII, que fueran los octales más bajos (las letras mayúsculas), y así se ha mantenido muchísimas cosas hasta ahora.

Con Internet llegó UNICODE, y con él una mejor forma de escribir todos los caracteres posibles inventados por el hombre (UTF-7, 8, 12 ó 16).

Unicode en parte se sincroniza con ASCII-7 en sus primeros carácteres (por eso, ARBOL en ASCII y ARBOL en UTF8 se representan igual), sin embargo “Árbol” o “ñandú” se representan con carácteres acentuados en valores octales distintos en ISO-8859-1 y en UTF-8.

¿y el espacio?

Como es imposible representar miles y miles de carácteres con solamente 8-bits, entonces UNICODE echa mano del multi-byte, es decir, un glifo o carácter puede requerir más de un byte para representarse, algunos dicen “Unicode es un sistema de 16-bits por ende una cadena UNICODE mide más que una cadena ASCII o Latin1″, es entendible este error común acerca de un encoding multi-byte, pero es errado.

En general, Unicode es multi-byte, así que aquellos (y sólo aquellos) glifos que no pudieran ser representados con 8-bits serán representados con más de un byte; ejemplo, una A ocupa los bits “0100 0001″:

A -> 0100 0001

A mide 8-bits, por ende, en UTF-8, los carácteres de la tabla desde 0-127 serán representados por un solo BYTE (la razón por la cual, “ARBOL” en ISO-8859-1 y “ARBOL” en UTF-8 lucen exactamente idénticos), el resto de carácteres y glifos serán representados por combinaciones de 2 y hasta 6 bytes.

Un buen ejercicio es crear en postgreSQL 2 bases de datos, una en SQL ASCII y otra en UTF-8, llenarla con cadenas regulares y preguntar ¿cual mide más?:

He creado una tabla “testnames”:

CREATE TABLE testnames
(
 id serial NOT NULL,
 test character varying,
 CONSTRAINT pk_test PRIMARY KEY (id)
)

La cual hemos llenado con 1000 cadenas sencillas:

insert into testnames(test) select * from  repeat('abcdef',1000);

Y luego le preguntamos a TOAST cuanto miden ambas tablas:

select pg_column_size(test), pg_column_size(repeat('abcdef',1000)) FROM testnames;

Lo cual es *no* sorprendentemente el mismo resultado:

pg1

abcdef mide exactamente igual (en bytes) en UTF-8 que en ISO-8859-1 (32Kb en espacio en disco).

¿Dónde queda la META?

El gran culpable de esta discusión es el carácter de error de encoding o -> � el cual tristemente aparece en más páginas web de las que uno se imagina; pero para algo que se cura con:

Content-Type: text/html; charset=UTF-8

O usando XML con:

<?xml version="1.0" encoding="UTF-8"?>

No entiendo por qué para “evitar” tener que codificar y re-codificar adecuadamente (o forzar una codificación en las aplicaciones a nivel programático) entonces ¿por qué no seguir escribiendo con únicamente los primeros 128 carácteres de la tabla ASCII?

Porque vivimos en un mundo globalizado.

¡YO NO ME LLAMO ASÍ!

En efecto, nuestro hermoso idioma, el español, difiere en muchísimas cosas del inglés (que valgame Dios, puede ser escrito bien con ASCII, UTF-8, ISO-8859-1 y con *casi* cualquier codepage o charset que exista), empezando por su nombre y esa letra N con sombrerito sinuoso (la Virgulilla o “rabo e’ cochino” para los venezolanos), pero igual de hermoso es el cirílico, el arameo o el árabe, por ende, pretender decirle al mundo que toda cadena plana y llana es un ASCII es un absurdo.

De hecho, como leí por allí alguna vez ¡”no existe esa cosa mal llamada el *texto plano*”, punto!.

Hay miles de millones de personas leyendo en idiomas y codificaciones de carácteres que van más allá del carácter 127, hay que respetarlos.

¡Y no!, mi nombre, mientras la Real Academia Española de la Lengua no derogue los acentos es Jesús, no es JESUS ni jesus; Es *Jesús*, con la J mayúscula (en señal de un nombre) y con la ú acentuada, es que incluso, si se escribe en mayúsculas, es ¡JESÚS!, esa regla que algunos se inventaron de que “las cosas en mayúsculas no se acentúan” no existe.

La codificación Moderna

El último incoveniente viene de la adaptación, mientras algunos profesores universitarios aún dan clases de bases de datos con viejos dinosaurios como FoxPro (ASCII), Access (ISO-8859-1) ú Oracle 8 (ANSI UNICODE) (todas de fines de los 90, cuando UTF-8 estaba en pañales) en la actualidad, interactuar con usuarios de diferentes codificaciones viene reflejado por simplemente ejecutar un:

SET NAMES = 'UTF8'

E incluso, bases de datos modernas como PostgreSQL soportan diversas codificaciones entre bases de datos y diversas versiones (COLLATIONS) de UNICODE incluso en una misma tabla, con columnas en diferentes locales; además, “ARBOL” y “arbol” y “Arbol” son completamente iguales si usamos ILIKE y otros tipos de búsquedas no-sensibles al uso de mayúsculas.

Dejo de gritar …

¡Oye!, ¡Qué ese pájaro no se llama Ñandú, sino NANDU! …

La posibilidad infinita de permitirle a una persona escribir su nombre, correctamente, con todas sus letras, acentos y carácteres diacríticos es para mí, más que suficiente, para adaptarme y hacer conversiones de CHARSET a conveniencia, hacer operaciones de “Capitalizado” y “lowercase” y agregar etiquetas META correctamente, que tener que almacenar sólo 127 carácteres por ahorrarme unos pocos bytes y un esfuerzo de codificación (y decirle a la gente que no se llama como lo registraron en su partida, sino como a mí, el DBA de turno, me da la gana llamarlo).

A ver si nos modernizamos un poco y abandonamos ese hueco en la arena donde te escondiste con tu ANSI SQL89 y tu SQL ASCII y nos alzamos de patas como las Suricatas, para ver que hay un hermoso mundo que describir allá afuera …

… y por favor, ¡con acentos!.

[OpenLDAP] Password policies

He incorporado una nueva entrada sobre openLDAP, referente a los password policies (política de contraseñas).

Puedes leerla acá: http://blog.phenobarbital.info/2014/10/openldap-password-policies/

Del por qué Lácteos los Andes usa UPC y no EAN

y otras absurdas afirmaciones …

 

Mientras dictaba una charla-taller de postgreSQL y programación en PL/Python, se me ocurrió hacer algo bastante simpático y que a Python se le da bastante bien y es una operación matemática, más especificamente para validar el código de barras de los productos (código EAN) y puse a mis compañeros a escribir una sencilla función en PL/Python y que, combinada con un Dominio, funcionaba de maravilla.

Eso, me llevó a escribir el siguiente artículo en mi blog técnico.

para saber más: http://blog.phenobarbital.info/2014/10/crear-un-dominio-en-postgresql-para-validar-codigos-de-barra/

 

Sin embargo un resultado imprevisto surgió de dicho ejercicio, y es que al taller nos enviaban refrigerios variados de Lácteos Los Andes (naranjada y jugos) y al intentar probar nuestra función de códigos de barra, los códigos de barra de dichos productos fallaban …

¿Cómo puede ser eso?, ¿cómo la industria láctea “bandera” del Estado Venezolano puede estar emitiendo códigos de barra corruptos en sus propios productos? …

Pues para quien no lo crea, acá una foto:

Choco-Lat Lacteos Los Andes

Choco-Lat Lacteos Los Andes

El producto es un “Choco-Lat”, bebida achocolatada hecha por Lácteos Los Andes en las plantas de Nueva Bolivia, Estado Mérida y Cabudare, Estado Lara, también lo verifiqué en el Papelón con Limón y el jugo mixto.

codigo_barras

Entre otras cosas:

  • El código tiene un valor par (12) de longitud, lo que lo hace un UPC Americano (Universal product Code)
  • Aunque el código de empresa está bien (709862) al no empezar en cero (0709862) falla el reconocimiento por ser un código de producto erróneo para el checksum digit asociado.
  • Si el código de producto fuera 01201 y no 01301, el checksum sería 4, el código sería: 709862012014 y la función indicaría que es un código válido.
  • 709 es el código GS1 para Noruega (en EAN)
  • El Global Trade Item Number válido para ese producto debería ser: 00709862013011

Tal vez Lácteos Los Andes buscaba “ahorrarse dólares con GS1″ dirán alguien por allí, sin embargo, este es un trámite que sugiere el propio organismo regulador SENCAMER (Una institución del Estado) y la representación de GS1 en Venezuela (Adscrita a FONDONORMA) emite códigos EAN completamente gratis a las empresas que se inscriban y paguen una membresía anual en GS1 de Venezuela.


GLN 0709862000004
UPCPrefix 709862
GS1Prefix 0709862
CompanyName Lacteos Los Andes, C.A.
StreetAddress Apartado 51442
City Caracas
ZipCode 1050-A
StateProvince
Country Venezuela
PrefixStatus Active
ModifiedDate 2013-11-22T00:00:00

¿Por qué entonces, en vez de usar códigos EAN universalmente aceptados, echa mano de códigos UPC americanos?

Como dice la propia página de GS1:

GTIN-12 (UPC-A): this is a 12-digit number used primarily in North America

Esta bien, ellos son buena-nota con el Imperio y decidieron etiquetar no con el universal EAN-13 o GTIN-14 sino con UPC-A americano y pagar los 2500US$ (con renovación anual de 500US$) que UCC exige por usar el código, mientras que en Venezuela, con el apoyo de SENCAMER, le pagas una membresía anual en bolívares a GS1 de Venezuela, con emisión de códigos EAN-13 completamente GRATIS.

Pero no, UPC/GTIN-12 es un código más chevere, porque tal vez pensamos exportar papelón con limón para USA.

Sigan mi nuevo (viejo) blog!

Mi blog phenobarbital.info se había quedado sin hosting por casi un año, he vuelto a recuperarlo de sus respaldos y está ahora online.

Será netamente técnico con algunas dosis de frikismo geek, así que los espero por allá y lo sigan tanto como a este.

Si notan mucha publicidad en ese blog, bueno, les pido disculpas de antemano, el blog está en un hosting VPS que se debe pagar y aunque trato en lo posible de seguir en mi ruta de publicar lo más que pueda sobre software libre y abierto en español, necesito cubrir los gastos del VPS y los ads son una forma de hacerlo.

Espero no les molesten mucho, le den algunos “clicks” y mantengan vivo ese blog.

 

Gracias y por allá los espero!.

 

[OpenLDAP] Bitácora de instalación

He decidido recuperar mi blog técnico, y para comenzar su uso, he incluído una completa guía de instalación, configuración y personalización del servicio de directorio OpenLDAP bajo Debian GNU/Linux.

Espero poder contar con sus visitas y comentarios en esta nueva etapa de documentación en mi blog.

Gracias y allá nos vemos!

[PostgreSQL] Crear triggers dinámicos con postgreSQL

¿Qué es un trigger dinámico?, es aquel trigger que la metadata de en cual tabla/campo va a operar es pasado de manera dinámica (parámetros) a la función de trigger (trigger function).

¿Y para qué sirve?, bueno, imaginen un sistema dónde cada operación debe ser por ejemplo, agregada a una tabla auditoría, o por ejemplo, que una operación en una tabla, causa una operación en otra tabla, que aunque el código sea *casi* el mismo, depende de la tabla que dispara el trigger, qué tabla va a operar.

La utilidad de esto es simplemente poder re-utilizar una única funcion trigger para diversas acciones a ser tomadas de acuerdo a los parámetros recibidos.

El ejemplo

Este ejemplo se construyó durante un taller de postgreSQL que estaba dictando, el criterio era el siguiente:

  • El trigger toma el valor insertado en una tabla
  • Busca dicho valor en otra tabla, usando otro campo como criterio
  • Si el valor no existe, retorna NULL
  • Si el valor existe, retorna el objeto NEW del disparador, con lo cual la inserción sí ocurre

Los campos TG_*

En los disparadores de postgreSQL se cuenta con un conjunto de variables muy útiles, como son:

  • TG_OP: define la operación realizada en la tabla (INSERT, UPDATE o DELETE)
  • TG_TABLE_SCHEMA: define el schema al que pertenece la tabla (ej: “public”)
  • TG_TABLE_NAME: define el nombre de la tabla que disparó este trigger
  • TG_ARGV: es un arreglo (array []) que contiene los parámetros enviados a una función de trigger.

Con esto podemos hacer cualquier tipo de condicional en la función de trigger, reduciendo el código a sólo una función que se usará, de acuerdo a los parámetros que se le pasen.

La Función

CREATE OR REPLACE FUNCTION permitir_insert() RETURNS trigger AS

Comenzamos con la definición, la llamaremos “permitir_insert()” y obviamente, retorna un trigger.

luego, en la sección de declaración, definimos las únicas variables que vamos a necesitar para este ejemplo:

 vrecord integer;
campo text;
tabla text;
id int;
rc int;

BEGIN

En el cuerpo de la función, preguntamos qué tabla y campo voy a consultar para verificar si permito o no el insert, esto se hace consultando a TG_ARGV:

 tabla := TG_ARGV[0];
campo := TG_ARGV[1];

Como ven, ya que podamos recibir cualquier cantidad de parámetros en el trigger, las opciones son infinitas.

Ahora, necesito saber que hay en el campo trigger (NEW.campo), en este caso, debo reemplazar “campo” con el nombre del campo de la tabla que disparó el trigger (y que voy a consultar en otra tabla), como en mi caso el valor de el “campo” en todas las “tablas” que usarán esta función de trigger es entero, he declarado “vrecord” integer, si su tipo será distinto, sería conveniente declararlo “anyelement”.

EXECUTE 'SELECT ($1).' || quote_ident(campo) || '::text' INTO vrecord USING NEW;

Lo que hace ese código, es ejecutar un $1.”campo”::text (dónde campo es una variable) y mete su valor en la variable “vrecord”, se usa el objeto NEW para la sustitución del $1.

Ejemplo, si el campo se llama “piezas“, ese “EXECUTE” quedaría “NEW.piezas” y entonces metería el valor de NEW.piezas en la variable “vrecord”.

¿sencillo, no?.

La consulta

Ahora, debo verificar que en el campo “campo”::text de la tabla tabla::text (variable) existe un valor con lo que está contenido en “vrecord”, de lo contrario retorno NULL y el trigger no se ejecuta (la operación de inserción no ocurre).

Sería algo como un “constraint” pero sin usar reglas de constraint, ¿entendido?.

IF TG_OP = 'INSERT' THEN

EXECUTE format('SELECT '||quote_ident(campo)||' FROM '||quote_ident(tabla)||' WHERE '||quote_ident(campo)||' =$1') USING vrecord INTO id;

En este caso, he ejecutado un SELECT (SELECT “campo”::text FROM “tabla”::text WHERE campo::text = vrecord), claro que haciendo las conversiones y los reemplazos respectivos.

El valor de esa ejecución lo agrego a la variable id.

Si adicionalmente se desea averiguar si esa consulta anterior retornó filas, colocamos seguidamente al EXECUTE:

GET DIAGNOSTICS rc = ROW_COUNT;

Si “rc” es igual a cero, entonces no existe el valor “vrecord” en el campo “campo” de la tabla “tabla”, caso contrario, se retorna NEW.

 IF rc = 0 THEN
    RAISE EXCEPTION 'no existe el valor % en el campo % de la tabla %', vrecord, campo, tabla;
    RETURN NULL;
END IF;
RETURN NEW;

Y listo!, definimos el cierre y que esta es una función VOLATILE:

END;
LANGUAGE plpgsql VOLATILE

Y ya podemos usarla.

Usando la función dinámica

Para usar la función dinámica, simplemente creamos un trigger en cada tabla que necesite convocarla, pasando como parámetros de la función trigger la tabla referencia y el campo que debe evaluar, ejemplo:

CREATE TRIGGER trg_insert_detalle_reportes
BEFORE INSERT
ON reportes
FOR EACH ROW
EXECUTE PROCEDURE permitir_insert('reportes', 'id_reporte');

Se insertará un detalle de reporte, solamente si el valor de “id_reporte” aparece en la tabla “reportes”.

Conclusiones

Sé que parece muy “rebuscado” un ejemplo que bien podría salir con una clave foránea, pero sirve para el hecho de demostrar la posibilidad de obtener e iterar sobre el objeto NEW, consultar metadata al “information_schema” o realizar cualquier operación de manera dinámica, pasando parámetros y consultando las variables mágicas TG_* de postgreSQL.

¿Se les ocurre alguna idea para estos triggers dinámicos? …

Historia de un script

Siempre me gusta tener un repositorio Debian en un disco portable, una conexión decente en dónde vivo (Guanare) es inexistente y de igual manera en el resto de ciudades, es mejor instalar Debian rápidamente que tener que esperar 2 horas de descargas.

Sin embargo, actualizarlo es otra cosa muy distinta, debo contar con una conexión “decente” (por encima de los 200kB/s) o podría pasar días enteros esperando a que “sincronize”, a veces, los archivos quedan “truncados” o no se descargan correctamente (uso rsync y si un archivo no se descarga correctamente, salta al siguiente y ese queda en falla).

Entonces escribí este script (https://github.com/phenobarbital/check_debian_repository), que, aunque está en sus inicios, aplica la filosofía del IDM (Internet Download Manager) y de los Download Accelerators, para descubrir qué archivos faltan en un mirror Debian y descargarlos en paralelo.

Por qué haría algo así? y por qué nadie había hecho algo parecido?, bueno, cuando tu velocidad promedio de descarga es:

>f+++++++++ pool/main/libr/libreoffice/libreoffice-help-zh-tw_4.2.6-1~bpo70+1_all.deb
1.93M 46% 162.71kB/s 0:00:13

162kB/s (y estaba rápida, son las 4 am) mientras amigos en países incluso consideradores “tercer mundo” con El Salvador o Guatemala poseen conexiones de 5MBps ó 10MBps, yo me tengo que conformar con “viajar” a Barquisimeto y conectarme al ABA de CANTV de la casa de mi mamá qué cuando funciona “de maravilla” (como ahora, a las 4am) reporta que es de 1.2MBps (aunque pago por 2MBps). La cosa no es que la conexión “sea cara” es que literalmente no existe.

Entonces, uno termina haciendo cosas que solo sirven para países en condiciones como las nuestras, espero que alguien más, con la necesidad de tener un mirror Debian multi-arch sincronizado y que tenga una conexión pobre, le sirva este script.

Saludos.

[ Motorola Android ] Rescatando al soldado Atrix 4G

El ladrillo …

Me encontraba probando varias ROM en mi Motorola Atrix 4G, cuando de repente sucedió lo imprevisto, la última ROM decidió no arrancar y cuando quité la pila y la volví a colocar, el teléfono inició indicando:

Failed to boot: 1

Oh Dios!, un soft-brick!, bueno, no importa!, eso se arregla con una ROM oficial Stock, en mi caso tenía en mi disco la:

1FF-olympus-user-2.3.4-4.5.91-110625-release-keys-signed-ATT-US-GAS_NA_OLPSGBATTSPE_P011.sbf

Uso el cargador RSD y … Oh Dios!, Failed to boot otra vez y esta vez ni siquiera el fastboot funciona! …

Bueno, vamos a entrar en modo RSD Protocol, para ello:

  • Sacamos la batería
  • Presionamos “Volume UP” y a su vez “Volume DOWN”
  • Metemos la batería
  • Encendemos el equipo

E intento aplicar usando el RSD protocol (protocolo para meter binarios en la NAND de equipos Motorola) el SBF:

1FF-olympus-user-2.3.6-4.5.141-111212-release-keys-signed-ATT-US-GAS_NA_OLPSGBATTSPE_P012.sbf

Y ahora el equipo ni siquiera entra en modo RSD! …

Panic Mode on!, un Hard-Brick? …
Lo bueno es que si uso el procedimiento “de emergencia” del protocolo RSD/Fastboot de Motorola:

  • Sacamos la batería
  • Presionamos “Volume UP”
  • Metemos la batería
  • Conectamos el cable micro-USB

El equipo se encenderá automáticamente y la pantalla indicará:

Failed to boot: 1
PwrReason: USB_CABLE
Starting fastboot protocol support

Sin embargo es un fastboot inútil, no puedes leer nada y no puedes flashear nada … entonces?

Para colmo, comienza a fallar la batería y aparece en la ventana del teléfono:

“Battery to low to flash”

Los teléfonos Motorola, si no tienen sistema operativo, no cargan las baterías así estén conectadas a una fuente de poder; para algunos esto es un “hard-brick” a menos que cuenten con alguna batería Motorola cargada adicional (que no es mi caso).

Qué hacer?, ya lo verán …

Cable USB-Activo

En este caso necesitas energizar de manera “independiente” la batería, mientras dejas el cable micro-USB solamente para comunicación, entonces.

  • Picas un cable viejo USB
  • Cortas y pelas los cables Rojo y Negro, dejando de lado el blanco y el verde, como se ve en la foto

2012-03-05_19-45-00_368

  • Pegas el cable ROJO en el símbolo (+) de la batería
  • Pegas el cable NEGRO en el símbolo (-) de la batería
  • Los sostienes con una mínima cantidad de cinta adhesiva
  • Conectas el cable USB a una fuente de poder (Cargador USB de 5V al menos 300mA) o en su defecto, a un puerto libre de la PC
  • Conectas el cable micro-USB

Y listo! … el teléfono encenderá y el cable permitirá energizar la batería mientras por el micro-USB accedemos al “extraño Fastboot Motorola”

Reparando el Fastboot

Aunque diga Fastboot, el equipo no es detectado por fastboot, pero si es detectado aún por las herramientas RSD (RSD Protocol), tal como “sbf_flash” para Linux.

Entonces, he descargado sbf_flash tal como expliqué en artículo anterior, y he ejecutado el flash de la ROM de stock (tranquilos, no la vamos a usar):

./sbf_flash 1FF-olympus-user-2.3.4-4.5.91-110625-release-keys-signed-ATT-US-GAS_NA_OLPSGBATTSPE_P011.sbf

Posteriormente, para recuperar “el verdadero” fastboot, cargamos el sbf_fix como indiqué en artículo anterior:

./sbf_flash 4547-fix-try2.sbf

En este momento, ya podemos acceder al fastboot.

Recuperando el Recovery

Ya con el sbf aplicado, podemos apagar el equipo (simplemente quitando cable USB y batería) y entrar en modo Fastboot de la siguiente manera:

  • Sacar la batería (recordemos que aún está energizada por el cable USB-activo)
  • Presionar “Volume DOWN”
  • Encender el equipo (o conectar el cable micro-USB)
  • El teléfono dirá “Failed to boot 1 Fastboot”
  • Presionar “Volume UP”
  • El dispositivo indicará “Starting Fastboot protocol support”

Ya podemos acceder desde ADB Fastboot.

Borramos el recovery (o lo que quedaba de él)

fastboot erase recovery

Aplicamos el recovery (el que me funciona para Atrix es el que indiqué en mi viejo post)

fastboot flash recovery recovery-dark-green-atrix5.img

Ahora podemos entrar al recovery

Aplicando la nueva radio y preparando para ROM nueva

Para acceder la Recovery:

  • Sacar la batería (recordemos que aún está energizada por el cable USB-activo)
  • Presionar “Volume DOWN”
  • Encender el equipo (o conectar el cable micro-USB)
  • El teléfono dirá “Failed to boot 1 Fastboot”
  • Presionar “Volume DOWN” varias veces hasta que donde decía “fastboot” diga “Android Recovery”
  • Presionar “Volume UP”
  • El dispositivo indicará “Starting Android Recovery”

Aprovechando que recuperé el equipo, he decidido aplicarle una nueva radio, diferente a la de stock, dicen que “se calienta menos” con una ROM Jelly Bean, además es la radio de la versión 145 que tantos dolores de cabeza le dió a varios.

Dicha radio la descargué de acá:

http://forum.xda-developers.com/showthread.php?t=2101841&page=46

Luego de ello, aplicarla es simplemente usar la opción “install zip from sd card” del Recovery.

Luego:

  • Wipe cache Partition
  • Advanced – Wipe Dalvik Cache
  • Mounts and Storage – Format /system
  • Mounts and Storage – Format /osh

Prepara el sistema para recibir una nueva ROM.

… Y listo para una nueva ROM

Como lo indican en xda-developers “Mientras el teléfono encienda, jamás será un hard-brick”, cada fabricante tiene métodos diferentes que hay que conocer para lograr “revivir de entre los muertos” a sus equipos, en el caso de Motorola, el protocolo RSD.

En mi caso, luego de probar la “SuperLite”, AtrICS y Atrix-MROM (ICS), me he decantado por la Epinter-10.1 con Kernel 3.1 a ver que tal me va.

UPDATE: Evitar el calentamiento de la batería

La ROM epinter es famosa por “poner caliente” la batería del teléfono, pero está documentado un proceso fácil para evitarlo:

entrar en modo ADB

adb shell

Ejecutar su – (pasar a root)

su -

Ejecutar el remontaje de /system como lectura-escritura:

mount -o remount rw /system

Borrar el siguiente archivo:

rm /system/app/FastDormancy.apk

Y reiniciar el equipo.

Y gracias a los experimentados de XDA-Developers por ayudarme a rescatar mi Atrix 4G de la muerte! …

[iptables] Descargando listas negras con Shorewall

Una de las características más importantes que debe realizar un firewall hoy día es reaccionar ante atacantes y/o conjuntos de atacantes, uno de ellos son los firewalls que protegen servidores de correo.

Las RBL (Realtime Blackhole List) son listas negras en tiempo real, generadas por muchísimas empresas e instituciones (spamhaus, por ejemplo) y que nos permiten obtener un listado bastante grande de IPs y subnets que son vigiladas por SPAM.

Hoy voy a probar hacer 2 listas negras, una desde Spamhaus y otra, de las subredes chinas más comunes utilizadas por los hackers.

Preparando a Shorewall para listas negras

Shorewall posee un archivo llamado /etc/shorewall/blacklist, de no poseer ese archivo, no hay problema, ya que crearemos un script que lo generará.

Pero primero, debemos indicar que la disposición de las IPs y subredes dentro del archivo BLACKLIST sea DROP.

Para ello ejecutamos:

sed -i "s/^BLACKLIST_DISPOSITION=.*$/BLACKLIST_DISPOSITION=DROP/" /etc/shorewall/shorewall.conf

Y refrescamos shorewall.

shorewall refresh

Script para descargar listas negras

Ahora debemos crear un script, que se ejecute mensualmente y que se dedique a “llenar” el archivo blacklist con listas dinámicas de varios sitios:

  • DShield Blacklist
  • Spamhaus DRBL
  • OKEAN Chinese and Korean Spammers
  • Wizcrafts (russian botnets)
  • RBN: Russian Bussiness Network
  • OpenBL

Con este conjunto de listas, creamos el script:

#!/bin/bash
cat <<EOF > /tmp/blacklist
#ADDRESS/SUBNET PROTOCOL PORT
# block all between ports 1 and 31
- tcp 1:31
# block unused ports
- udp 1024:1033,1434
- tcp 57,1433,1434,2401,2745,3127,3306,3410,4899,5554,6101,8081,9898
# block all from spamhaus, dshield and wizcrafts
EOF
echo "# dshield blocklist" >> /tmp/blacklist
wget -q -O - http://feeds.dshield.org/block.txt | awk 'NF && !/^[:space:]*#/' | sed '/Start/,+1 d' | awk '{ print $1 "/24"; }' >> /tmp/blacklist
echo "# spamhaus DRBL" >> /tmp/blacklist
wget -q -O - http://www.spamhaus.org/drop/drop.lasso | awk 'NF && !/^[:space:]*;/' | awk '{ print $1 }' >> /tmp/blacklist
echo "# chinese and korean spammers" >> /tmp/blacklist
wget -q -O - http://www.okean.com/sinokoreacidr.txt | awk 'NF && !/^[:space:]*#/' | awk '{ print $1 }' >> /tmp/blacklist
echo "# Wizcrafts Russian botnets, attackers and spammers" >> /tmp/blacklist
wget -q -O - http://www.wizcrafts.net/russian-iptables-blocklist.html | awk -F\> '/^pre>/{print $2}' RS=\< | awk 'NF && !/^[:space:]*#/' >> /tmp/blacklist
echo "# RBN Russian IPs" >> /tmp/blacklist
wget -q -O - http://doc.emergingthreats.net/pub/Main/RussianBusinessNetwork/RussianBusinessNetworkIPs.txt | awk 'NF && !/^[:space:]*#/' >> /tmp/blacklist
echo "# OpenBL.org 30 day List" >> /tmp/blacklist
wget -q -O - http://www.openbl.org/lists/base.txt | tr -d $'\r' | awk 'NF && !/^[:space:]*#/' >> /tmp/blacklist
echo "#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE" >> /tmp/blacklist
mv /tmp/blacklist /etc/shorewall/blacklist
shorewall refresh &>/dev/null

El script simplemente descarga todo en una lista temporal, que luego reemplaza el archivo blacklist y refresca la configuración del shorewall.

Luego, simplemente hacemos un enlace simbólico a /etc/cron.monthly

Para verificar, simplemente ejecutamos:

iptables -L -n --line

O en su defecto,

shorewall show blacklst

Que serían aproximadamente unas 28 mil IPs que quedarían permanentemente bloqueadas y que mensualmente se renovaría la lista.

Conclusiones

Atrás quedaron aquellas románticas (pero estúpidamente inútiles) épocas donde la gente escribía sus breves y concisos archivos de “reglas iptables” y los ponía en producción (aun queda *peligrosamente* gente así), en la actualidad es sumamente complicado mantener protegido un Firewall, con constantes botnets, malware, troyanos y un pare de contar de ataques y aprovechar estas listas, muchas actualizables incluso en tiempo real, nos ahorra mil dolores de cabeza y protege un poco más nuestros servidores.

¿imaginen qué pudieramos hacer si integraramos fwsnort al Firewall de nuestro equipo? …

 

[iptables]: Usar geoIP y Shorewall para bloquear paises

Y no, no es para hacer embargos! …

Preámbulo

Se estaba presentando el caso de un ataque de fuerza bruta contra un servidor públicamente visible, el ataque venía mayormente de China y Hong Kong y decidí, que sería interesante aprovechar las capacidades del módulo de xtables XT_GEOIP para ubicar una IP geográficamente con un porcentaje más o menos preciso.

Por ejemplo, GeoIPLookup (que hace uso de la base de datos de GeoIP), puede retornar la siguiente información:

geoiplookup 186.92.27.1
GeoIP Country Edition: VE, Venezuela

Lo cual resulta muy útil, ¿se podrá usar para bloquear tráfico desde países completos? …

Pre-requisitos

Los pre-requisitos son los siguientes:

  • Shorewall, versión 4.5 o superior
  • xtables-addons-common
  • libtext-csv-xs-perl (para procesar la base de datos de georeferencia).

Por ende, es simplemente instalar las dependencias y tener configurado Shorewall.

aptitude install xtables-addons-common libtext-csv-xs-perl

Creamos el directorio que requiere el módulo:

mkdir /usr/share/xt_geoip

Y montamos el módulo:

modprobe xt_geoip

Ahora, nos toca descargar la base de datos:

/usr/lib/xtables-addons/xt_geoip_dl

Veremos algo como:

root@proxy:/etc/shorewall# /usr/lib/xtables-addons/xt_geoip_dl
–2014-06-24 22:07:01– http://geolite.maxmind.com/download/geoip/database/GeoIPv6.csv.gz
Resolving geolite.maxmind.com (geolite.maxmind.com)… 108.168.255.243, 2607:f0d0:3:8::4
Connecting to geolite.maxmind.com (geolite.maxmind.com)|108.168.255.243|:80… connected.
HTTP request sent, awaiting response… 200 OK
Length: 823979 (805K) [application/octet-stream]
Saving to: ‘GeoIPv6.csv.gz’
100%[====================================================================>] 823,979 91.0KB/s in 9.3s
2014-06-24 22:07:11 (86.9 KB/s) – ‘GeoIPv6.csv.gz’ saved [823979/823979]

Y por último, convertimos este CSV en una forma binaria empaquetada que requiere el módulo xt_geoip:

/usr/lib/xtables-addons/xt_geoip_build -D /usr/share/xt_geoip *.csv
1 IPv6 ranges for VC Saint Vincent and the Grenadines
23 IPv4 ranges for VC Saint Vincent and the Grenadines
38 IPv6 ranges for VE Venezuela
230 IPv4 ranges for VE Venezuela
0 IPv6 ranges for VG Virgin Islands, British
48 IPv4 ranges for VG Virgin Islands, British
2 IPv6 ranges for VI Virgin Islands, U.S.
47 IPv4 ranges for VI Virgin Islands, U.S.
32 IPv6 ranges for VN Vietnam
257 IPv4 ranges for VN Vietnam
5 IPv6 ranges for VU Vanuatu
14 IPv4 ranges for VU Vanuatu

Y ya estamos listos para hacer uso de esta base de datos en Shorewall.

Configurando Shorewall

Desde Shorewall 4.5 existe soporte para GeoIP y su uso es extremadamente fácil, por ejemplo, podemos agregar al archivo /etc/shorewall/rules la siguiente regla:

DROP net:^[CN,TW,JP] fw - -

Y estaríamos bloqueando (DROP) desde mi zona “Internet” (net) a China (CN), Taiwan (TW) y Japón (JP), con destino a mi firewall (fw) de absolutamente todo tráfico UDP y TCP.  el formato del país es ISO-3661.

Podríamos por ejemplo, aceptar pero con información (LOG) todo tráfico WEB reportado como IP de Venezuela:

ACCEPT:info              net:^[VE]        fw          tcp          80,443

Podemos bloquear todo tráfico que sea explicitamente declarado como un proxy anónimo (según las reglas de GeoIP):

DROP        net:^[A1,A2]                  fw              -             -

Y listo!, verifiquen sus reglas y disfruten!.

Conclusiones

Los 2 comandos de arriba para descargar la base de datos de GeoIP podemos meterlos en un script, que se ejecute mensualmente, con esto, el sistema se actualizaría solo:

vim /etc/shorewall/scripts/updategeoip.sh

#!/bin/bash
# update geoip database (xt_geoip)
/usr/lib/xtables-addons/xt_geoip_dl > /dev/null 2>&1
/usr/lib/xtables-addons/xt_geoip_build -D /usr/share/xt_geoip *.csv > /dev/null 2>&1
# refresh configuration
shorewall refresh &>/dev/null

hacerlo ejecutable:

chmod 0770 /etc/shorewall/scripts/updategeoip.sh

Y colocar un enlace simbólico en cron.monthly:

ln -s /etc/shorewall/scripts/updategeoip.sh /etc/cron.monthly/updategeoip.sh

Y ya tendríamos un Firewall que bloquea (con una precisión del 74%) todo acceso desde el gigante asiático.

 

 

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 3.132 seguidores

A %d blogueros les gusta esto: