Наблюдения за vBulletin или попытки кэширования динамического контента. Наблюдения за vBulletin или попытки кэширования динамического контента Североамериканская vbulletin

Ты наверняка неоднократно видел форумы на движке vBulletin. Форумы как таковые уже не на пике моды, но vBulletin по-прежнему один из самых популярных движков. В его последней (пятой) версии нашли несколько уязвимостей, которые способны сильно испортить жизнь админу. В этой статье я расскажу, как они эксплуатируются.

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

Вторая уязвимость была найдена исследователями из компании TRUEL IT и получила идентификатор CVE-2017-17672. Она связана с особенностями десериализации данных в движке и может быть использована атакующим для удаления произвольных файлов в системе.

Полные отчеты с деталями обеих проблем были опубликованы в рамках программы Beyond Security от SecuriTeam. Там же есть PoC-эксплоиты для демонстрации уязвимостей. Давай по порядку пройдемся по всему этому.

Приготовления

В качестве сервера я использовал дистрибутив WAMP.

Читаем файлы, выполняем команды

Итак, причина первой уязвимости - некорректная логика при обработке параметра routestring, которая позволяет атакующему добавить через include любой файл на диске и выполнить PHP-код, который в нем находится.

Наш путь начинается с самого главного файла - index.php, где происходит базовая инициализация приложения.

/index.php
48: $app = vB5_Frontend_Application::init("config.php"); ... 60: $routing = $app->getRouter(); 61: $method = $routing->getAction(); 62: $template = $routing->getTemplate(); 63: $class = $routing->getControllerClass();

Посмотрим на метод vB5_Frontend_Application::init .

/includes/vb5/frontend/application.php
13: class vB5_Frontend_Application extends vB5_ApplicationAbstract 14: { 15: public static function init($configFile) 16: { 17: parent::init($configFile); 18: 19: self::$instance = new vB5_Frontend_Application(); 20: self::$instance->router = new vB5_Frontend_Routing(); 21: self::$instance->router->setRoutes();

Здесь нас интересует метод setRoutes .

47: public function setRoutes() 48: { 49: $this->processQueryString(); ... 54: if (isset($_GET["routestring"])) 55: { 56: $path = $_GET["routestring"];

В переменную $path попадает значение юзердаты из параметра routestring . В него можно передать путь до страницы форума, и она будет загружена.



Допустим, мы передали /test .

После назначения переменной следует кусок кода, который избавляется от слеша в начале строки, если он присутствует.

/includes/vb5/frontend/routing.php
75: if (strlen($path) AND $path{0} == "/") 76: { 77: $path = substr($path, 1); // $path = "test" 78: }
includes\vb5\frontend\routing.php
83: if (strlen($path) > 2) 84: { 85: $ext = strtolower(substr($path, -4)) ; 86: if (($ext == ".gif") OR ($ext == ".png") OR ($ext == ".jpg") OR ($ext == ".css") 87: OR (strtolower(substr($path, -3)) == ".js")) 88: { 89: header("HTTP/1.0 404 Not Found"); 90: die(""); 91: } 92: }

Как видишь, проверка довольно странная. Как минимум смущает наличие зашитого прямо в код списка запрещенных расширений. Да и вообще сам факт, что расширение получают, вырезая четыре символа с конца строки (строка 85), вызывает недоумение. В общем, если мы пытаемся получить файл с расширениями gif, png, jsp, css или js, то сервер вернет страницу 404 и выполнение скрипта прекратится. Когда все проверки пройдены, с помощью callApi вызывается метод getRoute из класса vB_Api_Route . Он ищет подходящие роуты, исходя из переданной пользователем информации.

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «сайт», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score!

Если Вы держите свой форум, то рано или поздно приходится думать о защите Вашего форума - ведь злоумышленники не дремлют! В этом топике я (при помощи хабраюзера ReaM) собрал список советов по увеличению безопасности Вашего форума. Заинтересовало? Добро пожаловать под хабракат:)

Итак… Начнем:

1) Апдейтимся в самый конец своей линейки(3.5.х,3.6.х,3.7.х)

Описание: Без комментариев

Почему?: Jelsoft постоянно закрывает всплывшие уязвимости. Никому не хочется работать на прошлогоднем дырявом форуме, правда?

2) Переименовываем админку и модерку

Описание: Переименовываем админку, но в конфигурации ни в коем случае не пишем путь к нашей переименованной админке. Также переименовываем модерку, но её уже можно прописать в конфигурации(хотя тоже нежелательно), так как она менее уязвима. Смотрите сами:)

Почему?: Если переименовать админку и не указать путь в конфигурации, то будет гораздо сложнее её найти и следовательно применить XSS или еще что похуже. Есть минусы: - редактирование профиля и добавление модераторов перестанут работать без ручной правки ссылок.

3) Ставим.htaccess на админку:

