Manual de PHP: Evitar el hotlinking de los buscadores

La práctica del hotlinking o "robo de ancho de banda", siempre ha supuesto un gran problema en Internet, ya que quien efectúa hotlinking está usando el espacio de almacenamiento, y sobre todo el ancho de banda, de la web enlazada, lo que tiene un coste para su propietario. Incluso podría motivar que se superen los límites del hosting y ser penalizado, ya sea económicamente o con la suspensión temporal del servicio, con lo que la página ya no podría visualizarse.

Por ello, muchos webmaster utilizan técnicas anti-hotlinking, generalmente utilizando el archivo .htaccess, fichero de configuración del servidor web Apache que permite denegar el acceso a las imágenes enlazadas mediante hotlinking o incluso reemplazarlas por otras imágenes con un mensaje publicitario del sitio original para disuadir a las personas sin escrúpulos de efectuar esta práctica.

Pero el gran problema ha surgido cuando también los motores de búsqueda han recurrido al hotlinking en los resultados de las búsquedas de imágenes, como es el caso de Google. Con la búsqueda de imágenes tradicional, el visitante localizaba las fotos a través de Google y posteriormente accedía al sitio web original, lo que satisfacía a todos.

Sin embargo con la nueva búsqueda de Google mediante hotlink, los usuarios pueden descargar las fotos sin visitar el sitio original, de tal manera que el buscador utiliza el ancho de banda y las imágenes del sitio original sin ni siquiera enviarle tráfico. Como muchos fotógrafos y artistas gráficos saben, la caída de tráfico de sus sitios webs debido a esta práctica de los buscadores es de gran trascendencia, puede rondar el 80%.

Nueva busqueda e imagenes de Google

La nueva búsqueda de imágenes de Google y otros buscadores mediante hotlinking provoca que el usuario no tenga incentivos para visitar la página web del creador original, ya que obtiene la imagen simplemente visitando Google, por lo que no hay razón para visitar la web original o preocuparse por la posible infracción de derechos de autor.

Para evitar este perjuicio la solución es implementar medidas anti-hotlinking, de tal manera que no se puedan descargar las imágenes desde Google, sino que el visitante al clickar en "Ver imagen original" visualice una imagen con marca de agua (watermark) donde se le indique que la imagen está protegida contra hotlinking y sólo se puede ver y descargar en el sitio original, para lo cual tendrá que clickar en "Visitar página".

Atención

Implementar sistemas anti-hotlinking puede suponer que algunos buscadores apliquen penalizaciones que afecten al PageRank y al posicionamiento, debido a que pueden ser considerada una práctica de “Imágenes encubiertas”, ya que las imágenes que se muestran en el sitio web no serían las mismas que aparecen en las páginas de resultados de búsqueda.

Por ejemplo, Google considera encubrimiento la práctica de mostrar un contenido a los usuarios y otro en los motores de búsqueda, lo que considera un incumplimiento de las Directrices para webmasters de Google porque proporciona a los usuarios resultados diferentes a los esperados.

Aunque existen numerosos plugins para evitar el hotlinking para la mayoría de plataformas de publicación, como WordPress, Joomla o Drupal, voy a mostrar aquí un script en PHP sencillo de implementar y válido para cualquier sitio web, donde se muestra la técnica para generar imágenes con marca de agua al vuelo (on the fly). Para ello emplea tres componentes:

  • watermark.png: imagen PNG para utilizar como marca de agua. Contiene una imagen personalizada, por ejemplo con el texto "Click here full resolution".
  • watermark.php: script en PHP que procesa on the fly la imagen que se le pasa como parámetro y la devuelve redimensionada y con marca de agua.
  • .htaccess: activaremos reglas rewrite en el fichero de configuración del servidor web Apache. Para otros servidores web habrá que definir unas reglas rewrite equivalentes.

watermark.php

El script watermark.php procesa imágenes JPG, PNG y GIF. Su contenido es el siguiente:

<?php
header('content-type: image/jpeg');
 
//imagen a procesar
$src = $_GET["src"];
 
//detectar extensión con pathinfo()
$path_info = pathinfo($src);
 
//imagen original
switch ($path_info['extension']) {
	case 'jpg':
		$image = imagecreatefromjpeg($src);
	break;
 
	case 'png':
		$image = imagecreatefrompng($src);
	break;
 
	case 'gif':
		$image = imagecreatefromgif($src);
	break;
}
$image_width = imagesx($image);
$image_height = imagesy($image);
 
//redimensionar la imagen original
$image_resized_width = 500;
$image_resized_height = $image_height * $image_resized_width / $image_width;
$image_resized = imagecreatetruecolor($image_resized_width, $image_resized_height);
imagecopyresampled($image_resized, $image, 0, 0, 0, 0, $image_resized_width, $image_resized_height, $image_width, $image_height);
 
