Защита от горячих ссылок для прокси и CDN аватаров

Мой сайт на Discourse насыщен изображениями. Из-за большого количества изображений я использую связку S3/CDN для их хранения и доставки. В рамках CDN я применяю различные меры для предотвращения перехвата изображений. Одна из таких мер — блокировка прямого доступа к картинкам, разрешая доступ только с определённого списка хостов.

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

Причина в том, что Discourse использует прокси-настройку для аватаров. В HTML используется прокси-ссылка для аватаров. Структура ссылки выглядит так: https://discourse.forum/user_avatar/discourse.forums/username/24/616_2.png.
После разрешения прокси браузер пытается получить прямой доступ к файлу изображения.

Мой CDN блокирует прямой доступ кодом 403 при таком запросе. В результате все пользовательские аватары отображаются в виде силуэтов.

Какие у нас есть варианты для отключения прокси?
Можно ли изменить структуру файла аватара на стандартную?

Не могли бы вы добавить IP-адрес вашего Discourse в белый список?

Прямой вызов ссылки доступа поступает с IP-адреса пользователя. Сервер обрабатывает информацию, но сам вызов выполняется локальным браузером.

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

Я ненавижу размытые вопросы. Что вы имели в виду, когда спрашивали про «это»?

Вот мои текущие настройки:

Настройка Discourse:

  • Стандартная установка в одном контейнере
  • Настроено как поддомен: forums.domain.tld
  • Стандартная настройка S3 для загрузок
  • Загрузки сохраняются в S3

Настройка S3:

  • Ведро S3 от Digital Ocean
  • Ведро включено для внешнего доступа
  • Никаких других уровней безопасности или разрешений

Настройка CDN:

  • bunny CDN
  • Настроены разрешённые рефереры: domain.tld и *.domain.tld
  • Переключатель, который заблокировал доступ к аватарам, назывался «Блокировать прямой доступ к файлам по URL».

Когда он включён, все аватары возвращают ошибку 403. Когда выключен — аватары отображаются.

Изображения, не являющиеся аватарами:

  • URL в Discourse: https://cdn.domain.tld/optimized/3X/3/1/filename_#_size.jpeg

Изображения аватаров:

  • URL в Discourse: https://forums.domain.tld/user_avatar/forums.domain.tld/mazzini/48/776_2.png

В предыдущем посте Как хранятся и доступны аватары? указывается, что Discourse использует прокси для аватаров. Следовательно, структура URL для аватаров не является стандартной структурой URL изображений.

В моей системе аватары доступны либо из S3, либо из CDN. Это означает, что где-то и каким-то образом URL аватара преобразуется в URL CDN.

Когда это происходит, CDN считает URL прямой ссылкой и блокирует доступ с ошибкой 403.

Надеюсь, я ответил на вопрос про «это»?

А я ненавижу, когда люди отвечают так, когда я трачу своё время на помощь им, так что это ничья :wink:.

Да, и «прокси» означает, что запрос проходит через Discourse. Запрос отправляется не браузером в CDN, а самим Discourse.

Вы настроили CDN как полный CDN сайта или как S3 CDN? Я подозреваю, что второе. В таком случае запрос отправляется Discourse в CDN без реферера. Но CDN всё равно может распознать, что это легитимный запрос, поскольку он исходит из IP-адреса Discourse. Поэтому я советую добавить его в белый список.

Редактирование: вы можете проверить это, отключив защиту на короткое время и посмотрев логи в Bunny, чтобы увидеть, с каких IP-адресов они поступают.

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

CDN настроен только для бакета S3.

Я проверил логи CDN для IP-адреса Discourse, связанного с ошибками 403, ещё до создания первоначальной темы. В файлах логов его не было.

Исходя из ваших комментариев, я вернулся и повторно проанализировал логи. После изучения IP-адресов с наибольшим количеством запросов я обнаружил, что первые несколько принадлежат шлюзам хостинг-провайдера.

Проблема в том, что я не хочу постоянно отслеживать IP-адреса шлюзов Digital Ocean, чтобы мой сервер Discourse мог корректно отображать изображения.

Спасибо за помощь.