Описание:
a) если ip статичен, то
order allow, deny
deny from all
allow from %ваш_IP%

B) Также ставим дополнительный пароль:

Почему?: Дополнительное паролирование админки никогда не помешает.

4) Удаляем файлы и папки:

Описание:
a) Удаляем файлы:
/validator.php(если имеется)
/checksum.md5(если имеется)
b) Удаляем папки:
/install/

Почему?: Небезопасные файлы от нулёных версий могут дать возможность просматривать список файлов, а также папка install очень вредная=)

5) Перемещаем вложения и аватары

B) Аватары -> Тип хранения изображений пользователя
Аватары должны храниться в базе данных

Почему? : Линейка 3.5, если мне не изменяет память, давала прямые ссылки на картинки - что при неправильной конфигурации хостинга, давало шанс залить шелл.

6)Выставляем права на папки

Описание: Если выполнен пункт 5, то теперь смело ставим права на папки custom_* 644, так как они нам теперь не нужны(или можете их удалить). Дальше, если Вы устанавливали vBulletin по инструкции, у вас все папке в / (корне) должны иметь права 644. Проверьте это, если не так, то выставите права 644.

Почему?: Затрудняем хакеру заливку шелла.

7) Нигде, никогда, никому не включаем опцию "Разрешить html".

Описание: Без комментариев. Зачем кому-то HTML?
Почему?: Возможность XSS атак при включенной функции.

8) Ставим.htaccess на папку includes

Описание : Ставим.htaccess на папку includes следующего содержания:

Order allow, deny
deny from all

Почему?:

  • если туда каким-либо образом зальют шелл, то не смогут зайти на него.
  • если вас будут ддосить, то возможен такой вариант, когда интерпретатор php отваливается и остается только апач - и апача разрешает уже читать файлы php - следовательно можно будет прочитать все файлы из папки /includes/ - тот же config.php, что не очень хорошо.

9) Пихните в директорию с файлами, на которых стоят атрибуты 0777 такой.htaccess:

kerk _http://vbsupport.org/forum/member.php?u=30

Описание:

RemoveHandler .phtml
RemoveHandler .php
RemoveHandler .php3
RemoveHandler .php4
RemoveHandler .php5
RemoveHandler .cgi
RemoveHandler .exe
RemoveHandler .pl
RemoveHandler .asp
RemoveHandler .aspx
RemoveHandler .shtml


Order allow,deny
Deny from all

Почему?: Скрипты с указанными расширениями более невозможно использовать в пределах директории с таким htaccess.

10) Отредактируйте config.php, впишите id администраторов в поле undeletable user(неудаляемые/неизменяемые пользователи).

Описание: /includes/config.php. Просто вписать id администраторов, после того когда внесли все необходимые изменения в профиль.
Почему?: Незачем лишний раз кому-то менять профили администраторов, даже им самим. Понадобится - удалят ID из файла, поменяют, вернут обратно. Безопасность - превыше всего! :)

11) После удаления модов/хаков не забывайте удалять файлы, которые Вы закачали вместе с ними.

Описание: Без комментариев
Почему?: А зачем вам на сервере лишние файлы? Незачем…

12) Никогда не сохраняйте бэкапы в пределах доступности веб-сервера.

Описание: Без комментариев
Почему?: Они будут доступны для скачивания любому, кто узнает имя бэкапа. Конечно, можно htaccess прикрутить, но все равно, безопасности ради, выносите бекапы за пределы доступности веб-сервера.

13) Установить плагин «Инспектор файлов».

