Facebook puede tumbar servidores web con su sistema de precargas de páginas. precargas páginas app facebook

precargas páginas app facebook: Hace ya unos meses que venía observando unas diferencias abismales entre las visitas que me daban las estadísticas de google analytics y las estadísticas provenientes de mis logs y sistemas de seguimiento. No en todas mis web, solo en algunas, principalmente las de mayor tráfico.
Por falta de tiempo no le he querido dar mucha importancia, dado que pensaba que se trataban de robots, indexadores, etc.

A medida que ha ido pasando el tiempo la situación se ha ido agravando considerablemente, con una tase de 10:1, por cada 10 visitas de mis logs en google analytics solo me reflejaba 1…, por ejemplo en una web con unas 70.000 visitas al día reales en los logs me reflejaban 700.000.
No es lo mismo un servidor para aguantar 70.000 visitas que un servidor para 700.000, además acabo de introducir un concepto en el párrafo anterior, “visitas reales”.

Ante esta situación y aprovechando estos días de pre navidad de menor carga de trabajo empecé a indagar los logs, en ellos nada relevante, solo un volumen muy alto desde Facebook, algo normal en la web en cuestión dado que el tráfico principal siempre ha venido desde Facebook, con un volumen de más de 2.500.000 seguidores, ocupando otras fuentes un lugar mucho menor en las estadísticas. Tampoco detectaba robots en exceso, nada anormal en ese aspecto. Tampoco parecían ataques ddos dado que las ip eren todas diferentes, clientes y usuarios normales.

Ante esta situación mi primera pesquisa para encontrar el problema y por un lado la más lógica era seguir la pista de visitas zombis, y empezar a indagar las cargas de js, eliminando el cacheado e intentar obligar a los clientes y visitas a descargar los js. Este fue mi primer acercamiento al problema, realmente las visitas se producen, hay peticiones pero no se descargaban CSS, JS ni imágenes, en una gran proporción. Pero cuidado porque al existir peticiones si hay tráfico, sobrecarga del servidor, ejecución de script del lado del servidor en mi caso PHP, peticiones y carga al servidor de base de datos… etc

Mi siguiente paso fue crear un sistema muy sencillo para guardar en una base de datos todas las peticiones, guardando url de referencia, header, agent, ip y fecha. Algo muy parecido a los ficheros logs de mi servidor en mi caso Apache pero en mi MySQL y así permitirme realizar consultas más elaboradas y que me ayudaran a encontrar el problema.

La verdad que lo que empecé a ver cada vez me gustaba menos, en tan solo 17 minutos más de 5000 peticiones y eso que eran altas horas de la noche, la mayoría con referencia http://m.facebook.com, pero tan solo 300 visitas marcadas en google analytics, un bombardeo indiscriminado a mi servidor… por suerte tengo 16GB con 4 nucleos en ese servidor y nunca había notado estrés… aunque me temo que se deben haber producido atascos en el trafico.

Decidí mejorar un poco el sistema, de tal forma que metí un pequeño código js que vía Ajax una vez cargada la página enviara el id de la visita guardada vía php en la petición y marcara esa visita como que había cargado Ajax, si no lograba hacer la petición Ajax es que en principio el cliente no podría cargar js y esa visita la marcaba como cliente o visita zombi. Quedando algo así:

CÓDIGO PHP QUE SE EJECUTA EN EL SERVIDOR EN LA PETICIÓN:


$headers_ = apache_request_headers();
$headers;
foreach ($headers_ as $header_ => $value_) {
$headers .= "$header_: $value_ \n";
}
$query = "INSERT INTO visitas (ip, broser, post, referencia, header) VALUES ('".$_SERVER['REMOTE_ADDR']."', '".$_SERVER['HTTP_USER_AGENT']."'," . $post['id'].", '". $_SERVER['HTTP_REFERER']."', '" . $headers . "')";
mysql_query($query);
$id_visita = mysql_insert_id();

CÓDIGO JS (JQUERY) LLAMAMIENTO AJAX, donde marco la visitas si carga y ejecuta esto:


$.post( "includes/visitas.php", { id: <? echo $id_visita; ?> } );

CÓDIGO visitas.php, script php que marca la visita ejecutora js:

