gentoo linux, java, software libre y otras hierbas
Sep, 06 2008 - 12:01 am

[Tutorial] Evitar hotlinking y sacarle provecho

Muchos sitios que copian nuestro contenido, bien sea de manera automática o manual, cargan además las imagenes que tenemos alojadas en nuestro servidor, lo cual nos roba el ancho de banda que estamos pagando. La idea de esta pequeña guía es enseñarte cómo evitar que te hagan hotlinking, e ir un poco más allá. El hotlinking es una práctica detestable, aunque reconozco que yo mismo lo hice en mis tiempos de ignorancia suprema

La técnica que utilizaremos consiste en editar el archivo .htaccess que tenemos en la raiz de nuestro servidor. Para los que no saben qué es .htaccess, me permito citar una definición:

es un archivo de configuración en un servidor Web, y contiene comandos en el lenguaje del servidor que le indican cómo debe comportarse en ciertas situaciones. Alguno de los usos más comunes de un archivo htaccess son la restricción del acceso a determinados archivos o carpetas en Internet (o en una intranet) mediante el uso de contraseñas. Adicionamente, los htaccess se usan para redirigir usuarios automáticamente, para bloquear o permitir el acceso al servidor a ciertas direcciones de IP, y para llamar páginas de error customizadas en lugar de las páginas de error 404 standard del servidor. Los servidores Web Apache, y otros servidores que cumplimentan las normas del NCSA pueden usar htaccess.

Además, es ampliamente utilizado por los bloggers, aún cuando no se den cuenta, puesto que es la manera en que Wordpress hace que las URL puedan ser del tipo http://ejemplo.com/url-muy-satanica, en vez de http://ejemplo.com/?p=666. De eso ya había creado un pequeño artículo, que no esta demás nombrar.

Entonces, la idea de este artículo es configurar nuestro servidor a través del .htacces para que realice algunas de las siguientes acciones:

No cargar imágenes alojadas en nuestro servidor en otras páginas

Vamos a tomar como ejemplo mi .htaccess, que de seguro será similar o igual al tuyo, si usas Wordpress. El archivo en cuestión es el siguiente:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /wordpress/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wordpress/index.php [L]
</IfModule>

Si deseamos que ninguna de nuestras imágenes puedan ser cargadas desde otro servidor, simplemente debemos añadir algunas líneas dejando el archivo en el siguiente estado:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /wordpress/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wordpress/index.php [L]

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://tuweb.com$ [NC]
RewriteCond %{HTTP_REFERER} !^http://tuweb.com/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.tuweb.com$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.tuweb.com/.*$ [NC]
RewriteRule .*\.(gif|jpg|jpeg|png|bmp)$ - [F,NC,L]
</IfModule>

Donde debes cambiar tuweb, por el nombre de dominio de tu site o blog. Pero nada mejor que entender lo que significan estas extrañas líneas:

  • Las líneas del tipo RewriteCond %{HTTP_REFERER} !^http://tuweb.com$ [NC] básicamente le dicen al servidor que para una petición que no (NO = !) proceda de las URLs indicadas, debe crear una regla…
  • … la regla es RewriteRule .*\.(gif|jpg|jpeg|png|bmp)$ – [F,NC,L], y lo que hace es prohibir (F) la carga de cualquier tipo de imagen (gif|jpg|jpeg|png|bmp), ignorar la diferencia entre mayúsculas y minúsculas (NC) de tal manera que sea igual una petición http://ejemplo.com/imagen.jPg que http://ejemplo.com/imagen.jPG, y por último la L indica que esa será la última regla en ejecutarse en caso de que se cumplan las condiciones.

Solo permitir que algunos sitios carguen nuestras imágenes

Para este caso, la idea es crear una lista blanca de los sitios que pueden cargar nuestras imágenes. Esto es útil, por ejemplo, para permitir a los lectores que nos sigan por medio del feed cargar las imágenes en Google Reader, NetVibes, etc.

Siguiendo con el ejemplo anterior nuestro .htaccess ahora deberá lucir de la siguiente manera:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /wordpress/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wordpress/index.php [L]

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://tuweb.com$ [NC]
RewriteCond %{HTTP_REFERER} !^http://tuweb.com/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.tuweb.com$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.tuweb.com/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.google.com/reader/view/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.google.com/reader/m/view/.*$ [NC]
RewriteRule .*\.(gif|jpg|jpeg|png|bmp)$ - [F,NC,L]
</IfModule>

Como ves, lo único que cambia es que añadimos las URL de los sitios permitidos, debajo del nuestro.

Cargar una imagen diferente

Lo típico a hacer aquí, es cargar una imagen que tenga nuestro logo y URL, de tal manera que los lectores del blog que nos hace hotlinking, se vean obligados a entrar a nuestro sitio si quieren ver nuestra imagen.

En este caso, lo que cambia es la última línea (RewriteRule), que es donde ordenamos al servidor a hacer una redirección:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://casidiablo.net$ [NC]
RewriteCond %{HTTP_REFERER} !^http://casidiablo.net/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.casidiablo.net$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.casidiablo.net/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.google.com/reader/view/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.google.com/reader/m/view/.*$ [NC]
RewriteRule .*\.(gif|jpg|jpeg|png|bmp)$ http://casidiablo.net/hotlink.png [R,NC,L]
</IfModule>