Автор - Ghost (http://www.vbsupport.org/forum/member.php?u=38422)

Описание (цитата):

Лазая по своим старым скриптам, напоролся на этот продукт - Инспектор файлов. Это несколько модулей для vBulletin, при помощи которых можно сохранять в базе данных список существующих файлов и время от времени проверять, не изменились ли какие из них (для каждого файла сохраняется размер, владелец и права доступа) - встроенная cron-задача уведомит администратора по почте о найденных несоответствиях. Можно сохранять в БД несколько различных копий (ревизий) списков файлов для сравнения (автоматическая проверка с уведомлением на email сверяется только с последней ревизией). Внешний вид и доступные настройки можно посмотреть на скриншотах.

INSTALL: Для установки необходимо залить два PHP-файла из архива на сервер и импортировать продукт из файла «product-gfi.xml».

UPDATE: Обновление версий не предусмотрено, так что для установки новой рекомендуется сперва удалить предыдущую версию.

З.Ы. Продукт успешно работал на всех версиях от 3.6.8 до 3.8.1 включительно. Правда ссылка в выпадающее меню в панели навигации добавлялась в разные места, но это уже мелочи.


Скачать с vbsupport.org

Почему?: Незаменимая вещь в поиске шеллов на сайте, но ставить её необходимо заранее.

Итог:

Доступ к админке получить довольно сложно - следовательно залить шелл через админку тоже. Можно залить шелл через уязвимости vB, но если лить в /includes (там есть для некоторых хаков файлы, которые требуют 777), то у нас на папке includes стоит deny from all - шелл попросту не будет доступен извне!

На остальные папки можно ставить права 644, если проделали все пункты - тогда достаточно сложно будет залить, особенно при правильной настройке chroot. И наконец, мы добавили защиту от самих админов, которые лазают где не попадя, тем самым сажая себя на XSS"ки и трояны.

Собственно, на этом всё… Это первый мой топик на хабре, так что просьба сильно не пинать:)

UPD: Перенес в «Информационную безопасность».

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

Движок создаёт высокую нагрузку на сервер, особенно после установки дополнений и сторонних скриптов. Поэтому для нормальной работы придётся покупать нормальный хостинг — забудьте про бесплатные предложения и младшие тарифы за копейки, на которых тормозит даже сайт-визитка. Чем выше будет посещаемость, тем больше нагрузка на сервер, так что надо брать пропускную способность с запасом. Желательно — неограниченную.

Экономить на хостинге нельзя ещё и потому, что Vbulletin предназначен для создания крупных проектов. Движок устойчив к взлому и спам-атакам, поэтому посетители могут чувствовать себя в безопасности. Модератор понадобится, но не для очистки веток от рекламных постов, а для управления дискуссиями.

Для базовой настройки внешнего вида, добавления и изменения страниц можно использовать встроенный конструктор. Чтобы перейти в него, нужно авторизоваться на сайте под учётной записью администратора. Рядом с именем пользователя есть переключатель, который следует перевести в положение On. После повторного ввода пароля сайт откроется в режиме конструктора.

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

Для пользователей, которые не желают взаимодействовать с серверной инфраструктурой, разработчики предлагают решение vBulletin Cloud. С его помощью можно получить полностью работающий форум со всеми административными функциями, минуя этапы скачивания, установки и настройки движка. По сути, после покупки тарифа вам остаётся только кастомизировать сайт под свои нужды, прежде чем запускать на него посетителей.

Дизайн

На официальном сайте движка можно скачать темы для базового дизайна. Они легко устанавливаются на сайт и могут быть изменены в соответствии с пожеланиями веб-мастера. Для управления стилями в административной панели есть раздел Advertising. В нём можно:

  • Изменить или добавить фон сайта.
  • Добавить изображение вместо фона.
  • Отредактировать файл стиля.

Базовые изменения можно выполнить через конструктор. Например, чтобы изменить лого, нужно открыть вкладку Header и загрузить подходящий файл. На вкладке Navigation Bar можно управлять главным меню сайта: добавлять и удалять ссылки на другие страницы, менять порядок их расположения, назначать имена.

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

Поисковая оптимизация (SEO)

На CMS vBulletin нет специального модуля для проведения поисковой оптимизации. Однако это не значит, что над форумом не нужно работать. К сайтам применимы требования об обязательном наличии тега H1, по которому роботу определяют тему страницы. Для настройки индексации нужно редактировать файл robots.txt - советы по его правильному оформлению можно найти на форумах, посвящённых сайтам на vBulletin.

Поисковая оптимизация движка во многом завязана на включении или выключении отдельных функций. Например, необходимо отключать меню быстрого перехода для экономии кода. Таких мелочей очень много, узнать их можно только на специализированных форумах - в справке vBulletin ничего подобного нет.

