Tengo un sitio web con muchas páginas donde cada página tiene muchas imágenes (docenas o incluso cientos).
Estoy tratando de evitar el hotlinking de imágenes, pero sin aumentar demasiado los costos de AWS.
Hasta ahora encontré 3 opciones:
Opción 1: use WAF para evitar los enlaces directos, creando una regla para bloquear según el encabezado de referencia.
El problema de esta solución es que si tiene muchas imágenes cargadas en cada página, el costo aumentará demasiado, porque más allá de pagar S3 y CloudFront, también deberá pagar WAF, por cada solicitud de imagen (imagínese si tiene 100 imágenes en cada página, por ejemplo).
Opción 2: Configure CloudFront para activar un activador de solicitud de Lambda@Edge Viewer que inspeccionará cada solicitud a medida que llega y bloqueará las solicitudes en función del encabezado de referencia.
https://stackoverflow.com/a/46044606/2444386
Esto es similar a la opción anterior. El problema es que agrega una sobrecarga a CADA solicitud, incluso si la imagen ya está en el caché de CloudFront. Lambda@Edge siempre se llamará y también aumentará demasiado el costo si tiene muchas imágenes en cada página de su sitio web.
Opción 3: Configure la política de depósito de S3 para bloquear solicitudes en función del encabezado del remitente y agregue el encabezado del remitente a la lista blanca en CloudFront.
Hasta ahora me parece la opción con mejor costo beneficio, porque si la imagen ya está en caché de CloudFront, no tienes gastos generales, y además el costo es el más económico porque no necesitas pagar WAF ni Lambda@Edge.
El problema es que la proporción de aciertos de la memoria caché será mucho menor, porque CloudFront no entregará una respuesta de la memoria caché a menos que el encabezado Referer de la solicitud entrante coincida exactamente con uno de una solicitud ya almacenada en la memoria caché.
Traté de usar el encabezado de solicitud de "origen" para evitar este problema, pero parece que el navegador no envía este encabezado para las solicitudes GET de imágenes.
¿Hay alguna opción mejor?
Puede evitar los anteriores mediante el uso de una opción nativa compatible con CloudFront, Signed Cookies .
Al agregar una función Lambda@Edge si el usuario llega a una página no basada en activos (es decir, la página de inicio), podría generar una cookie firmada. Al hacer cumplir esto en CloudFront, solo las personas que navegan por su sitio web podrán acceder a los activos.
Alternativamente, puede generar una URL firmada de CloudFront , aunque esto debería hacerse para cada activo.
Para usarlos, cree un origen/comportamiento secundario para los activos que desea proteger y agregue la regla de comportamiento de Restrict Viewer Access (Use Signed URLs or Signed Cookies) . Lambda@Edge viviría en el otro origen.
Terminé usando la opción 3 ( política de depósito S3 ) y, además, usando el plan gratuito de CloudFlare . CloudFlare tiene "Protección Hotlink" en el "Scrape Shield" incluso en el plan gratuito.
Política de depósito S3 para evitar hotlinking:
{ "Version": "2012-10-17", "Id": "http referer policy", "Statement": [ { "Sid": "Allow access only from my website", "Effect": "Deny", "Principal": { "AWS": "*" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::resources.mywebsite.com/*", "Condition": { "StringNotLike": { "aws:Referer": [ "https://dev.mywebsite.com:8080/*", "https://staging.mywebsite.com/*", "https://www.mywebsite.com/*" ] } } } ] }En CloudFront incluí en la lista blanca el encabezado Referer:
Y en CloudFlare puedes habilitar la opción "Protección Hotlink" en el menú "Scrape Shield":