<? include("../datos.php"); $id = $_POST['id']; $query = "UPDATE visitas SET cargado = 1 WHERE id = " . $id; mysql_query($query); ?>

Los resultados empezamos a ser aclaradores, un volumen altísimo de las peticiones no lograban cargar ejecutar PHP pedido desde ajax, casi todas con referencia http://m.facebook.com con ip todas diferentes.
Un pantallazo de la tabla quedaría así. Marcando el campo “cargado” con 0 si no ejecuta js y con 1 si lo carga.

a
Pensé en mirar otras opciones tipo crear una imagen de un pixell con php en cada petición identificando la visita que al mismo tiempo produjera al mismo efecto del js si lograba cargar la imagen, pero me llevaría otro ratito y estaba claro lo que estaba pasando… eran llamamientos a mis páginas desde clientes cuyo navegador solo pedía el html, algo parecido a lo que hacen los indexadores y robots, pero estaba claro que eran personas normales, usuarios normales por la gran cantidad de ip´s, un ataque ddos u otros estaba al mismo tiempo descartado.

Mi intuición me decía que eran precargas, en este caso desde Facebook. Pero no lo podía confirmar porque usando utilizando la app Facebook no conseguía identificar mi ip entre los registros como visita zombi, no he podido lograr saber cuando la app facebook o su algoritmo hace realmente una precarga, ha puesto el movil incluso solo en modo 2g.

Sabiendo y conociendo el problema no me quedaba más remedio que empezar a buscar en internet personas con problemas similares, encontrado muy poca documentación. Hoy en día los foros cada vez son peores, con un nivel muy por debajo de lo que podías encontrar hace unos años, una pena. Decidí preguntar en el grupo de desarrolladores para Facebook oficial… se puede ver en este Hilo:

Gracias a la comunidad mis pesquisas se venían a confirmar… o al menos es lo que pensaba y no podía confirmar. Se tratan de precargas por parte de la app Facebook, básicamente cuando un usuario de la app Facebook para Android mira su muro y aparece un enlace de alguna de mis páginas, si el algoritmo de la app entiende que tiene posibilidades de hacer click, la app precarga nuestra página en la trastienda, en segundo plano, dejando preparado el html que generalmente es el contenido principal, para que pueda visualizarla los más rápido posible, quedando la carga del css, js, imágenes y demás para cuando el usuario hace click.

Esto que en principio puede ser interesante es un verdadero problema cuando son cientos de miles de fans los que tienes, incluso algún miembro de la comunidad ha llegado a decir que esto sucede cuando tienes una web Facebook con más de 10000 seguidores… en mi caso en ese caso tenemos más de 2.500.000 seguidores. Es un verdadero ataque ddos segmentado en miles de usuarios que te hacen peticiones al servidor, generando más problemas que soluciones y velocidad real de descarga que incluso se puede ver mermada dramáticamente. Creo que facebook no ha sido capaz de prever las consecuencias. Insisto que son los dispositivos de los usuarios utilizando sus datos de conexión los que inundan con peticiones a los servidores.

La idea por parte de facebook entiendo que puede ser la siguiente, para dar la impresión de velocidad en la app Facebook, lo que hacen es utilizar los dispositivos de los usuarios para precargar las páginas en pro de un % ínfimo de velocidad de carga, si esto lo multiplicamos por cientos de miles de usuarios haciendo peticiones sobre un servidor el resultado puede ser desastroso.

El único pro que le veo a esto es una carga un poco más rápida, si tienes un buen servidor será algo totalmente trasparente para el usuario.

Pero hay muchos más contras de este sistema, aparte de parecerme abusivo y muy poco ético, primero decir que el sistema de precarga está ideado para precargar tus propias páginas (esa es la ideología) no las de terceros, si tienes una web y quieres precargar la posibles páginas en ser visitadas, lo vas haciendo en la trastienda dado lugar a una sensación de carga más rápida, pero es algo que puedes controlar sabiendo la cantidad de visitas propias… el problema es que precargan páginas que no son suyas. Aparte los navegadores permiten cerrar esta posibilidad si el usuario así lo configurar.

Esto provoca una inundación indiscriminada y en un alto porcentaje inútil de peticiones, eleva mucho el tráfico, porque aunque no descarga recursos js o imágenes si descarga el html, se producen ejecuciones en el servidor agotando los ciclos de proceso, peticiones a la base de datos, aumentado los logs del sistema, y un largo etc.

