Archivo de la etiqueta: Web

Generando online imágenes de información de carga de Ajax

Hoy vamos con algo que personalmente me parece muy útil y que he utilizado en multitud de ocasiones.

¡Quién no ha necesitado en algún momento una imagen de esas típicas de información de actividad que aparecen en una aplicación  web cuando lanzas una acción AJAX!

5-0

La solución: ajaxload.info.

ajaxloadinfo

Desde ajaxload.info podemos generar nuestra imagen de “loading” de muchas formas diferentes personalizando los colores, directamente y online.

Hay gran cantidad de formas distintas que se pueden utilizar, desde las más típicas hasta otras mucho más originales, todas totalmente personalizables según tus necesidades.

combo

Una vez has definido cómo quieres tu imagen puedes visualzar el resultado hasta que te satisfaga completamente y descargarla. Este sería el resultado.8-1

Otra aplicación similar es Preloaders.net, aunque yo prefiero la anterior.

Cajas con esquinas redondeadas con CSS y sin tablas

Uno de los problemas más importantes a los que se ha tenido que enfrentar un maquetador web en los últimos años ha sido el de crear cajas con bordes redondeados sólo con CSS, sin utilizar tablas. Puede parecer algo muy simple, pero sabemos que no lo es. Con tablas era extremadamente sencillo, pero con CSS se complica bastante hacer algo así:

redondo.jpg

La verdad es que hay muchísima literatura al respecto, pero la cosa sigue siendo bastante complicada. Aquí tienen un tutorial muy descriptivo, la idea queda clara, pero la práctica…

Al final dí con un sitio que es perfecto para estos momentos, de hecho lo he utilizado bastante los últimos años: roundedcornr.com.

roundedcornr.com

Desde roundedcornr.com puedes generar directamente el código html, css y las imágenes necesarias para tus cajas. Tienen hasta tres tipos completamente configurables, normales, con borde y con degradado, increíblemente completo todo, sólo tienes que indicar grosores en píxeles y colores y te lo genera todo. ¿El resto? copiar y pegar.

Buscar en tu web desde el buscador integrado de los navegadores

Hoy veremos cómo añadir una nueva opción a los motores de búsqueda integrados de los navegadores, los que aparecen habitualmente arriba a la derecha. La utilidad puede ser dudosa y discutible teniendo en cuenta que la mayoría de usuarios “normales” ni utiliza la caja de buscar de su navegador ni sabe cambiar de motor de búsqueda, pero la opción está ahí. Obviamente el objetivo no es añadirlo nosotros únicamente sino proveer el mecanismo para que nuestros visitantes puedan automáticamente buscar en nuestro site y añadir la opción permanentemente. Si despliegas los motores disponibles al visitar este artículo verás que te sale una nueva opción. Si añades el motor tendrás este resultado.

buscar_firefox.gif

Ahora que sabemos qué es lo que queremos hacer, veamos cómo hacerlo. Los dos navegadores mayoritarios, Internet Explorer y Firefox, basan su caja de búsqueda en el proyecto OpenSearch con lo que el mismo método nos sirve para los dos.

Lo primeroque tendremos que hacer será crear un archivo XML con los datos de nuestro site y guardarlo en nuestro servidor. Yo lo he guardado en el directorio raíz, /opensearch.xml.

<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
    <ShortName>Buscar en Cerebro en la Sombra</ShortName>
    <Description>Búsqueda de artículos en el blog Cerebro en la Sombra</Description>
    <Tags>php flex linux viajes</Tags>
    <Image height="16" width="16" type="image/gif">http://blog.osusnet.com/favicon.ico</Image>
    <Url type="text/html" method="GET" template="http://blog.osusnet.com/?s={searchTerms}" />
    <InputEncoding>UTF-8</InputEncoding>
    <AdultContent>false</AdultContent>
    <Language>es-es</Language>
</OpenSearchDescription>

Todos los parámetros son claramente explicativos y no creo que sean necesarias más aclaraciones excepto con <Url>. En este parámetro debemos añadir la URL que nuestra web utiliza para buscar. Por ejemplo. WordPress utiliza algo como

http://tudominio.com/?s=loquebuscas

En Google sería algo así

http://www.google.es/search?q=casa

Cómo se puede ver, el formato es similar, una URL con un parámetro y las palabras clave sobre las que se busca. Éso es exactamente lo que debemos poner en el parámetro <Url> sustituyendo las palabras clave del ejemplo por {searchTerms}, que será reemplazado en el momento de buscar por las palabras que el usuario haya introducido en la caja de búsqueda.

Si todo ha ido bien ya tienes la parte más complicada terminada. Ahora habrá que indicarle a nuestra web que ése es nuestro motor de búsqueda OpenSearch. Esto lo haremos añadiendo un nuevo tag html en la cabecera de nuestra web.

<head>
...
<link rel="search" href="http://blog.osusnet.com/opensearch.xml" type="application/opensearchdescription+xml" title="Buscar en Cerebro en la Sombra"/>
...
</head>

Siendo href la URL al archivo XML que creamos antes. Ya está todo hecho. Si ahora visitas tu web con Firefox y despliegas la lista de buscadores verás algo como esto.

buscar_add_firefox.gif

De manera que automáticamente puedes añadir tu motor de búsqueda a la lista de motores disponibles.

Si visitas tu web con Explorer verás esto otro.

buscar_explorer.gif

Explorer da, además,  la opción de usar el buscador directamente sin añadirlo a la lista.

Como véis es un proceso muy sencillo el de automatizar la agregación de proveedores a los buscadores integrados de los navegadores. Como decía al principio, lo dudoso es su utilidad real ya que ¿cuantos usuarios lo saben utilizar? 😉 .

Otras utilidades para un servidor de correo