Для добавления новых возможностей доступны плагины SEO. Самый известный - VBSEO. С его помощью можно оптимизировать форум под требования поисковых систем: настроить редиректы, убрать дубли, исключить из индексации отдельные страницы. Главный недостаток - VBSEO создаёт дополнительную нагрузку на сервер, которая у CMS и так немаленькая.

Тарифы

Пожизненная лицензия с обновлениями на год обойдётся в 250 долларов. За эти деньги доступны все возможности движка:

  • Встроенные приложения: форум, группы, опросы, блог.
  • Инструменты поисковой оптимизации.
  • Профессиональная поддержка.
  • Гибкие настройки интерфейса.
  • Контрольные панели для всех участников: администратора, модератора, пользователя.
  • Инструменты управления пользователями.

250 долларов — не окончательная цена. За эти деньги вы приобретаете только право пожизненного использования движка.

  • Чтобы продолжить получать обновления, необходимо каждый год платить 209 долларов. Разработчики предлагают также платные аддоны:
  • Удаление брендинга в нижнем колонтитуле на всём сайте — разовая оплата 169 долларов.
  • Дополнительная поддержка по телефону или тикетам — 49 долларов в месяц или 329 долларов в год.
  • Профессиональная установка или обновление движка — разовая оплата 149 долларов.

Если вы хотите, чтобы форум хорошо выглядел на небольших экранах, можно купить «Мобильный пакет». Лицензия обойдётся в 399 долларов, а продление обновлений — 359 долларов ежегодно. Отдельно мобильная версия стоит 199 долларов. Без неё форумом нормально можно пользоваться только на компьютере.

При выборе vBulletin Cloud доступно три тарифа: Bronze, Silver и Gold. Все они предлагают:

  • Автоматическое обновление до актуальной версии системы.
  • Использование серверов, оптимизированных под vBulletin.
  • Изменение доступного объёма на диске в соответствии с вашими потребностями.
  • Автоматическое создание резервных копий.

Минимальный тариф обойдётся в 19,95 долларов в месяц (14,99 долларов при оплате за год). Он предлагает пропускную способность 25 Гб, бесплатную поддержку и домен в подарок. Это отличное решение для небольших форумов с невысоким трафиком.

Silver стоит уже 39,95 долларов в месяц (29,99 долларов при оплате за год) и даёт 75 Гб пропускной способности, а также поддержку через систему тикетов. Этот тариф подходит для растущих сообществ со средним трафиком.

Максимальный тариф - Gold за 74,95 долларов в месяц (59,99 долларов при оплате за год). Пропускная способность 200 Гб, бесплатная поддержка по телефону. Оптимальное решение для крупных форумов.

Достоинства и недостатки

VBulletin работает очень давно, поэтому у него развитое сообщество пользователей, подробная документация и много сопутствующих материалов: тем, шаблонов, расширений. Среди других достоинств отметим:

  • Большое количество тем оформления.
  • Возможность расширения функциональности путём установки плагинов и модулей, которых уже больше 1000.
  • Простые инструменты для создания контента и управления сайтом.
  • Упрощённая настройка дизайна.
  • Быстрая публикация пользователями фото и видео.
  • Оптимизация под мобильные устройства при покупке соответствующего пакета.

Если вы до этого использовали другой форумный движок, то долго будете привыкать к административной панели VBulletin. Она не плохая — просто необычная и в некоторых моментах неудобная.

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

После смены команды разработчиков много вопросов возникает и к безопасности движка. Самой стабильной версией остаётся 3.8. Четвёртая и пятая версии постоянно получают обновления безопасности, которые говорят о том, что разработчики латают дыры уже после выпуска продукта.

Есть в моем ведении несколько VPSов, на которых крутится… вообщем не моя зона ответственности, и потому крутится там то что крутится, в меру тормозит, в меру работает. И оказалось, что крутится на одном из них некий форум, и начал форум притормаживать. И захотелось разобраться…

Исхдные
  • Форум под vBulletin 3.8.x
  • Вынесен на поддомен forum.domain.com
  • Nginx 1.1.13, php 5.3.x (fpm)
  • Кроме форума на этом сервере ничего не крутится. (это важно ).
  • Mysql на отдельном сервере, коммуникация через TCP/IP.
