Искатель Facebook сильно бьет по моему серверу и игнорирует директивы. Многократный доступ к одним и тем же ресурсам


Искатель Facebook поражает мои серверы несколько раз в секунду, и, похоже, он игнорирует как заголовок Expires, так и свойство og:ttl.

В некоторых случаях он обращается к одному и тому же ресурсу og:image несколько раз в течение 1-5 минут. В одном примере - искатель обращался к одному и тому же изображению 12 раз в течение 3 минут, используя 12 разных IP-адресов.

Мне нужно было только регистрировать запросы в течение 10 минут, прежде чем я поймал следующее пример:

Список времени и IP-адресов обходчика для одного изображения:

2018-03-30 15:12:58 - 66.220.156.145
2018-03-30 15:13:13 - 66.220.152.7
2018-03-30 15:12:59 - 66.220.152.100
2018-03-30 15:12:18 - 66.220.155.248
2018-03-30 15:12:59 - 173.252.124.29
2018-03-30 15:12:15 - 173.252.114.118
2018-03-30 15:12:42 - 173.252.85.205
2018-03-30 15:13:01 - 173.252.84.117
2018-03-30 15:12:40 - 66.220.148.100
2018-03-30 15:13:10 - 66.220.148.169
2018-03-30 15:15:16 - 173.252.99.50
2018-03-30 15:14:50 - 69.171.225.134

Что такое og:изображение в соответствии с документацией Facebook:

URL-адрес изображения, которое появляется, когда кто-то делится контентом с Фейсбук. Смотрите ниже для получения дополнительной информации и ознакомьтесь с нашими лучшими практиками руководство, чтобы узнать, как указать изображение предварительного просмотра высокого качества.

Изображения, которые я использую в og:image, имеют заголовок Expires, установленный на +7 дней в будущем. В последнее время я изменил это значение на +1 год в будущем. Ни одна из настроек, похоже, не имеет никакого значения. Заголовки, которые искатель, похоже, игнорирует:

Cache-Control: max-age=604800
Content-Length: 31048
Content-Type: image/jpeg
Date: Fri, 30 Mar 2018 15:56:47 GMT
Expires: Sat, 30 Mar 2019 15:56:47 GMT
Pragma: public
Server: nginx/1.4.6 (Ubuntu)
Transfer-Encoding: chunked
X-Powered-By: PHP/5.5.9-1ubuntu4.23

Согласно документации по свойствам объектов Facebook , свойство og:ttl:

Секунды до того, как эта страница будет очищена заново. Используйте это для ограничения скорости искатели контента Facebook. Минимально допустимое значение составляет 345600 секунды (4 дня); если вы установите меньшее значение, будет использоваться минимальное. Если ты не включайте этот тег, ttl будет вычислен из Заголовок "Истекает", возвращаемый вашим веб-сервером, в противном случае он будет по умолчанию равен 7 дням.

Я установил для этого свойства og:ttl значение 2419200, что составляет 28 дней в будущем.

У меня возникло искушение использовать что-то вроде этого:

header("HTTP/1.1 304 Not Modified"); 
exit;

Но я опасаюсь, что искатель Facebook проигнорирует заголовок и пометит изображение как сломанное, тем самым удалив предварительный просмотр изображения из общей истории.

А видео, показывающее скорость, с которой поступают эти запросы от искателя.

Есть ли способ предотвратить возвращение искателя к этим ресурсам так скоро?

Пример кода, показывающий, как выглядят мои открытые графические и мета-свойства:

<meta property="fb:app_id" content="MyAppId" />
<meta property="og:locale" content="en_GB" />
<meta property="og:type" content="website" />
<meta property="og:title" content="My title" />
<meta property="og:description" content="My description" />
<meta property="og:url" content="http://example.com/index.php?id=1234" />
<link rel="canonical" href="http://example.com/index.php?id=1234" />
<meta property="og:site_name" content="My Site Name" />
<meta property="og:image" content="http://fb.example.com/img/image.php?id=123790824792439jikfio09248384790283940829044" />
<meta property="og:image:width" content="940"/>
<meta property="og:image:height" content="491"/>
<meta property="og:ttl" content="2419200" />
Author: Wayne Whitty, 2018-03-30

8 answers

После того, как я перепробовал почти все остальное с кэшированием, заголовками и всем прочим, единственное, что спасло наши серверы от "чрезмерно восторженного" искателя Facebook(агент пользователя facebookexternalhit) был просто отказ в доступе и отправка обратно HTTP/1.1 429 Too Many Requests HTTP-ответа , когда искатель "слишком много ползал".