El único flag por explicar, teniendo en cuenta que ya explique el resto en el primer ejemplo, es R: redirecciona la petición a la URL indicada. Con esto cuando alguien intente poner la imagen en su Web, el resultado será el siguiente:

hotlinking frustrado

Cargar la misma imagen pero modificada (distorsionada, en blanco y negro, o con una marca de agua)

Este es mi método favorito, aunque requiere algo de programación en PHP. Puesto que el lector de la web que nos hace hotlinking no tiene la culpa, la idea es que hagamos algo más profesional: mostrar la imagen pero con modificaciones. Así, si nos robaran ésta imagen (de 103.95 KB), el navegador mostraría esto (una imagen de 9.01 KB):

hotlinking frustrado

Lo que se hizo fue lo siguiente:

  • Transformar la imagen JPG, lo cual hace que el ancho de banda utilizado sea menor
  • Reducir el tamaño la imagen, lo cual hace que el ancho de banda utilizado sea menor
  • Poner la imagen en blanco y negro, lo cual hace que el ancho de banda utilizado sea menor
  • Poner una marca de agua, para hacerle saber al lector a donde debe dirigirse
  • Mostrar un preview de la imagen original

Para lograr esto, debemos tener las librerías GD para PHP instaladas en el servidor (la mayoría los trae por defecto). Si deseas aprender a hacerlo, continúa leyendo la siguiente página…

Páginas de esta entrada: 1 2

35 Comentarios | deja el tuyo

4 enlaces entrantes

31 Comentarios en “[Tutorial] Evitar hotlinking y sacarle provecho”

  1. julian dice:

    @cristian, diferente en que?

  2. Cristian dice:

    Que tienes bastantes subscriptores vía mail… yo creo que tengo 2 XD Y en mi caso la mayoría usa GReader :P Y creo que tienes más subscriptores que yo, no recuerdo cuantos tengo :mrgreen:

  3. RUBI VANESSA dice:

    mira estoy desarolalando unproyecto no se si domines c# y agregar el boton de esacala de grises me esta fallando mira ya rompi la imagen y multiplique matrises pero nada mas no puedo sacar lo de la escala de grises si me pudieras ayudar no es q me lo agas pero si me pudieras dar una acesoria

  4. Ivan Moreno dice:

    Que tal, pues la verdad es que yo soy bastante principiante en php, sin embargo pues hice un agregado a tu script, un sistema de cache para evitar la sobre carga del servidor (a mi me pasaba luego de muchas ejecuciones continuas)

    Verificalo y me cuentas si tengo algun error.

  5. Ivan Moreno dice:

    Joder, me suprimio el codigo… mandame un mail para hacerte llegar el codigo…

  6. blog2k dice:

    inteesante, de hecho es lo que estaba busando, ahora si queremos que las imagenes que carguen esten en un server de imagenes gratuitaos como imagehack o similar, solo debemos agregar la direccion de esa imagen, no??
    saludos

  7. Cristian dice:

    Claro, tan simple como eso!

  8. blog2k dice:

    de mas agradecido!, ahora me queda ver que server uso! :P saludos y gracias

  9. blog2k dice:

    bueno les dejo la consulta por ahi puede ser un tema del servidor… estoy probando esto en un directorios de enlaces hecho con phpld y agrego la siguiente linia al htacces
    RewriteRule .*\.(gif|jpg|jpeg|png|bmp)$ http://img196.imageshack.us/img196/8088/enlaceblogdir6.gif [R,NC,L]
    el tema es que en algunos sitios no me muestra nada y en otros me lo muestra en cualquier posición….
    saludos

  10. Andres dice:

    Hola, use tus funciones para redimensionar las imagenes antes de subirlas a la BD y quedó perfecto, gracias. Pero hay imagenes sobre 1600px en que da un error de memoria. Esta imagen pesa 396Kb y las dimensiones son 3000 x 2121.

    Este es el error: Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 413965 bytes)

    Espero me puedas ayudar.

  11. Andres dice:

    Cristian, Gracias por contestar.
    Modifiqué la memoria limite del php.ini y mejoró, me dejo subir la foto, pero ahora tengo otra foto y pereciera que tengo que agrandar mas y mas la memoria limite. Ya voy en 512M. Como puedo restringir que intenten subir estas imágenes.

    Salu2.

  12. Cristian dice:

    Umm… OK, eso lo haces directamente desde PHP… en muchas partes se explica cómo hacerlo, por ejemplo:

    http://www.maestrosdelweb.com/editorial/upphp/

    Un saludo!

  13. Andres dice:

    Hola Cristian.
    Yo tambien uso $_FILES['archivo']['size']; para restringir el tamaño. Tengo imagenes que pesan 300k y no tengo problemas para subirlas y redimensionarlas, pero hay otras que pesan menos, pero que superan los 1600px donde aparece el error. Eso me ocurre justo en la linea donde ejecuto $im = imagecreatefromstring($bin_data);

    En un foro decían que que se debe a la función descomprime la imagen para poder trabajar con ella….. no se que tan valido es eso…. pero ahora estoy tratando de manejar el error que aparece para que el usuario entienda lo que pasó. Sabes como se hace?
    Salu2

  14. Diiego dice:

    uso la segunda opcion y me da error 500

  15. k-rlitos dice:

    Que bien explicado, se agradece mucho!!!!!

¡Déjanos tu comentario!