A veces un servidor de correo puede sernos de muchísima utilidad si sabemos cómo manejarlo correctamente. En el artículo de hoy veremos como utilizar nuestro MTA para ejecutar automáticamente acciones cuando se recibe un determinado email o con los parámetros que definamos. Una vez conozcamos la teoría plantearemos dos casos prácticos como ejemplo.

Para comenzar necesitaremos un servidor Linux con Qmail como MTA. Supongo que cualquier otro servidor de correo servirá (Sendmail, Postfix), yo lo personalizo en Qmail porque es el que conozco y utilizo, pero estoy seguro de que con los demás se puede hacer lo mismo.

La teoría

Para entender cómo funciona la idea debemos entender primero cómo Qmail realiza la entrega de mensajes en los buzones locales. Es un tema sobre el que hay bastante literatura buscando en Google pero que puede no quedar muy claro en una lectura rápida. Es el famoso lío de los archivos .qmail.

Cada vez que se crea un usuario del sistema se debe crear, si va a recibir emails, un archivo .qmail-default en su directorio de usuario.

[jiglesias@lerez ~]# cat /home/jiglesias/.qmail-default
./Maildir/

Normalmente este archivo se crea automáticamente ya que al instalar qmail se habrá creado una copia de este archivo en el esqueleto de creación de usuarios /etc/skel:

[jiglesias@lerez ~]# ls -la /etc/skel
total 56
drwxr-xr-x  4 root root  4096 Jul 29 18:29 .
drwxr-xr-x 97 root root 12288 Dec 30 04:08 ..
-rw-r--r--  1 root root    33 Feb  1  2008 .bash_logout
-rw-r--r--  1 root root   176 Feb  1  2008 .bash_profile
-rw-r--r--  1 root root   124 Feb  1  2008 .bashrc
drwx------  5 root root  4096 Aug 29  2007 Maildir
-rw-r--r--  1 root root    12 Jan  2  2008 .qmail-default
-rw-r--r--  1 root root   658 Sep 12  2006 .zshrc

Para el que no lo sepa, el esqueleto son los archivos que se copiarán al directorio de usuario (con los permisos de éste) cada vez que se crea uno nuevo. Si quieres que todos tus usuarios tengan algún archivo automáticamente, éste es tu sitio. En nuestro caso vemos que además del .qmail-default está el directorio Maildir, el de entrega por defecto del correo en qmail. Teniendo un usuario este archivo y este directorio, podrá recibir correo.

Vale vale, vas muy deprisa. Todavía no has explicado para que sirve el .qmail-default ese.  Cierto. Los archivos .qmail indican las reglas de entrega de los mensajes en base a dos parámetros:

  • El nombre del archivo .qmail-xx hace referencia a la cuenta de correo sobre la que actúa.
  • El contenido indica qué hacer con el correo.

Supongamos un usuario (jiglesias)  que recibe el correo de dos cuentas distintas (jiglesias@… y osus@…).

Por defecto todo su correo irá a su buzón ya que es lo que indica el archivo .qmail-default. Queremos ahora que el comportamiento sea distinto dependiendo de la cuenta a la que vaya dirigido, creamos entonces los archivos .qmail para las direcciones:

  • .qmail-jiglesias : controla el correo que vaya a jiglesias@…
  • .qmail-osus : controla el correo que vaya a osus@…

Podemos incluso ir un poco más lejos con un archivo .qmail-jiglesias-default, y controlaríamos el correo que vaya a cualquier dirección del tipo jiglesias-XXXX@…, es decir, cualquier dirección que comience por jiglesias- será controlada por este archivo .qmail.

En el caso básico, que es el que veíamos, la entrega se realiza al buzón de correo del usuario (el directorio Maildir) pero podríamos hacer otras cosas en función del contenido del archivo .qmail encargado de procesar la entrega del correo:

Reenvío a otra cuenta:

[jiglesias@lerez ~]# cat /home/jiglesias/.qmail-jiglesias
[email protected]

Reenvío a un programa/script:

[jiglesias@lerez ~]# cat /home/jiglesias/.qmail-osus
|preline /usr/bin/programa

Combinación de los anteriores

[jiglesias@lerez ~]# cat /home/jiglesias/.qmail-jiglesias
./Maildir/
[email protected]
|preline /usr/bin/programa

El caso que nos interesa es el segundo, es decir, pasar la entrega del email a un script que se encargará de analizar el email y tomar decisiones.

Te habrá llamado la atención el |preline del archivo .qmail. Es el sistema que prepara un email para ser procesado y entregado a otro script añadiendo algunas cabeceras. La salida del script que reciba el email es importante ya que de ella depende el resultado de la entrega final de email, en concreto es importante saber que si queremos rechazar un email habrá que terminar el script con un exit (100), esto indicará a qmail que debe rechazar ese mensaje. Veremos más adelante la utilidad de esta salida.

La práctica

Una vez sabemos cómo pasar el control de un email recibido a un script, veamos como tratarlo. Lo haremos con un script PHP. En nuestro archivo .qmail haremos algo como:

[jiglesias@lerez ~]# more .qmail-jiglesias
|preline /usr/bin/php /home/jiglesias/prueba.php

Con esto hemos terminado el trabajo en el servidor de correo. Veamos ahora como parsear el email desde PHP.

Lo primero que debemos hacer es recoger el contenido del email desde el script a través de la entrada estándar,  después ya podemos procesar el email como una cadena de texto.

<?php
$email=file("php://stdin");
$email=implode("", $email);
?>

Con estas sencillas dos líneas de código tendremos en nuestro script el contenido del email. Ahora sólamente debemos procesarlo. Podemos hacerlo línea por línea por nuestra cuenta o apoyarnos en alguna librería. Yo utilizo Mail_mimeDecode de Pear. La ventaja de esta librería es que podemos obtener, además del texto del email, los archivos adjuntos.