Предыстория
Жил себе форум, не тужил, показывал по xm top нагрузку в районе 30-40 процентов. А затем наступил час «Х» и нагрузка подскочила до ровной полки в 90 процентов с пиками выше, что, вообщем-то, не есть гуд. Подозрение на DDOS не подтвердилось. По логам наблюдалась обычная рабочая нагрузка. Ну а перед тем как тупо наращивать ресурсы возникла идея разобраться в происходящем и попытаться закэшировать все что можно.
Расследование. Часть первая - чего хочет женщина посетитель
Так как с идеологией и особенностями данной софтины я знаком не был, то начал изучение проблемы с анализа логов и траффика между посетителями и сервером. Первым делом я с удивлением обнаружил, что аттачи к сообщениям в форуме отдаются исключительно скриптом attachment.php , при этом сами файлы могут храниться в базе, могут на локальном диске, но отдача - только через скрипт. И никак иначе. То есть получаем по 8-10 лишних дерганий php-интерпретатора на ветвь сообщений с 8-10 фотографиями. И это для каждого посетителя. Так как на этом форуме для просмотра аттачей не требуется регистрация, то аттачи можно закэшировать, допустим, на пару дней. Примерно вот так:
location = /attachment.php { expires max; limit_req zone=lim_req_1s_zone burst=5; fastcgi_pass forum__php_cluster; include /etc/nginx/fastcgi_params; include /etc/nginx/fastcgi_params_php-fpm; fastcgi_cache forum_att__cache; fastcgi_ignore_headers Cache-Control Expires Set-Cookie; fastcgi_hide_header Set-Cookie; fastcgi_hide_header Pragma; fastcgi_cache_key "$request_method:$http_if_modified_since:$http_if_none_match:$host:$request_uri:"; fastcgi_cache_use_stale updating error timeout invalid_header http_500; fastcgi_cache_lock on; fastcgi_cache_lock_timeout 2m; fastcgi_cache_valid 2d; } и где-ньть в http-секци объявим forum_att__cache: fastcgi_cache_path /var/cache/nginx/att levels=1:2 keys_zone=forum_att__cache:4m max_size=2g inactive=2d;

Вторым «откровением» для меня было то, что на форуме есть архивы, и они не просто существуют, а практически половина запросов приходится именно на них. Внешний вид страниц также позволяет закэшировать их содержимое:
location /archive/ { expires 10d; limit_req zone=lim_req_1s_zone burst=2; location ~ \.css$ { expires max; } fastcgi_pass forum__php_cluster; fastcgi_index index.php; include /etc/nginx/fastcgi_params; include /etc/nginx/fastcgi_params_php-fpm; fastcgi_param SCRIPT_FILENAME $document_root/archive/index.php; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_cache forum_arc__cache; fastcgi_hide_header Set-Cookie; fastcgi_ignore_headers Cache-Control Expires Set-Cookie; fastcgi_cache_key "$request_method:$http_if_modified_since:$http_if_none_match:$host:$request_uri:"; fastcgi_cache_use_stale updating error timeout invalid_header http_500; fastcgi_cache_valid 2d; } и в http-секцию: fastcgi_cache_path /var/cache/nginx/arc levels=1:2 keys_zone=forum_arc__cache:4m max_size=2g inactive=2d; Заодно подстрахуемся от DDOS-атак: limit_req_zone "$psUID" zone=lim_req_1s_zone:2m rate=1r/s;
О формировании ключа "$psUID" я поведаю далее.