Debo entender que estas precargas se harán cuando el dispositivo este connectado a un conexión wifi…,

Mitigar el problema de precargas páginas app facebook

Incluso Facebook tiene un tip de ayuda donde se habla de esto.

Aquí se deja claro que las precargas son identificadas de la siguiente forma:
Para solventar esto, Facebook ha adoptado la práctica estándar en el sector de incluir un encabezamiento “X-Purpose:preview” en estas solicitudes…

Algo que tampoco es válido porque así es como se deberían identificar según la normativa este tipo de peticiones, pero no las segmenta ni discrimina, la idea sería bloquear a nivel servidor esas peticiones, pero cuidado porque si hacemos eso corremos el riesgo de al mismo tiempo mitigar el problema, prohibir otras precargas que si nos sean necesarias por otros motivos.

Queda en manos de nosotros identificarlas, y volviendo a las líneas de arriba hay que recordar que la url de referencia principal era http://m.facebook.com con lo que tendríamos otra línea para bloquear… que se debe dar al mismo tiempo y no por separado, porque las visitas reales al mismo tiempo también vienen desde esa url por lo que cuidado y no bloquear la visitas de esa referencia.

En una web americana encontré un patrón para identificar al menos desde mi punto de vista en parte las ( precargas páginas app facebook )  con el que después de un experimento no estoy del todo de acuerdo, por otro lado se habla del agente que identifica este tipo de visitas, aquellos agente que cuentan entre su información con esto: User-Agent has: FB_IAB/FB4A;FBAV (Facebook in-app browser for Android), algo en lo que coincido. Y al mismo tiempo con x-fb-http-engine: Liger en el requerimiento http.
De tal forma que en principio según la comunidad se debería bloquear  vía servidor a la peticiones con requerimientos X-Purpose:preview y x-fb-http-engine: Liger 

Algo que podemos conseguir por ejemplo incluyendo en él .htaccess del raíz de nuestro proyecto incluyendo estas líneas:

RewriteCond %{HTTP:x-fb-http-engine} Liger
RewriteCond %{HTTP:X-Purpose} preview
RewriteRule .* - [F,L]

Básicamente enviamos un error 403 al cliente ante peticiones cuyo encabezamiento de requerimiento son ambos.

En mi caso no estoy del todo de acuerdo puesto que analizando los registro de todas las entradas si encontré visitas donde había ambos encabezados, y al mismo tiempo desde referencia http://m.facebook.com que si lograban cargar el js del Ajax, si bloqueamos no sabemos si realmente estamos perdiendo visitas reales. O quizás es que el sistema de precargas al mismo tiempo en algunos casos si carga y ejecuta el js?

Al mismo tiempo después de de seguir analizando he podido verificar que hay otro encabezamiento basante sosfechoso: HTTP:X-FB-HTTP-Engine: Tigon+iOS igualmente son visitas desde facebook que provocan precargas, en este caso el agente siempre era ipad, aunque intuyo que es para dispositivos apple, por lo que ahora mismo estoy utilizando y parece que estoy mitigando al completo todo este problema… y espero no estar desperdiciando visitas válidas, aunque sigo con pruebas:

RewriteCond %{HTTP:x-fb-http-engine} Liger
RewriteRule .* - [F,L]
RewriteCond %{HTTP:X-FB-HTTP-Engine} Tigon
RewriteRule .* - [F,L]
RewriteCond %{HTTP:X-FB-HTTP-Engine} iOS
RewriteRule .* - [F,L]

Y por otro lado utilizando esas directivas a nivel apache si siguen entrando muchas entradas zombis, no tantos y se consigue relajar el problema bastante… en el servidor, por lo que por un lado no sé si algunas de esas visitas de precargas al final son reales y por otro lado la cantidad de visitas que en principio son solo recargas disminuye bastante pero no se freta totalmente.

Voy a seguir haciendo algunas pruebas y contaré el resultado… en todo caso si has leído esto te animo a que hagas tus pruebas y comentemos experiencias.

Ya deberías ser tú el que decida actuar en consecuencia contra estas precargas a nivel servidor analizando los costes del mismo o si por otro lado te compensa. Las precargas páginas app facebook en definitiva son un gran problema.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *