Pull to refresh

Comments 33

А не боитесь, что кто-то устроит перебор GET /yPkjPk_200x200.gif, GET /yPkjPk_200x201.gif, GET /yPkjPk_200x202.gif,… и или забъет кэш, что место на диске закончится или процессор устанет конверитирования выпонять?
Боюсь :)
Считаю, это не ответственность сервиса, нужно делать защиту на уровне веб-сервера, разрешая или запрещая определенные URI.
Так сервер можно положить только допустимыми URI — заставить его генерить все допустимые размеры для всех элементов. Если элементов немного, то это не проблема, но тогда и функционал такой не нужен. Если же элементов много, то над сервером можно круто поизмываться.
Не понял. Если разрешить, например, с десяток размеров изображений, то остальные генерироваться не будут. Проблема решена. Или нет?
А все разрешенные размеры для всех хранимых документов правда нужны, это штатная работа сервиса, после генерации они будут отдаваться как статический контент.
Не совсем штатная.
Как я понимаю цели сервиса:
допустим, есть у нас фотохостинг. Он предусматривает для каждого изображения, скажем, 10 разных размеров. Из них 2-3 являются востребованными, а остальные 7-8 являются экзотикой, которая далеко не для каждого изображения будет востребована (а значит и создана). Почему я считаю что это будет именно так? Потому что в противном случае имело бы смысл генерировать все размеры еще при загрузке оригинала. Так же мы экономим ресурсы и создаем нужные размеры только когда (если) в них возникнет необходимость. По сути, технология нам позволяет сократить занимаемое место до X*0.3, где X — полный объем всех возможных изображений.

Что делает злоумышленник? А делает он очень просто — запрашивает все возможные размеры для каждого изображения. В результате сервис изображений должен в стрессовом режиме создать и разместить 0,7*Х гигабайт изображений. Более того, даже если предположить что он выдержит этот стресс-тест, потом он должен будет хранить эти никем невостребованные Х гигабайт, вместо того чтобы хранить всего 0,3*Х.

Собственно, я не утверждаю что сама концепция изображений по запросу плохая, но хотелось бы какого-то решения как раз на вышеописанный случай…
Теперь понял.
У нас другая специфика. Если 100500 клиентов с документами. Мы их показываем на страницах сайта. И вдруг однажды у проекта меняется дизайн. Например лого компании на странице деталей теперь другого размера. Дизайнер меняет URI картинки — у вуаля! Проблемы нет.
А дискового места нам не жалко :)
Собственно, вы ушли от ответа.
Так нет решения, предлагайте pull request :) Я просто рассказал как у нас дела.

Если придумывать на ходу, я бы сделал какой-нибудь сборщик мусора, если правда памяти жалко.
>Так нет решения, предлагайте pull request :)
Если бы у меня был правильный ответ — я бы не спрашивал, а с умным видом поучал как надо делать:)
К сожалению, ресайз картинки — это медленная процедура, а уж если добавить sharp, чтобы она выглядела получше… Мы пробовали на, кажется, 4-процессорном E5-2660 ресайзить картинки размера 1200х1200 вниз, с помощью imagemagick. Просто ресайз занимал порядка 100мс, ресайз с шарпом — уже больше 300мс.

С учётом того, сколько стоит процессор, а сколько диски — выгоднее сразу поресайзить на все размеры и их хранить. С коэффициентом 0.3 вы не совсем правы — если это фотохостинг, то надо оригиналы хранить, или хотя бы хайрез картинки. Оригинал современных мыльниц от 5мб, средний размер приближается к 10мб, ресайзы 1200х1200 и ниже в сумме (штук 7-10 размеров) меньше 2 мегабайт займут, а то и всего 1 мегабайт.
Если не ошибаюсь, можно решить подобное следующим способом:
1. Названия/урлы изображений делать рандомными, хранить в базе.
2. При запросе изображения, веб-сервер проверяет наличие изображения в директории. Находит — отдает, нет — передает управление скрипту для подготовки изображения.
3. Раз в день/неделю/месяц удалять редко запрашиваемые изображения.