Расследование. Часть вторая - авторизация в vBulletin
С точки зрения посетителя форума зашедший может быть либо зарегистрированным пользователем, либо гостем. Но совсем другая ситуация складывается, если мы пронаблюдаем ситуацию «пришел, походил, залогинился, походил, отлогинился, походил» с точки зрения появления и исчезновения кук в браузере. Итак, очищаем куки для домена и его поддоменов, открываем HTTPfox и наблюдаем что происходит:
HTTP/1.1 200 OK Set-Cookie: PHPSESSID=cdme9rrptft67tbo97p4t1cua5; expires=Wed, 22-Feb-2012 15:04:12 GMT; path=/; domain=.domain.com Set-Cookie: bblastvisit=1329059052; expires=Mon, 11-Feb-2013 15:04:12 GMT; path=/; domain=.domain.com Set-Cookie: bblastactivity=0; expires=Mon, 11-Feb-2013 15:04:12 GMT; path=/; domain=.domain.com Set-Cookie: uid=XCuiGU831OyC8VLqAx/QAg==; expires=Thu, 31-Dec-37 23:55:55 GMT; domain=.domain.com; path=/
С uid и PHPSESSID все понятно - это происки nginx"a и php-интерпретатора с установленной опцией session.auto_start , а вот остальные - следилки за активностью на форуме. А вот главной сессионной куки vBulletin пока не наблюдается. Забегая вперед скажу, что vBulletin не использует стандартную php-вую сессию (точнее ПОЧТИ не использует), а ведет свою, идентификатор которой хранит в куке bbsessionhash . Итак, пользователь зашел, а сессии нет - то есть он аноним без сессии. При этом ссылки на форум далее могут иметь два вида (имеются ввиду все ссылки на странице, а не одна так, а другая эдак):
forum.domain.com/forumdisplay.php?s=12b66e447be52ebc84ab16d3f39626fb&f=69
forum.domain.com/forumdisplay.php?f=69
И если пройти по ссылке первого типа, то следующим ответом от форума придет кука сессии, а если по ссылке второго - нет. Если со вторым ответом кука от сессии не пришла то по форуму можно так и бродить безсессионным и неприкаянным пока не нарвешься на ссылку первого типа (закономерность их появления у меня выявить не получилось), или захочешь залогиниться. При успешном логине кука сессии придет по-любому. Если до логина гость был анонимом-с-сессией, то сессию ему заменят. Выглядит это так:
HTTP/1.1 200 OK Set-Cookie: bbsessionhash=85745bc6110db5221e159087bf037f24; path=/; domain=.domain.com; HttpOnly
После логина сессия «стабильна» и чехарды с ссылками не происходит. Процедура логаута оригинальностью не отличается - удаляются все существующие форумные куки (даже те, которые не были проставлены) и пишется кука новой («анонимной») сессии:
HTTP/1.1 200 OK Set-Cookie: bbsessionhash=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.domain.com Set-Cookie: bblastvisit=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.domain.com Set-Cookie: bblastactivity=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.domain.com Set-Cookie: bbthread_lastview=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.domain.com Set-Cookie: bbreferrerid=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.domain.com Set-Cookie: bbuserid=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.domain.com Set-Cookie: bbpassword=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.domain.com Set-Cookie: bbthreadedmode=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.domain.com Set-Cookie: bbstyleid=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.domain.com Set-Cookie: bblanguageid=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.domain.com Set-Cookie: bbsessionhash=3d0bdc5dbe8dabae361deebe8f6048d2; path=/; domain=.domain.com; HttpOnly
То есть на выходе мы получаем анонима (гостя), но стопроцентно имеющего сессию.
В итоге с точки зрения форумного софта И HTTP-заголовков мы имеем три типа пользователей: гость без сессии , гость с сессией , залогиненный посетитель . Причем на уровне nginx"a отличать вторых от третьих крайне проблематично.

Теперь, поняв какие куки и как курсируют между посетителем и сервером, можно подойти к вопросу кэширования динамического контента. Как известно, функционал кэширования ответов fastcgi-бэкенда в nginx встроен в модуль ngx_http_fastcgi_module . Для этого надо прописать глобально в http-секции зону кэширования, а в нужном location"e - ключ. И если для условно-статического контента (изображения, архивы) ключем для кэширования мог считаться URI с незначительными дополнениями, то для кэширования динамики нужно учитывать еще и юзера. Казалось-бы правило типа
fastcgi_cache_key "$request_method:$http_if_modified_since:$http_if_none_match:$host:$request_uri:$cookie_bbsessionhash:";
могло бы удовлетворить и гостей и залогиненных пользователей, однако на практике посетители начали получать содержимое чужого кэша. Кэширование «истиной» динамики пришлось отключить. Надеюсь приговор не окончателен.

Однако данная информация не бесполезна. На ее основе мы можем генерить ключ для ограничения частоты запросов основываясь не только на IP адресе посетителя, но и на его статусе.
set $psUID "anon"; set $psUCL "anon"; if ($cookie_bbsessionhash) { set $psUID "$cookie_bbsessionhash"; set $psUCL "user"; } if ($psUCL = "anon") { set $psUID "anon:$remote_addr"; }
Данный фрагмент конфига размещаем в секции server конфига nginx до описания всех location. В итоге мы получаем оригинальный ключ на пользователя имеющего сессию и ключ основанный на IP адресе для посетителей сессии не имеющих (например для поисковый краулеров).

Результаты
В результате предпринятых усилий общая нагрузка на виртуалку снизилась с полки на 90 процентов до пилы на 40 с всплесками до 80 процентов.