По общему признанию, у нас были тысячи изображений, которые мы хотели, чтобы искатель сканировал, но искатель Facebook был практически DDoS-атакой на наш сервер с десятками тысяч запросов (да, одни и те же URL-адреса снова и снова), в час. Я помню, что в какой-то момент это было 40 000 запросов в час с разных IP-адресов Facebook с использованием агента пользователя te facebookexternalhit.

Мы не хотели полностью блокировать искатель, и блокировка по IP-адресу также не была вариантом. Нам нужно было только, чтобы искатель FB немного отступил (совсем).

Это фрагмент PHP-кода, который мы использовали для этого:

.../images/index.php

<?php

// Number of requests permitted for facebook crawler per second.
const FACEBOOK_REQUEST_THROTTLE = 5;
const FACEBOOK_REQUESTS_JAR = __DIR__ . '/.fb_requests';
const FACEBOOK_REQUESTS_LOCK = __DIR__ . '/.fb_requests.lock';

function handle_lock($lockfile) {
    flock(fopen($lockfile, 'w'), LOCK_EX);
}

$ua = $_SERVER['HTTP_USER_AGENT'] ?? false;
if ($ua && strpos($ua, 'facebookexternalhit') !== false) {

    handle_lock(FACEBOOK_REQUESTS_LOCK);

    $jar = @file(FACEBOOK_REQUESTS_JAR);
    $currentTime = time();
    $timestamp = $jar[0] ?? time();
    $count = $jar[1] ?? 0;

    if ($timestamp == $currentTime) {
        $count++;
    } else {
        $count = 0;
    }

    file_put_contents(FACEBOOK_REQUESTS_JAR, "$currentTime\n$count");

    if ($count >= FACEBOOK_REQUEST_THROTTLE) {
        header("HTTP/1.1 429 Too Many Requests", true, 429);
        header("Retry-After: 60");
        die;
    }

}

// Everything under this comment happens only if the request is "legit". 

$filePath = $_SERVER['DOCUMENT_ROOT'] . $_SERVER['REQUEST_URI'];
if (is_readable($filePath)) {
    header("Content-Type: image/png");
    readfile($filePath);
}

Ты также необходимо настроить перезапись, чтобы передавать все запросы, направленные на ваши изображения, в этот PHP-скрипт:

.../ изображения/.htaccess ( если вы используете Apache)

RewriteEngine On
RewriteRule .* index.php [L] 

Похоже, что искатель "понял этот" подход и эффективно снижена частота попыток от десятков тысяч запросов в час до сотен/тысяч запросов в час.

 5
Author: Smuuf, 2018-04-09 21:22:51

Отправка заголовка вслепую 304 Not Modified не имеет особого смысла и может еще больше запутать поисковик Facebook. Если вы действительно решите просто заблокировать какой-то запрос, вы можете рассмотреть 429 Слишком много запросов заголовок - это, по крайней мере, четко укажет, в чем проблема.

В качестве более мягкого решения вы можете попробовать:

  • Добавьте заголовок Last-Modified с некоторым статическим значением. Искатель Facebook может быть достаточно умен, чтобы обнаружить, что для постоянно меняющегося контента он должен игнорировать Expires заголовок, но недостаточно умен, чтобы правильно обработать отсутствующий заголовок.
  • Добавьте заголовок ETag с надлежащей поддержкой 304 Not Modified.
  • Измените заголовок Cache-Control на max-age=315360000, public, immutable, если изображение статичное.

Вы также можете рассмотреть возможность сохранения кэшированного изображения и его обслуживания через веб-сервер без использования PHP. Если вы измените URL-адреса на что-то вроде http://fb.example.com/img/image/123790824792439jikfio09248384790283940829044 Вы можете создать резервный вариант для несуществующих файлов с помощью правил перезаписи:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^img/image/([0-9a-z]+)$ img/image.php?id=$1 [L]

PHP должен обрабатывать только первый запрос, что позволит сэкономить кэш для запрошенного URL-адреса (например, в /img/image/123790824792439jikfio09248384790283940829044). Затем для всех дальнейших запросов веб-сервер должен позаботиться об обслуживании содержимого из кэшированного файла, отправке правильных заголовков и обработке 304 Not Modified. Вы также можете настроить nginx для ограничения скорости - это должно быть более эффективно, чем делегирование обслуживания изображений PHP.

 3