//marca de agua
$watermark = imagecreatefrompng('watermark.png');
$watermark_width = imagesx($watermark);
$watermark_height = imagesy($watermark);
 
//redimensionar la marca de agua
$watermark_resized_width = $image_resized_width;
$watermark_resized_height = $watermark_height * $image_resized_width / $watermark_width;
$watermark_resized = imagecreatetruecolor($watermark_resized_width, $watermark_resized_height);
imagecopyresampled($watermark_resized, $watermark, 0, 0, 0, 0, $watermark_resized_width, $watermark_resized_height, $watermark_width, $watermark_height);
 
//fondo para la marca de agua
$background = imagecreatetruecolor($image_resized_width, $image_resized_height);
imagefill($background, 0, 0, 0x000000); //negro
 
//fusionar el fondo sobre la imagen original
imagecopymerge($image_resized, $background, 0, 0, 0, 0, $image_resized_width, $image_resized_height, 50); //opacidad 0-100
 
//fusionar la marca de agua sobre la imagen original
imagecopymerge($image_resized, $watermark_resized, 0, 0, 0, 0, $watermark_resized_width, $watermark_resized_height, 50); //opacidad 0-100
 
//exportar imagen con marca de agua
switch ($path_info['extension']) {
	case 'jpg':
		imagejpeg($image_resized, NULL, 70); //calidad 0-100
	break;
 
	case 'png':
		imagepng($image_resized, NULL, 9); //compresión 0-9
	break;
 
	case 'gif':
		imagegif($image_resized);
	break;
}
?>

watermark.png

En la imagen watermark.png se puede personalizar el texto de la marca de agua, por ejemplo "Click here full resolution", "Visit website yoursite.com for see full resolution photo", "Hotlinking has been disabled for this domain", "Hotlinking in not cool" o "This person was hotlinking this image and stealing bandwith from yoursite.com".

Marca de agua

.htaccess

En el archivo .htaccess establecemos las reglas rewrite para Apache. Redirige imágenes JPG, PNG y GIF y envía la petición a watermark.php pasándole el nombre de la imagen como parámetro. Sólo permite nuestro dominio y subdominios, traductores y spiders. No permite blank referers. No olvides reemplazar yoursite.com por el sitio correspondiente. Su contenido es el siguiente:

# BEGIN Stop Image Hotlinking
RewriteCond %{REQUEST_URI} \.(jpg|png|gif)$ [NC]
RewriteCond %{HTTP_REFERER} !^http://([^.]+\.)?yoursite\.com [NC]
RewriteCond %{HTTP_REFERER} !(translate.google\.com|googleusercontent\.com) [NC]
RewriteCond %{HTTP_REFERER} !(translate\.googleusercontent\.com|gstatic\.com) [NC]
RewriteCond %{HTTP_REFERER} !(microsofttranslator\.com) [NC]
RewriteCond %{HTTP_REFERER} !(googleapis\.com|ytimg\.com) [NC]
RewriteCond %{HTTP_USER_AGENT} !(googlebot|msnbot|baiduspider|slurp|webcrawler) [NC]
RewriteCond %{HTTP_USER_AGENT} !(teoma|facebookexternalhit|facebookplatform) [NC]
RewriteCond %{HTTP_USER_AGENT} !(pinterest|feedfetcher|ggpht|smush\.it|akamai) [NC]
RewriteCond %{HTTP_USER_AGENT} !(cloudfront|netdna|bitgravity|maxcdn|edgecast) [NC]
RewriteCond %{HTTP_USER_AGENT} !(limelight|tineye|developers|gstatic|googleapis) [NC]
RewriteCond %{HTTP_USER_AGENT} !(googleusercontent|google|ytimg|photon) [NC]
RewriteRule (.*) watermark.php?src=$1 [L]
# END Stop Image Hotlinking

De esta manera, las imágenes enlazadas con hotlinking se visualizarán con marca de agua (dcha), muy diferentes del original (izda):

Imagen original e imagen con marca de agua

Artículos en la categoría "Manual de PHP"

  1. Manual de PHP: Estructuras de control
  2. Manual de PHP: Funciones
  3. Manual de PHP: Objetos
  4. Manual de PHP: Formularios web
  5. Manual de PHP: Imágenes
  6. Manual de PHP: XML
  7. Manual de PHP: MySQL
  8. Manual de PHP: Sesiones
  9. Manual de PHP: Matrices
  10. Manual de PHP: Expresiones regulares
  11. Manual de PHP: Sanear datos de usuario
  12. Manual de PHP: Email
  13. Manual de PHP: Evitar el hotlinking de los buscadores