Три шага вроде решают описанную проблему. Возникает только одна проблема — ручками изображение вставить в страницу будет сложно. Но, по мне, это скорее плюс.
А есть защита от DDoS? В своё время хотел сделать тоже самое, но решил, что будет слишком легко положить сервер отправкой кучей запросов на изменение размеров изображений, например.
Как уже сказал выше, защита от DDoS должна быть на уровне веб-сервера.
А что считать DDoS в случае такого сервиса? Вариант если только новые картинки вылетают по таймауту, а старые выдаются как статика уже ддос?
Как уже написали выше, злоумышленник может найти картинки побольше и начать их активно запрашивать в разных размерах, что вызовет нагрузку на процессор нехилую. Или тоже самое с переконвертированием видео, через имеющийся плагин. Единственный видимый вариант — ограничить список размеров до статического (например, только 50х50 и 100х100, все остальные запросы считать невалидными) — но тогда смысл проекта, имхо, немного теряется.
Следует не забывать, что приложение — штука меняющаяся во времени. Это очень ценно, когда мы имеем оригиналы загруженных пользователями данных, чтобы легко менять то, как мы их показываем в новых версиях.
Ну так это можно делать средствами самого приложения — для rails, например, что paperclip, что carrierwave умеют прозрачно для пользователя генерировать из загруженного изображения несколько с разными размерами, без выставления уязвимых веб-сервисов наружу.
Да, это другой подход для решения той же проблемы. Либо выполняете эту работу для всего контента разом при обновлении проекта, либо в процессе работы по мене необходимости. Разве вы не видите, что в обоих случаях вы потратите одинаковое количество ресурсов?
Просто нагрузка на ддос не тянет. Если, грубо говоря, nginx будет справляться с отдачей полноразмерных и уже обработанных картинок, то можно ли считать такую атаку удачной?

В общем, когда я думал над подобной системой, то пришел примерно к такой архитектуре:
— веб сервер проверяет есть ли точно запрошенный формат в кэше, если есть отдает (тут никакой новой опасности)
— запрос идет в приложение, оно отправляет задание на ресайз в независимую от контекста запроса очередь и делает временный редирект на оригинал, что-то более подходящее по формату или временную заглушку (тут нагрузка не сильно большая чем на «хелло ворлд» средствами php).
— демон очереди тупо шарит по заданиям на ресайз c минимальным приоритетом, объединяя одинаковые. Или это вообще скрипт по хрону. Количество процессов ресайза ограничено сверху.

По задумке сереверу конечно поплохеет, но ляжет он много позже чем при синхронном ресайзе, а пока не ляжет будет быстро отдавать то, что нужно на старых картинках, и чуть медленнее не совсем то, что нужно. А на обработку очереди можно вообще повесить целый кластер, в том числе и по получению админом аларма от мониторинга. Веб-часть от ресайза не зависит почти.
— запрос идет в приложение, оно отправляет задание на ресайз в независимую от контекста запроса очередь и делает временный редирект на оригинал, что-то более подходящее по формату или временную заглушку (тут нагрузка не сильно большая чем на «хелло ворлд» средствами php).

Это очень важный момент, который, как я понял, в представленном проекте не учитывается.
Да, такого протокола нет.
Это просто размышления на тему защиты от DoS подобных сервисов без особой потери функциональности. В принципе ещё можно совместить синхронную и асинхронную модель: если ответа долго нет (или очередь большая или еще как по косвенным признакам оцениваем, что ответа долго не будет)), то выдаем редирект на оригинал или заглушку. Но тут надо экспериментировать, а в предложенном изначально варианте (полностью асинхронном) прототип довольно быстро сделать должно быть, используя хотя бы встроенные в php очереди.
а интеграции с tinymce нету? удобно было бы, заливать медиа информацию на отдельный сервис
Нет, но хорошая идея. Думаю, было бы удобно тем, кто tinymce использует. Я еще помню боль от подключения к нему плагинов для аплоада картинок. Конечно, это должно быть сделано со стороны tinymce а не barberry.
UFO just landed and posted this here
Видео тоже на ходу можно конвертировать? Не сильно ли это накладно?
Ух ты, правда давно, первый коммит 2007 года. А где можно найти документацию?
По поводу разрешенных форматов, имхо, дельное замечание. Я бы сделал что-то типа того:
* Ввести группы, каждый файл цепляется на группу (например «documents»)
* Для группы задаются доступные форматы (в будущем можно и другие настройки цеплять)
* При запросе проверять доступен ли формат
* Урлы сделать с группой (/documents/yPkjPk.jpg), дабы на вебсервере можно было просто сделать такое же ограничение по формату
* Настройки для вебсервера можно генерить прям апликейшеном.

Что касается кэширования, то как раз это лучше перенести на вебсервер. На nginx можно сделать простейшую схему с try_files и X-Accel-Redirect, полностью исключив отдачу файлом непосредственно апликейшеном — только генерация.
Идея про кеширование мне нравится. Нужно только понять, получится ли метод DELETE в этом случае (нужно удалить кеш и передать управление сервису, чтобы он удалил документ).
А я уже во втором проекте использую для этих целей UploadCare, опыт оч. положительный.
Sign up to leave a comment.

Articles