Author: rob006, 2018-04-09 21:10:54

Похоже, что поисковые роботы Facebook не всегда проявляют такое уважение. В прошлом мы реализовали это предложение здесь: чрезмерный трафик от бота facebookexternalhit.

Это не лучшее решение, так как для Facebook было бы неплохо ограничить частоту запросов, но очевидно, что они этого не делают.

 2
Author: Simon R, 2018-04-02 20:05:44

Я получил ответ от самой команды Facebook. Надеюсь, это внесет некоторое разъяснение в то, как искатель обрабатывает URL-адреса изображений.

Вот оно:

Искатель обрабатывает URL-адреса изображений иначе, чем другие URL-адреса.

Мы очищаем изображения несколько раз, потому что у нас разные физические области, каждая из которых нуждается в извлечении изображения. Так как у нас есть вокруг 20 разных регионов, разработчик должен ожидать ~20 звонков для каждого изображение. Как только мы сделаем эти запросы, они остаются в нашем кэше около месяц - нам нужно часто повторно сканировать эти изображения, чтобы предотвратить злоупотребления на платформе (злоумышленник может заставить нас очистить доброкачественную изображение, а затем замените его оскорбительным).

Таким образом, в принципе, вы должны ожидать, что изображение, указанное в og:изображение, будет отображено 20 раз после того, как оно будет передано. Затем, месяц спустя, его снова соскоблят.

 1
Author: Wayne Whitty, 2018-04-10 06:29:03

Согласно документации Facebook только искатель Facebot соблюдает директивы обхода. Однако они также предполагают это

Вы можете настроить один из этих пользовательских агентов для предоставления искателю непубличной версии вашей страницы, которая содержит только метаданные и не содержит фактического контента. Это помогает оптимизировать производительность и полезно для сохранения защищенный контент с платным доступом.

Некоторые люди предлагают ограничить доступ к facebookexternalhit, однако я сомневаюсь это хорошая идея, так как это может помешать искателю обновлять содержимое.

Просмотр нескольких обращений с разных IP-адресов, но одного и того же бота может быть приемлемым, в зависимости от их архитектуры. Вы должны проверить, как часто выполняется обход одного и того же ресурса. og: ttl - это то, что рекомендует документация и должно помочь.

 0
Author: Emil, 2018-04-07 16:18:15

Если искатели FB игнорируют заголовки вашего кэша, в этом случае можно использовать заголовок "ETag", чтобы вернуть правильные 304 ответа и снизить нагрузку на ваш сервер.

При первом создании изображения вычислите хэш этого изображения (например, используя md5) в качестве заголовка ответа "ETag". Если ваш сервер получает запрос с заголовком "Если не совпадает", проверьте, не вернули ли вы уже этот хэш. Если ответ "да", верните ответ 304. Если нет, сгенерируйте изображение.

Проверка того, что вы уже вернули заданный хэш (избегая при этом повторного создания изображения), означает, что вам нужно будет где-то хранить хэш... Может быть, сохранить изображения в папке tmp и использовать хэш в качестве имени файла?

Дополнительная информация о заголовках "ETag" + "Если не совпадает".

 0
Author: Rober MH, 2018-04-07 18:04:58

Документация Facebook, в частности, гласит "Изображения кэшируются на основе URL-адреса и не будут обновляться, если URL-адрес не изменится".. Это означает, что не имеет значения, какие заголовки или мета-теги вы добавляете на свою страницу, бот все равно должен кэшировать изображение.

Это заставило меня задуматься:

  1. Использует ли каждый пользователь немного другой URL-адрес вашей страницы? Это приведет к тому, что общее изображение будет повторно кэшироваться каждый раз.
  2. Доступ к вашему общему изображению осуществляется с помощью слегка другой URL-адрес?
  3. Может быть, изображение где-то связано по-другому?

Я бы отслеживал журналы страниц и точно видел, что происходит - если URL-адрес страницы или URL-адрес изображения даже немного отличаются, механизм кэширования не будет работать. К счастью, это не похоже на проблему типа заголовков/тегов.

 0
Author: Walter White, 2018-04-08 09:12:18

@ Нико предлагает

У нас были такие же проблемы на нашем веб-сайте/сервере. Проблема заключалась в метатеге og:url. После его удаления проблема была решена для большинства вызовов facebookexternalhit.

Так что вы можете попробовать удалить это и посмотреть, устранит ли это проблему

 0
Author: serv-inc, 2018-04-09 07:18:39