<?php
$email=file("php://stdin");
$email=implode("", $email);
$params['include_bodies'] = true;
$params['decode_bodies'] = true;
$params['decode_headers'] = true;
$params['input'] = $email;
$structure = Mail_mimeDecode::decode($params);
$subject = trim($structure->headers['subject']);
$ddate = trim($structure->headers['date']);
$from = addslashes(trim($structure->headers['from']));
if(ereg("<(.*)>", $from, $p)) $from=$p[1];
if(ereg(""(.*)"", trim($structure->headers['from']), $pp))
    $nombre=$pp[1];
?>

Así podemos ya procesar el email y tomar las decisiones que consideremos oportunas. Podremos insertarlo en una base de datos, lanzar otros procesos automatizados, enviar avisos por SMS… lo que se nos ocurra.

Casos prácticos

La pregunta clave, después de ver la teoría, sería ¿para qué me sirve esto?.  Os propongo dos aplicaciones que yo he hecho.

Sistema de soporte

El típico sistema de tickets de soporte. En el asunto del email se arrastra el identificador del ticket, por ejemplo [#123445]. Tendremos que analizar el asunto y comprobar si aparece el patrón predefinido. Si no existe estamos ante un nuevo ticket e insertamos los datos en nuestra base de datos, en caso contrario es una respuesta a una incidencia anterior y ahí tendremos el identificador. Sencillo ¿no?. Podemos incluso adjuntar a nuestras indicendias archivos que puedan llegar en el email.

Envío de archivos desde el movil

El segundo ejemplo sería semejante al anterior técnicamente pero distinto conceptualmente. La mayoría de los móviles (salvo los de gama alta) no pueden enviar archivos desde los formularios wap (<input type=”file”>). La alternativa es que el usuario envie un email o un MMS (la mayoría de operadoras permiten el envío a direcciones de email) con sus archivos. Nuestro script procesará el contenido del mail recibido, decodificará los archivos y los tratará como sea oportuno.

Son dos sencillos ejemplos de cómo utilizar el email para automatizar tareas, pero, como he comentado, podríamos hacer todo lo que se nos ocurra, desde enviar un SMS de aviso hasta incluso reiniciar nuestro servidor o lanzar cualquier otra tarea.

Conversión de vídeos a 3gpp bajo demanda en un entorno web

Hoy veremos como aplicar conversiones de vídeo en un entorno web donde los usuarios suben sus vídeos en cualquier formato. Sí, tienes razón, ni más ni menos que lo que hace YouTube, de hecho utilizaban un sistema muy similar a lo que veremos ahora y basado en el mismo software. En realidad el artículo se podría aplicar a prácticamente cualquier tipo de conversiones, incluso para iPod o PSP, sólo hay que utilizar los parámetros adecuados. Nosotros nos centraremos en la conversión a 3gp para después poder hacer streaming con ellos además de permitir su descarga.

Nuestro entorno se basará en un servidor con Linux (Centos5 en mi caso). Como software sólamente necesitaremos ffmpeg, herramienta imprescindible para cualquier aplicación (tanto web como de escritorio) bajo Linux.

¿Qué es ffmpeg?

Hace unas semanas veíamos cómo utilizar ffserver para convertir flujos de vídeo y hacer streaming. ffmpeg es la utilidad en la que se apoya ffserver para realizar las conversiones.

ffmpeg es una herramienta de software libre que permite realizar conversión entre la mayoría de formatos de vídeo más utilizados. Una inmensa mayoría de programas de conversión bajo Windows no son más que frontends gráficos para ffmpeg.

Normalmente los paquetes precompilados de ffmpeg no vienen con las extensiones adecuadas para las conversiones que necesitamos, así que deberemos compilar nuestra propia versión.

Necesitas instalar los siguientes paquetes, son más de los imprescindibles, pero así nos ahorraremos problemas futuros:

libmp4v2
libvorbis
libvorbis-devel
lame
lame-devel
faac
faac-devel
faad2
x264
x264-devel
xvidcore
xvidcore-devel

Debo decir que para mi Centos no están todos disponibles como rpm con lo cual habrá que compilar manualmente algunos de ellos. No deberías tener ningún problema para localizar cada librería.

Finalmente habrá instalar los siguientes paquetes:

http://ftp.penguin.cz/pub/users/utx/amr/amrnb-7.0.0.2.tar.bz2

http://ftp.penguin.cz/pub/users/utx/amr/amrwb-7.0.0.3.tar.bz2

Con esto tenemos ya todo preparado para compilar nuestro propio ffmpeg. Descarga el paquete desde la web oficial, descomprímelo y:

./configure --enable-libmp3lame --enable-libvorbis --enable-libogg --enable-libamr-nb --enable-libamr-wb --enable-libfaac --enable-gpl --enable-libxvid --enable-libx264 --enable-libfaad --enable-shared
make
make install

Si has seguido bien todos los pasos tendrás el software de conversión preparado.

Convirtiendo a 3gp

Para realizar las conversiones algo tan sencillo como:

ffmpeg -y  -i original.avi -s qcif -r 12 -b 30 -ac 1 -ar 8000 -ab 12200 video.3gp
/usr/local/bin/MP4Box -3gp -mtu 1450 -hint video.3gp

Cuando vimos cómo hacer streaming a móviles veíamos como utilizar la utilidad MP4Box para que nuestros vídeos 3gp se puediesen utilizar para emitir en vivo.

Para nuestro proyecto es probable que necesitemos algo más. Si queremos que también se puedan visualizar los vídeos desde una web necesitaremos convertirlos a flv:

ffmpeg -y -i original.avi -acodec libmp3lame -ac 2 -ar 22050 -r 12 -b 196 -s 176x144 video.flv
/usr/bin/flvtool2 u video.flv

Flvtool es una herramienta que inserta en los flv los metadata necesarios para que funcione bien en el reproductor flash.

Y necesitaremos capturar algún fotograma del vídeo para mostrar como demo:

ffmpeg -i original.avi -y -ss 00:00:01 -vframes 1 -an -sameq -s 160x120 -f image2 thumbnail.jpg

Ahora ya sabemos:

  • cómo crear nuestro vídeo 3gp que nos sirva tanto para descarga como para streaming.
  • cómo crear el vídeo flv que nos sirva para ver vía web.
  • cómo generar thumbnails de escenas del vídeo.

Creando el entorno web

Supongamos que queremos desarrollar una web al estilo Youtube donde el usuario sube vídeos desde un formulario y posteriormente se desea mostrarlos categorizados, con un buscador, una preview (flv), descarga para móviles, etc.

La parte de la web propiamente dicha resulta obvia, no vamos a entrar en detalles. Lo que nos ocupa aquí es como realizar la conversión según las instrucciones que hemos visto. Obviamente no podemos ejecutar la conversión cada vez que un usuario sube un vídeo, sería un proceso lento y pesado. La mejor manera es crear una cola de conversión. Cuando se sube un nuevo vídeo no esta disponible públicamente (no se ha convertido todavía). Podríamos definir tres estados diferentes para un video:

  1. Sin procesar (convertir).
  2. Procesando.
  3. Procesado.

Según esto sería sencillo tener en una tabla el estado de los vídeos. Sólo los procesados se listarían públicamente.

Por otro lado tendríamos una tarea encargada de buscar vídeos en estado “sin procesar” y realizar su conversión. Esta tarea podría ser o bien un demonio residente que está permanentemente buscando vídeos o bien, si el tráfico de nuevos vídeos no va a ser elevado, podría ejecutarse periódicamente para realizar las conversiones.

Si el tráfico fuese muy elevado podría incluso haber varias tareas en paralelo ya que una vez una de ellas encuentra un vídeo “no procesado” actualiza su estado a “procesando” de manera que la siguiente tarea ya no escogerá ese mismo vídeo.

La teoría es mucho más sencilla de lo que parece. La tarea que realiza la conversión creará los formatos que estimemos oportunos según ya hemos visto antes.

Convirtiendo a otros formatos

Con ffmpeg se pueden generar los vídeos para casi cualquier formato existente incluyendo PSP, iPod/iPhone/iTouch… Googleando un poco encontrarás los parámetros adecuados para cada formato.

Conclusiones

En este artículo he explicado cómo realizar conversiones de vídeos a distintos formatos y cómo aplicarlo a un entorno web dónde los usuarios suben sus propios vídeos. He dado los pasos básicos para entender el sistema, vosotros tendríais que adaptarlo a vuestras necesidades.

Depurando condiciones Rewrite en Apache

Últimamente he tenido que utilizar bastante ModRewrite de Apache en distintos proyectos, algunos de migración y otros de Internet Móvil donde se necesitan ciertas URL’s para que las operadoras lancen sus sitemas de billing.

Con ModRewrite es muy fácil convertir URLs antiguas al formato nuevo en caso de migración (de manera que no pierdes el SEO que tengas). En el caso del billing de las operadoras móviles es todavía más sencillo puesto que simplemente lo usamos para simular una URL premium. Por ejemplo:

http://tudominio.com/premium.php?noticia=3

Se convierte en:

http://tudominio.com/index.php?noticia=3

De este modo no es necesario hacer scripts independientes y separados por operadora sino que todo queda integrado en nuestro framework.

El problema es que es bastante tedioso depurar lo que hace ModRewrite para ver si las condiciones que has escrito son correctas o si algún filtro no se está ejecutando correctamente. Para solucionarlo lo mejor que podemos hacer es decirle a Apache que “logee” todas las decisiones que va tomando sobre nuestros filtros. Tan fácil como esto:

RewriteEngine on
RewriteLog "/logs/rewrite.log"
RewriteLogLevel 4

RewriteCond %{REQUEST_URI} ^/premium.php$
RewriteRule ^/premium.php /index.php

Este sencillo ejemplo nos permite comprobar qué veremos en el log:

213.xxx.xxx.xxx - - [15/Nov/2008:00:48:23 +0000] [tudominio.com/sid#127d7b0][rid#16b8c20/initial] (3) applying pattern '^/premium.php' to uri '/premium.php'
213.xxx.xxx.xxx - - [15/Nov/2008:00:48:23 +0000] [tudominio.com/sid#127d7b0][rid#16b8c20/initial] (4) RewriteCond: input='/premium.php' pattern='^/premium.php$' => matched
213.xxx.xxx.xxx - - [15/Nov/2008:00:48:23 +0000] [tudominio.com/sid#127d7b0][rid#16b8c20/initial] (2) rewrite /premium.php -> /index.php
213.xxx.xxx.xxx - - [15/Nov/2008:00:48:23 +0000] [tudominio.com/sid#127d7b0][rid#16b8c20/initial] (2) local path result: /index.php
213.xxx.xxx.xxx - - [15/Nov/2008:00:48:23 +0000] [tudominio.com/sid#127d7b0][rid#16b8c20/initial] (2) prefixed with document_root to /var/www/tudominio.com/index.php
213.xxx.xxx.xxx - - [15/Nov/2008:00:48:23 +0000] [tudominio.com/sid#127d7b0][rid#16b8c20/initial] (1) go-ahead with /var/www/tudominio.com/index.php [OK]

Por cada URL que se solicita al servidor, Apache va comprobando las posibles condiciones que has escrito por si coincide con el patrón (matched) o no (not matched). Si la URL cumple los requisitos, la reescribe según se indica en la regla, en caso contrario la deja pasar tal cual. Con toda esta información podemos hacer un completo seguimiento de las reglas que queremos aplicar para comprobar si hay algún error o por qué determinada URL no hace lo que esperamos que haga.

El nivel del log indica la cantidad de información que se guardará, de 0 a 9. A  mayor valor, más información.

Algo muy sencillo pero que pasa desapercibido para la mayoría y acabamos perdiendo muchísimo tiempo probando reglas sin saber qué está ocurriendo en el interior de nuestro servidor web.

Usando certificados SSL de cliente como sistema de autenticación web

A menudo creamos aplicaciones web con un backend de gestión que, por ser también web, exponemos públicamente a cualquiera que consiga averiguar la URL. Habitualmente estos sistemas son de acceso restringido, sólo un pequeño grupo de usuarios lo utiliza.

En escenarios donde tenemos un número de usuarios acotado y se necesita autentificación, se puede utilizar un mecanismo de certificados que aporten mayor seguridad al sistema, de esta manera solo aquellos usuarios que tengan el certificado en cuestión tendrán acceso a la máquina.

Hoy veremos como permitir el acceso a nuestra aplicación a aquellos usuarios que dispongan de un certificado que previamente les habremos enviado mientras que si no lo tienen no podrán acceder de ningún modo. Este método se puede combinar, además, con el tradicional usuario/clave para dar mayor seguridad. Podremos incluso verificar que el nombre de usuario que se intenta utilizar se corresponde con el certificado de usuario que le hemos enviado y no intenta autentificarse con otro.

Conceptos básicos sobre certificados SSL

El método que vamos a ver se basa en certificados SSL. Se utilizan para asegurar la información entre un cliente y el servidor y prevenir escuchas ya que la información viaja encriptada. Ésta es su función y la hace aunque no esté firmado por una autoridad certificadora (CA) oficial o, incluso, aunque esté caducado. Sigue asegurando las comunicaciones.

Los navegadores web reconocen, por defecto, una serie de autoridades certificadoras como Verisign o Thawte, aunque hay muchas más. Puedes verlas todas en las opciones de tu navegador. Pero, ¿qué es realmente lo que hace una Autoridad Certificadora? Firmar. Firma tu certificado SSL asegurando que os pertenece a ti y a tu dominio. Cuando un cliente accede a tu dominio y descarga el certificado SSL, busca dentro de sus certificados de CA‘s si hay alguno que lo haya firmado. Si lo encuentra, acepta tu certificado y no ocurre nada especial, pero si no encuentra la CA lanza un aviso indicando que no se reconoce la autoridad que lo firma. Esto no quiere decir que el certificado no sea válido, lo único que ocurre es que no sabe quien lo firma. Esto significa, por tanto, que tú mismo puedes ser tu propia autoridad certificadora y firmar tus certificados, funcionarán perfectamente y cumplirán su cometido de asegurar las comunicaciones cliente/servidor.

Comercialmente o en sistemas de acceso público en general, no se recomiendan certificados autofirmados ya que el aviso de autoridad de certificación no reconocida generará desconfianza entre tus usuarios, pero en entorno intranet o de paneles de adminsitración es un método ideal.

El servidor puede requerir, además, otro certificado al cliente, de manera que ámbos extremos autentifiquen la comunicación. Esto es precisamente lo que vamos a hacer hoy en este artículo.

Según lo que hemos explicado, los certificados autofirmados son igual de seguros que los firmados por una autoridad certificadora. Como en el ejemplo que estamos viendo estamos asegurando el acceso a nuestra aplicación para un grupo reducido de usuarios, no hay ningún problema en utilizar un certificado firmado por nosotros mismos ya que nuestros usuarios sabrán que no hay ningún problema. Pero esto no es todo, por esta misma razón podemos decir a los usuarios que se instalen el certificado público de nuestra CA, tal y como hacen las CA oficiales, y automáticamente el navegador comenzará a confiar en nuestros certificados ya que, ahora sí, tiene un certificado de una CA que firma los certificados SSL.

Como resumen, nuestro trabjo consistirá en:

  • Crear nuestra autoridad certificadora y su certificado.
  • Crear el certificado SSL para nuestro servidor web firmado por nuestra CA.
  • Crear los certificados de cliente para nuestros usuarios.
  • Habilitar la lectura de los datos SSL desde PHP.

Servidor web SSL

Utilizaremos el paquete Openssl para generar los certificados. Si aún no lo tienes instalado en tu servidor, es el momento. Explicaré de manera rápida como crear crear certificados SSL para asegurar las comunicaciones ya que es el primer paso necesario para añadir certificados de cliente, sin embargo no es el objeto principal de este artículo y hay mucha documentación, googlea un poco 😉 .

Primero creamos el certificado y la clave privada de nuestra autoridad de certificación:

openssl req -x509 -newkey rsa:2048 -days 3650 -keyout CAXplotaKey.pem -out CAXplotacert.pem

Lo más importante de este comando es el parámetro days, ya que no queremos que dentro de un año nos caduque el certificado de nuestra propia entidad. Yo le pongo 10 años. Este comando genera dos archivos, la clave privada con la que firmaremos nuestros futuros certificados y el certificado con la clave pública que instalaremos, si queremos no recibir avisos, en el navegador. Este comando te pedirá algunos datos (nombre de empresa, país…) y, sobre todo, una contraseña. Deberás recordarla cada vez que vayas a firmar un certificado SSL, así que no la olvides. Ya tenemos nuestra CA creada.

Creamos ahora el certificado SSL para nuestro dominio:

openssl genrsa -des3 -out claveprivada.pem 2048
openssl req -new -key claveprivada.pem -out certificado.pem

El primer comando crea la clave privada de nuestro certificado. Te pedirá otra contraseña, esta vez para la clave privada. Recuérdala también.

El segundo comando genera la petición de certificado sobre la clave privada anterior. Te pedirá la contraseña de la clave privada anterior.

En este punto tenemos cuatro archivos, la clave y el certificado de tu CA y la clave y la solicitud de tu certificado SSL. Sólo queda firmar el certificado con nuestra CA y ya podremos utilizarlo.

Para poder firmarlo debemos generar primero un fichero de texto con algunos parámetros de configuración:

cat configservidor.cnf

basicConstraints = critical,CA:FALSE
extendedKeyUsage = serverAuth

Y firmamos el certificado.

openssl x509 -CA CAXplotacert.pem -CAkey CAXplotaKey.pem -req -extfile configservidor.cnf -in certificado.pem -days 3650 -CAcreateserial -sha1 -out certificado-servidor.pem

Ya tenemos un certificado SSL preparado para utilizar en nuestro servidor web. En nuestro caso es certificado-servidor.pem. Vamos a configurar Apache para que lo utilice.

Habrá que editar httpd.conf y añadir

LoadModule ssl_module modules/mod_ssl.so
Listen 443

Es probable que, si no has compilado tu propio Apache y has instalado un paquete precompilado, tengas ya algún ssl.conf. Activándolo tendrás este paso preparado. En mi caso, un CentOS5, sólo hay que incluir /etc/httpd/conf.d/ssl.conf.

Finalmente hay que indicar en el virtual host que quieres asegurar que use nuestro nuevo certificado. Para hacerlo añadimos un nuevo virtual que escuche en el puerto 443 y añadimos las siguientes líneas:

SSLEngine on
SSLCertificateFile /ruta/a/certificado-servidor.pem
SSLCertificateKeyFile /ruta/a/claveprivada.pem

Si ahora reinicias Apache y accedes a tu dominio con https verás que en tu navegador aparece el candado indicando que la información es segura. Verás también que te aparece un aviso de que no se confía en la autoridad certificadora. Veremos más adelante como solucionarlo.

Añadiendo certificados de cliente

Ahora que ya tenemos nuestro servidor web seguro con nuestros certificado autofirmado llega el momento de crear certificados para nuestros clientes de manera que si alguien intenta acceder a nuestra aplicación sin uno de ellos se le prohíba el paso.

Crearemos primero un archivo de configuración con los parámetros que necesitaremos.

cat configcliente.cnf

basicConstraints = critical,CA:FALSE
extendedKeyUsage = clientAuth

Con esto daremos instrucciones de que es un certificado cliente a la hora de firmar el certificado.

Creamos ahora, igual que hacíamos antes, la clave privada y la solicitud de certificado.

openssl genrsa -des3 -out clave-cliente.pem 2048
openssl req -new -key clave-cliente.pem  -out certificado-cliente-req.pem

Como antes, al generar la clave te pedirá una contraseña que deberás introducir después, al hacer la solicitud de certificado. Los datos que te pide esta solicitud, como ocurría antes, los podrás leer posteriormente para comprobar datos o lo que estimes oportuno, así que es importante que prestes atención.

Firmamos ahora el certificado con nuestra CA:

openssl x509 -CA CAXplotacert.pem -CAkey CAXplotaKey.pem -req -in certificado-cliente-req.pem -days 3650 -extfile configcliente.cnf  -CAcreateserial -sha1 -out certificado-cliente.pem

Como véis, el proceso es el mismo para generar el certificado de servidor, pero cambiamos el contenido del archivo de configuración que le indica que es un certificado cliente, no servidor.

Vale, bien, pero ¿no quedamos que es el cliente el que debe instalar el certificado? Sí, ahí vamos ahora. El certificado que acabamos de generar lo debes instalar en tu navegador web, no en el servidor, así que habrá que convertirlo a algún formato que puedan entender. Para esto hacemos lo siguiente:

openssl pkcs12 -export -in certificado-cliente.pem -inkey clave-cliente.pem -certfile CAXplotacert.pem -out cliente.p12

Nos pedirá la contraseña de la clave privada del certificado y nos solicitará otra para el que va a generar. Es importante poner contraseña al certificado final ya que es el que vas a enviar a tus usuarios y pretendes que sólo estos puedan utilizarlo, así que poner una contraseña nunca está demás.

Ya tienes tu certificado cliente.p12. Puedes probarlo tu mismo. Ah no, espera, que no hemos configurado el servidor web para que solicite sí o sí un certificado al cliente. Añade a la configuración SSL de tu virtual host de Apache:

SSLCACertificateFile /path/a/CAXplotacert.pem
SSLVerifyClient require

Y reinicia tu servidor web. Si ahora intentas acceder a tu dominio verás como salta una ventana solicitando un certificado que no tienes. Desde las opciones de tu navegador, busca la sección de certificados SSL y añade un nuevo certificado. Selecciona tu cliente.p12. Te pedirá la contraseña que pusiste al convertirlo a pk12. Ya está. Accede ahora y verás como te aparece el certificado en la ventana de certificiados disponibles y, si lo seleccionas, te deja acceder a tu aplicación.

Revocar certificados

A veces puede ser necesario prohibir el paso con determinados certificados, bien porque el usuario ya no colabora o trabaja contigo, bien porque hay posibilidades de que el certificado haya sido robado, etc. Una opción es, a la hora de crear el certificado, y si sabes de antemano que el usuario lo necesitará pocos días (cuenta de prueba, usuario esporádico o cualquier razón similar), generarlo con una validez limitada (10 días, un mes, etc.), de modo que pasado este tiempo el certificado caduca y el usuario no puede entrar. El problema más importante lo tendrás cuando necesites prohibir el acceso a usuarios con certificados a largo plazo. Para hacerlo debemos crear una lista de revocación de certificados.

En mi caso (CentOS5 y RHEL5) tuve algunos problemas de configuración. Openssl debería de mantener una lista de los certificados que emite y sus números de serie sin embargo tal como hemos generado nuestros certificados no lo hace. Para solucionarlo, creamos a mano la lista.

touch /etc/pki/CA/index.txt

Ahora debemos editar el archivo de configuración de Openssl para reflejar algunos parámetros. Por defecto indica una ruta relativa hacia los directorios donde dejará los certificados, pero no me funcionó bien hasta que no le puse rutas absolutas. Modificamos pues la ruta al directorio y le indicamos donde están la clave privada y el certificado de nuestra CA.

Editar /etc/pki/tls/openssl.cnf

dir             = /etc/pki/CA              # Where everything is kept
certificate     = /path/a/CAXplotacert.pem    # The CA certificate
private_key     = /path/a/CAXplotaKey.pem # The private key

Ahora sí, podemos revocar un certificado de manera tan sencilla como:

openssl ca -revoke certificado-cliente.pem

A partir de la lista con el estado de los certificados debemos crear una lista de revocación que usaremos para indicar al servidor web los certificados que no debe permitir.

openssl ca -gencrl -out recovados.crl

Es posible que al lanzar este comando te apareza otro error relacionado con crlnumber. Esto viene relacionado con lo que os indicaba antes y es simplemente que no existe el archivo de números de serie. Para solucionarlo, simplemente lo creamos:

echo "01" > /etc/pki/CA/crlnumber

Y volvemos a generar la lista de revocación. Cada vez que revoques un certificado deberás repetir esta operación para tener la nueva lista.

Ya sólo falta indicarle a Apache qué certificados no debe permitir. Añadimos a la configuración de nuestro virtual host, en el mismo sitio donde configuramos anteriormente el certificado SSL, la siguiente línea:

SSLCARevocationFile path/a/revocados.crl

Eso es todo, ya tenemos nuestro servido SSL funcionando, nuestra aplicación protegida con certificados de cliente y la opción para revocar certificados.

Comprobando los certificados con PHP

Queremos ir un poco más allá. Queremos que, desde nuestra aplicación, podamos leer el certificado SSL del cliente y comprobar quién es. Seguro que a ti se te ocurren mejores cosas que hacer con estos datos 😉 . Lo primero que tendremos que hacer será configurar Apache para que pase los datos del certificado. En la configuración de tu virtual host añades:

<Files ~ ".(cgi|shtml|phtml|php?)$">
 SSLOptions +StdEnvVars +ExportCertData
</Files>

Ya está. Si ahora haces un print_r($_SERVER) en la aplicación donde tienes instalado tu certificado SSL de cliente verás entre todos los datos algo como:

[SSL_CLIENT_S_DN] => /C=ES/ST=Valencia/L=Valencia/O=Osusnet/CN=blog.osusnet.com/emailAddress=osusENosusnet.com
[SSL_CLIENT_S_DN_C] => ES
[SSL_CLIENT_S_DN_ST] => Valencia
[SSL_CLIENT_S_DN_L] => Valencia
[SSL_CLIENT_S_DN_O] => Osusnet
[SSL_CLIENT_S_DN_CN] => blog.osusnet.com
[SSL_CLIENT_S_DN_Email] => osusENosusnet.com

Tienes toda la información que necesitas, son los datos que se solicitaban al crear la solicitud de certificado. Generando estos parámetros de manera adecuada podrás saber quién entra a tu aplicación a partir del certificado cliente que usa.

Eso es todo por hoy. De una manera muy sencilla hemos añadido un poco más de seguridad a una aplicación web de acceso privado y con un número de usuarios acotado. También hemos aprendido y poco más sobre certificados SSL y hemos visto cómo firmar nuestros propios certificados, igual de fiables que los comerciales. Espero que os sirva de algo 😛 .

Las operadoras móviles y el control de Internet

Hace algo más de un año saltaba la noticia: Vodafone UK había implantado un proxy-transcoder en su red de datos de manera que todas las conexiones de sus clientes pasaban por este sistema. Con la excusa de hacer accesibles a todos los terminales cualquier página web ya existente, modificaban completamente el aspecto de la misma, añadiendo publicidad, accesos directos a Vodafone Live! y lo que es peor, modificando las hojas de estilos de los portales, con lo que tu trabajo perdía su apariencia original.

El movimiento internacional dentro del sector fué considerable. Gente como Andrea Trasatti o Luca Passani, verdaderos gurús de la adaptación, se revelaron contra la medida. Mucha gente lo criticó.

El problema no era sólo la apariencia de los portales, eso es lo que se veía directamente, el problema serio era (es) que se estaban cargando uno de los conceptos básicos de la adaptación para móviles: el UserAgent. Aunque existe en todos los navegadores web, el UserAgent cobra especial importancia en un dispositivo móvil ya que lo identifica, te aporta información sobre marca y modelo del mismo con lo que, con una buena base de datos de terminales (por ejemplo wurlf), puedes obtener compatibilidades (vídeo, mp3, mms…) y tamaños de pantalla. Al eliminarse el UserAgent se eliminaba la posibilidad de ofrecer contenido compatible con ese terminal. Pensemos en los juegos Java para móvil donde es imprescindible saber qué modelo tiene el cliente puesto que hay que darle un archivo compilado para ese mismo.

Después de algunas protestas, desde Vodafone UK decidieron enviar el UserAgent del teléfono original pero en una cabecera HTTP distinta, con lo cual tendrías que modificar TODOS tus desarrollos por culpa de esta maravillosa idea.

Finalmente se sacaron de la manga dos soluciones al transcoder:

  • Si tu dominio es .mobi no modifican el contenido ya que asumen que YA es contenido optimizado para pequeños dispositivos.
  • Una whitelist donde, si enviabas tus dominios, dejaban de filtrarlos y adaptarlos.

En realidad no sé si el segundo método llegó a funcionar alguna vez. El primero sí.

En octubre del año pasado llegaba la debacle a España. Vodafone ES ponía el famoso transcoder y todos nuestros portales móviles perdían su look&feel además de verse modificados para incluir todos los enlaces directos de Live!. También tuvimos voces de alarma.

Aquí el problema fue peor, nunca llegaron a enviar el UserAgent original. No sé si ahora lo hacen, pero en su momento no lo hicieron. Esta medida de Vodafone hizo mucho daño al sector.

Hoy, casi un año después, he descubierto, por pura casualidad, que Movistar también tiene el famoso proxy-transcoder, aunque por el momento parece que no hacen un uso abusivo de él. No modifican nada visualmente ni esconden el UserAgent, pero adaptan algunas cosas. Os explico la situación que me tuvo loco durante dos días.

Preparando un portal para una importante promoción me encontré con que en un Nokia N95 las imágenes no se veían al tamaño adecuado. Nuestra plataforma adapta automáticamente el tamaño de las imágenes en función del ancho de pantalla del terminal del cliente (obtenido a partir del UserAgent).  Pues resulta que en el servidor estábamos generando las imágenes correctamente, a 240px de ancho, mientras que en el teléfono se estaban recibiendo a 95px de ancho. ¡Imposible!

Probamos con el mismo teléfono pero con tarjetas SIM de otras operadoras y voila, funcionaba a la perfección. Finalmente pruebo con otros terminales y descubro que, en efecto, están adaptando las imágenes, imagino que para reducir el tráfico de red y optimizar el ancho de banda. El problema del N95 es que, por alguna extraña razón, lo tienen mal configurado en su base de datos de terminales  y, en vez de ponerle el tamaño real de pantalla que tiene (240×320), le han puesto 95px de ancho, incluso a lo mejor es el tamaño por defecto que devuelve el transcoder si no existe ese terminal en la base de datos, razón todavía peor, el N95 es uno de los dispositivos más populares a pesar de su coste.

¿Qué hago ahora cuando  el cliente nos diga que el portal se ve mal en su N95? ¿Se creerá que la culpa es de Movistar?

Urchin vs. Analytics, la batalla se libra en casa

Webalizer (con su excelente fork continuado awffull) y awstats han tenido históricamente fama de contar visitas y páginas de más, sobre todo desde que Google abrió al público su Analytics y ya nada volvió a ser lo mismo. Hace años tuvimos alguno de nuestros proyectos auditado por OJD y la diferencia con webalizer era mínima, sin embargo las distancias con Analytics son abismales.

Analitycs surge de la compra de Urchin por parte de Google en 2005, otro clásico del software para estadísticas web. Analytics se lanzó primero en beta muy cerrada y bastante después la abrieron completamente al público. Desde el primer día todos nos hemos dado cuenta de las enormes diferencias de datos que había entre lo que contaban nuestros analizadores de logs y lo que contaba Analytics.

Recientemente necesitaba valorar las estadísticas de acceso a distintos proyectos móviles y la única herramienta de la que disponía era el querido webalizer, pero ¡cómo fiase de sus datos!. Analytics no es una opción en este entorno ya que la inmensa mayoría de terminales no soportan Javascript, con lo cual no va a funcionar la contabilización de páginas. Se me ocurrió entonces probar Urchin Software, la última versión del software comprado por Google y que ellos mismos distribuyen y en el que, se supone, se basa Analytics. Aunque el precio de la licencia sea posiblemente prohibitivo para la mayoría, tenemos una versión de prueba de 3 meses, así que dicho y hecho, la descargamos la instalamos y comenzamos a monitorizar nuestros sites móviles. La sorpresa fue mayúscula al cabo de un par de días cuando comprobamos que el resultado es prácticamente el mismo que con webalizer. No nos lo podíamos creer, así que decidimos monitorizar sites también controlados por Analytics para comparar, comenzando por el blog Restaurantes en Madrid. Al cabo de unos días volvimos para comparar el resultado y nos sorprendimos de nuevo. Resultados semejantes a webalizer y completamente distantes de Analytics. Pero ahora la diferencia era enorme, estamos hablando del doble con creces de visitas y páginas que nos muestra Urchin respecto a Analytics.

Urchin (o webalizer, o awstats) se basa en el análisis de logs de acceso del servidor web, mientras que Analytics lo hace a través de Javascript. No cabe duda alguna de que el primer método ha de ser, por fuerza, mucho más creíble y eficaz ya que se basa en peticiones HTTP recibidas de verdad, mientras que el segundo método confía en que el cliente tenga Javascript. Pero ¿qué ocurre con clientes sin Javascript?, más aún, ¿qué pasa con los accesos a feeds?, ¿son visitas no contabilizadas y perdidas? Pues sí. Osea, la herramienta de estadísticas web por excelencia está contabilizando, al menos, un 20% (según he leído en algún sitio) de tráfico menos de lo que en realidad tienes y aún así se ha convertido en el estandar, no lo puedo entender. ¿Los que te leen por RSS no son visitantes también? Se ve que no… La única razón que se argumenta en favor de Analytics es que así no cuenta tráfico proveniente de los robots de los buscadores, pero no dicen nada de los efectos colaterales.

Las críticas que se puedan aplicar a webalizer o a awstats son exactamente las mismas que puedes echar sobre Urchin, con la diferencia de que este último cuesta la nada desdeñable cifra de 3.000 euros. Sin embargo te habrás gastado este dineral para obtener unas cifras nada parecidas a Analytics. Cuando vayas a vender tus espacios publicitarios qué datos vas a enseñar, los de Urchin o los de Analytics, o mejor aún, cuales te van a pedir tus anunciantes?.