Миниатюры чата обходят s3_cdn_url и используют прямые URL-адреса S3-бакетов

, ,

Я недавно настроил бакет для загрузки в Cloudflare R2, и миниатюры изображений в чате перестали отображаться. Я провёл расследование, быстро исправил конфигурацию и наткнулся на эту тему: Cloudflare R2 Image URL Display Issue: Detailed Explanation and Fix. В итоге я изучил другие конфигурации бакетов для загрузки в S3 и понял, что проблема не специфична для Cloudflare.


Описание

Когда для загрузки настроено внешнее хранилище S3 или совместимое с ним, миниатюры изображений в чате обходят CDN и загружаются напрямую по URL бакета.

Для защищённых внешних бакетов, совместимых с S3 (например, Cloudflare R2), миниатюры в чате ломаются и не отображаются.

Суть проблемы заключается в том, что сериализатор чата не применяет настройку s3_cdn_url к миниатюрам. Вместо того чтобы перенаправлять изображение через настроенный CDN, он передаёт в полезную нагрузку браузера «сырой» внутренний URL бакета S3.

Шаги для воспроизведения

Это можно воспроизвести на Meta и других сайтах, использующих бакеты для загрузки в S3:

  1. Опубликуйте изображение в чате или канале.
  2. Проверьте URL миниатюры изображения в консоли.
  3. Нажмите на изображение, чтобы открыть оригинал большего размера, и проверьте URL.
  4. Сравните его с URL миниатюры.

Вот пример из чата Meta:

URL миниатюры: напрямую из бакета

https://cdck-file-uploads-global.s3.dualstack.us-west-2.amazonaws.com/meta/optimized/4X/4/7/9/479815360e0e6e0cd9f4ba565891776e84aea532_2_375x500.jpeg

URL оригинала: через CDN

https://global.discourse-cdn.com/meta/original/4X/4/7/9/479815360e0e6e0cd9f4ba565891776e84aea532.jpeg

В консоли HTML для миниатюры <img... содержит атрибут data-large-src с URL CDN CloudFront, а атрибут src — URL бакета AWS.

скриншот

Влияние:

  • Для хранилищ, совместимых с S3 (например, Cloudflare R2), которые по умолчанию защищены и блокируют неаутентифицированный доступ к конечным точкам сырых бакетов, миниатюры изображений в чате (оптимизированные) не работают.
  • Утечка трафика (и денег) для AWS и других хранилищ, совместимых с S3, которые позволяют доступ к конечным точкам сырых бакетов, так как чат полностью обходит CDN; это приводит к оплате прямых сборов за исходящий трафик S3 за весь трафик миниатюр чата.
  • Утечка инфраструктуры: «сырые» URL бэкенд-хранилищ (включая внутренние имена бакетов, а иногда и идентификаторы аккаунтов) раскрываются в полезных нагрузках JSON на стороне клиента.

PR:

Я подготовил PR для исправления этой проблемы здесь:

Похоже, что Сэм добавил метод getURLWithCDN в предпросмотр композера чата — однако, я не уверен, что он работает в потоке чата?

Мне интересно, могло ли исправление в композере не работать для некоторых конфигураций S3 из-за того, что getURLWithCDN падает при несовпадении протоколов (// против https://)? В любом случае, вышеуказанный PR просто расширяет работу Сэма, добавляя обёртки для потока и делая решение независимым от протокола.

Временное решение:

Прежде чем я понял, что проблема не только в Cloudflare, я создал лёгкий компонент темы. Он перехватывает «сырые» домены S3 в DOM чата и заменяет их на правильный домен CDN до того, как браузер попытается загрузить их. Это правильно маршрутизирует трафик и устраняет утечку трафика. Я адаптировал его для работы с любым хранилищем, совместимым с S3. Достаточно всего двух настроек: Raw S3 bucket URL (Сырой URL бакета S3) и S3 CDN URL (URL CDN S3).

(не знаю, почему однобоковые ссылки GitHub здесь не работают) Исправлено сейчас

2 лайка

Скорее всего, связано с переездом сайта… Я только что перекомпилировал.

1 лайк