it-swarm.com.ru

Сканер 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-адрес изображения, которое появляется, когда кто-то делится контентом с Facebook. См. Ниже для получения дополнительной информации и ознакомьтесь с нашими лучшими практиками руководство, чтобы узнать, как указать высокое качество предварительного изображения.

Изображения, которые я использую в 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

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

Секунды, пока эта страница не будет пересмотрена. Используйте это, чтобы оценить ограничение сканеры контента Facebook. Минимально допустимое значение составляет 345600 секунды (4 дня); если вы установите более низкое значение, будет использовано минимальное значение . Если вы не включите этот тег, ttl будет вычислен из Заголовок «Expires» возвращается вашим веб-сервером, в противном случае он будет по умолчанию до 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" />
12
Wayne Whitty

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

По общему признанию, у нас были тысячи изображений, которые мы хотели, чтобы сканер сканировал, но сканер Facebook был практически DDOSing нашему серверу с десятками тысяч запросов (да, одни и те же URL снова и снова), в час. Я помню, что это было 40 000 запросов в час с разных IP-адресов Facebook с помощью агента пользователя 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 скрипт:

.../images/.htaccess (если вы используете Apache)

RewriteEngine On
RewriteRule .* index.php [L] 

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

9
Smuuf

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

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

  • Добавьте заголовок 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
rob006

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

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

3
Simon R

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

Здесь это идет:

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

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

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

2
Wayne Whitty

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

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

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

Дополнительная информация о заголовках "ETag" + "If-None-Match" .

0
Rober MH

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

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

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

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

0
Walter White

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

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

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

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

0
Emil

@Nico предлагает

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

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

0
serv-inc