Каждый более или менее крупный сайт хоть раз, но пытались атаковать. Такое было и с нашим сервисом Rusprofile, люди пытались спарсить финансовые и юридические данные о компаниях, которые мы агрегируем у себя последние 5 лет. Поэтому наша команда написала неплохую систему защиты с несколькими эшелонами проверок. В этот Новый год случилась DDoS-атака, которую наша система смогла отбить меньше чем за час. Сегодня расскажем, почему другим нужны ваши данные и можно ли защититься от подобных атак (спойлер: можно).
Мы в Rusprofile занимаемся тем, что собираем в различных источниках данные обо всех компаниях в России и выводим их в удобном интерфейсе. Сервисом регулярно пользуются сотрудники отделов закупок, бухгалтеры, юристы и все, кому нужно узнать о какой-либо фирме сразу всё, в одном месте. К сожалению, наличие большого количества тщательно собранного контента (а мы обновляем базу ежедневно) привлекает желающих это украсть.
Зачем кому-то воровать контент и почему просто нельзя сделать свою базу данных
До этого года у нас была простая модель монетизации. Вся прибыль шла от рекламы, а трафик — из поисковых систем. Более 4 лет мы показывали все данные бесплатно, открыто и полностью. И разумеется, были желающие эти данные получить в готовом виде, чтобы сделать подобную систему и тоже зарабатывать на рекламе. Проще скопировать, чем самим собирать данные из десятков источников, анализировать, сопоставлять и разбирать. Не будем раскрывать имён, но все попытки забрать контент были исключительно ради денег. Даже самое простое проксирование сайта могло дать человеку заработать немного на трафике, который должен идти к нам. Некоторые одновременно проксировали сайт и пытались спарсить данные, а иногда даже копировали наш дизайн. Порой воры были более изобретательны, и хотя бы сайт делали свой. Сейчас практически все эти сайты мертвы.
Основная причина для атак и попыток скопировать всё — это контент. Бесплатная дата, которую можно отдавать аудитории и зарабатывать деньги на рекламе. На самом деле, мы бы не узнали о большинстве попыток (даже успешных) скопировать сайт, но это мешает, т.к. нагрузка вырастает аномально. Люди пытаются вытащить всё и сразу, накидываются в сотни потоков, и, соответственно, начинают страдать наши пользователи. Сайт тормозит и не успевает обрабатывать и реальные запросы, и попытки скопировать все его страницы, которых более 100 миллионов на текущий день.
К сожалению, защититься в полной мере, чтобы вообще никто и ничего не смог скачать с сайта, практически невозможно. Но можно сделать этот процесс невыгодным для злоумышленников. У нас ушёл год исследований и улучшений систем, чтобы закрыть возможность парсить нашу базу целиком. Это помогло избавиться от нескольких зеркальных проектов, которые зарабатывали на нашем труде.
"Но ведь можно взять все источники и точно так же скачать оттуда данные?" резонно спросите вы. Конечно, можно. Более того, мы и не скрываем, откуда берём информацию. Любой может на сайте зайти в раздел Источники данных и увидеть, где мы всё собираем. Их там около полусотни. К сожалению, для любителей быстрого заработка, недостаточно просто знать эти источники. Мы провели много времени, чтобы правильно настроить интеграции, разбор и обработку данных. И в пересчёте на стоимость человеко-часов, конечно, это уже миллионы рублей. Поэтому никому не интересно строить подобную систему, проще украсть уже готовые структурированные данные и перепродать их.
Fail2ban — первый шаг, чтобы отсечь мошенников
Когда нагрузка на проект от ботов стала большой, возникла задача отсечь их. Как вообще работает парсер? Самый простой вариант — пишется какой-то простенький скрипт, который дёргает страницы и каким-то образом их разбирает, но это уже не наше дело. Нас волнует только то, что кто-то постоянно стучится в наш сервер. В этом случае мы видим массу запросов с одного IP-адреса и, естественно, можем это элементарно ликвидировать. Просто баним этот IP, используя автоматизированное решение.
К сожалению, количество таких парсеров обратно пропорционально сложности решения. Значит, львиную долю нежелательных запросов создают странные люди, которые просто запускают скрипт на своём компьютере. Были даже автоматизированные решения, которые продавались на форумах. Они умели сразу работать с Excel, куда складывались данные. Естественно, у этих парсеров был IP компьютера, на котором запускался этот скрипт, ну а дальше уже всё понятно.
Первое, что мы сделали — начали отключать около 80% script kiddies. Просто банили по IP тех, кто слишком много хотел. Это классическая схема, техническое решение давно известно: Fail2ban, который анализирует логи и при превышении определённого порога запросов за определённое время IP-адрес улетает в бан. Большая часть доморощенных хакеров отвалилась, но были те, кто пошёл дальше. Они стали заходить не с одного IP адреса, а через наборы прокси — 1000, 10000, 100000 — и дёргать нас с каждого адреса по чуть-чуть. Дальше нужно было решать проблему иначе.
Как ограничить парсинг, не усложняя жизнь пользователям
Одно из самых важных свойств Rusprofile — обновление. Дело в том, что данные об организациях постоянно меняются. Кто-то закрывается, кто-то открывается, меняются реквизиты, учредители, юридический адрес. Регулярно проходят тендеры, суды и прочее. И ценность в том, чтобы предоставлять только актуальные данные. Объем обновления огромный. За сутки собираются несколько десятков гигабайт. Затем это обрабатывается и в более компактном виде хранится уже в нашей базе. И на следующий день всё заново. Поэтому сперва мы решили разрешить нас парсить, но… с такой скоростью, чтобы не успевать за обновлениями. То есть, данные у злоумышленников были неактуальными, а значит, ценности не представляли. Как только скорость парсинга падает меньше скорости, с которой мы обновляем данные, для бизнеса (если воровство контента можно назвать бизнесом) это становится бессмысленно, т.к. данные всегда будут устаревшие.
Мы стали применять для этого поведенческий анализ. У реального пользователя есть определённый профиль запросов (как и что он делает, насколько часто). Конечно, активность варьируется в широких пределах. Иногда бывают люди, которые работают в нескольких окнах, открывают ссылки десятками. Но мы видим, откуда человек пришёл, понимаем, что он мог нажать на несколько ссылок из поиска и открыть их в новых вкладках. Парсеры же сильно отличаются как по количеству запросов, так и по профилю. Обычно человек через браузер загружает сайт целиком, со всеми стилями, картинками, динамическими элементами, JavaScript и всем прочим. Бот дёргает только HTML с данными. Это достаточно легко отсекается. Но со временем мы заметили, что как только мы отключаем юзера по признаку невзятия статики, боты начинают заходить с headless-браузеров и загружать всё целиком, как живые пользователи. Но это очень невыгодно, т.к. процесс существенно усложняется и начинает требовать больше ресурсов, плюс нужно выполнять все действия со скоростью человека, а не робота.
Так что сам парсинг принципиально не изменился, но увеличилось количество вложений. Соответственно, отвалилось большое количество самых примитивных парсеров. Когда мы перешли на модель SaaS, у нас упал трафик примерно на 12-15%, в основном за счёт подобных скриптов. С меньшим количеством нагрузки на сервер мы стали зарабатывать больше денег, потому что отвалились паразитные запросы. У нас остался поток в районе 20-30 RPS (запросов в секунду) от разнообразных парсеров. Но 20-30 запросов — это мелочи, а вот когда их тысячи...
Всё это время у нас была классическая война копья и щита. Мы придумываем что-то новое, разработчики парсеров реагируют и находят решения, как это обойти. Мы придумываем более изощрённый вариант отключать потоки, они снова обновляют алгоритм. В конечном итоге мы пришли к тому, чтобы делать их бизнес максимально невыгодным. Нас по-прежнему можно парсить, но этот процесс настолько сложный, что никакой коммерчески выгодной информации в разумные сроки от нас не получить. В принципе, это равносильно тому, что живой человек зайдёт и попытается скачать руками десятки тысяч страниц. Вряд ли он успеет это за 1 день, пока не обновились данные.
Дополнительные методы отслеживания и блокировок
Поведенческие факторы позволяют отсечь большинство паразитных запросов. Но что делать, если реальный пользователь упрётся в лимиты для роботов? Такое, увы, иногда случается. Например, пользователь сильно меняет своё поведение: раньше он открывал от силы 10 страниц в день, а тут внезапно открыл 50 в разных окнах. Конечно, мы не блокируем его сразу. Юзеру покажется Google CAPTCHA, у которой есть интересный режим теневой капчи.
Shadow captcha проверят браузер пользователя с точки зрения его схожести с ботом. Это происходит на стороне Google, у них очень большие возможности для этого. Благодаря проникновению и огромной базе знаний, Google анализирует множество факторов, которые нам недоступны. Грубо говоря, сервис оценивает, насколько это потенциально бот и выдаёт рейтинг от 0 до 1. У нас настроен порог, что если посетитель условно “робот” и его рейтинг меньше 0.4, то он улетает в бан. Если выше, то юзер продолжает работать, пока не станет нарушать с большей интенсивностью.
Помимо Google Shadow captcha, есть и явная Captcha. Если у человека хороший рейтинг, но мы считаем поведение подозрительным, то нужно будет пройти тест на робота. Но происходит это только при очень серьёзном выходе за нормативные параметры, поэтому реальные пользователи видят капчу в единичных случаях. Раньше, впрочем, тест выводился при малейшем подозрении и мы получали много жалоб от юзеров. Забавно, что парсеры тоже писали в саппорт и просили их разбанить. Но здесь социальная инженерия не срабатывает, т.к. на нашей стороне данные и мы всегда можем детально проверить, как вёл себя тот или иной пользователь.
Кроме этого, мы применили обфускацию. Анализ поведения парсеров показал, что люди запускают скрипты с сотен тысяч прокси, и забывают про них на несколько дней или даже недель. Поэтому мы решили выдавать некорректные данные. Как только юзер определяется как злоумышленник, данные ему не перестают поступать (ведь иначе парсер об этом узнает и что-то сделает), но цифры меняются местами и больше не представляют никакой ценности, хотя злоумышленник думает, что всё хорошо. Но юзеру с нормальным браузером мы такое, конечно, не отдаём. Живой пользователь на этом месте получает капчу, и не может продолжать работу, пока её не пройдёт. Игнорирующий ввод кода бот будет продолжать получать мусорные данные Это тоже нужно, чтобы увеличить затраты на парсинг. Парсер может поработать неделю, отчитаться, что всё собрал (ошибки в цифрах мало заметны несведущему человеку), но на выходе будет лишь мусор. Продать эти данные невозможно, время уже упущено, убытки и в деньгах, и в репутации.
Когда спарсить не получилось, в ход идёт DDoS
Как таковой DDoS, в общем-то, никому не интересен. Это дорогая затея и по деньгам, и по ресурсам. Кроме того, атака в чистом виде не имеет смысла, особенно с Rusprofile. В других рынках бывает практика, когда на пике продаж, например, перед Новым годом, атакуются сайты конкурентов. Но у нас нет пика сезона, а все конкуренты — крупные компании с хорошей репутацией, которые поступать так не будут. Парсерам же это вдвойне невыгодно, т.к. они потеряют доступ к данным, которые пытаются скачать. Но иногда бывают мстительные “хакеры”.
Перед Новым 2021 годом на сервер случилась DDoS-атака и мы не знаем достоверно, что стало причиной. Возможно, это была обида одного из парсеров, которому нас "заказали", а мы отдали ему перемешанные данные и он просто решил отомстить. Причина тогда была не особо важна. Мы фильтровали десятки тысяч запросов в секунду и не сразу смогли это остановить.
От DDoS, по большому счёту, защиты нет. Если есть достаточное количество денег, то можно успешно атаковать хоть Google, хоть Amazon. Что уж говорить о сайте довольно узконаправленного проекта, который умещается в одной серверной стойке. Меры противодействия тут есть разные, начиная от фильтраций эшелонов прокси до защиты на уровне провайдера. Есть Cloudflare DDoS protection или аналоги. Но, во-первых, это стоит денег. Во-вторых, они проксируют весь наш трафик через свои сервера, что довольно медленно. А далее защита выстроена примерно так же, как и у нас, но на большем количестве устройств. Соответственно, они смогут выдержать огромный поток.
Получается, что в "мирное" время мы проигрываем дважды. Первый раз — когда платим деньги. Второй — когда проксируем весь трафик и теряем скорость. А время ответа сайта для нас очень важный фактор. Мы стараемся поддерживать эту характеристику на высоком уровне, потому что у нас есть много клиентов со старыми компьютерами. При том, что у нас время ответа маленькое, с добавлением 100-150 миллисекунд от Cloudflare — это уже увеличение в разы. Поэтому до серьёзных атак мы решили такие средства не применять.
Но в тот Новый год, видимо, мы кого-то сильно обидели. Для атаки использовали около 2,5 миллионов проксей. Это были простые устройства, которые отправляли по несколько запросов в секунду. Причём вводились прокси постепенно. Сначала 500 тысяч штук, потом 1 миллион, потом 1,5 миллиона и так до 2,5 миллиона в пике. Но мы держались и не падали. Да, иногда сайт тормозил, изредка начинал выдавать 503 ошибку, но продолжал работать. Такой результат мы смогли получить за счёт настроенной системы бана по IP, Rate limit’а, бана по регионам, по поведенческим факторам и по непрохождению CAPTCHA. В общем, вкупе все эти методы помогли нам устоять и отсечь мусорный трафик. И даже при наличии налаженных систем, на ходу приходилось всё вручную оптимизировать и донастраивать. Мы мониторили реальных пользователей и старались максимально не задеть их, готовили даже план Б, чтобы уйти на решения хостеров или под Cloudflare. К счастью, мы лежали около 20-25 минут, затем наши настройки начали работать, ну а спустя час DDoS был отфильтрован и со временем прекратился.
Пэйволл как финальная защита… или нет?
Мы долгое время оставались открытым источником, при том что различные наши конкуренты, например, СПАРК, Контур и прочие были платными. Бесплатными были только мы и мелкие проекты с нерелевантными и неконсистентными данными, с которыми крупные подрядчики никогда не работали. Тогда стало понятно, что пора меняться.
Сейчас мы закрыты пэйволом (paywall — способ ограничения доступа к контенту веб-страницы до оплаты разовой или постоянной подписки), соответственно, большую часть данных человек без оплаты получить просто не сможет. Поэтому теперь мы не очень интересны для парсинга, особенно с учётом остальных методов защиты. Подавляющее большинство script kiddies не хотят вкладывать ни рубля, но чтобы сейчас парсить, нужно оплачивать подписку. Мы отслеживаем пользователей, сессии, и если система замечает разные устройства и IP у одного аккаунта, то юзера просто разлогинивает. То есть, сейчас для кражи контента нужно вкладывать больше денег. И это, конечно же, невыгодно.
Подводя итоги
Сейчас у нас хорошая, но не идеальная система. Можно было бы настроить ещё множество факторов, подключить различные сервисы для защиты. Но, как говорится, важно соотношение цена/качество. Мы способны справиться с нагрузкой от 2,5 миллиона прокси и сделали максимально комфортным использование сайта для живого юзера. Можем быстро отсечь робота, если точно определим, что это он (в среднем, за 6 секунд). Продолжают ли нас парсить? Как это ни удивительно — да. Но теперь халявщики вынуждены платить и приносить нам прибыль, а если делают это как-то нечестно, то получают лишь мусор вместо данных.
Проблема парсинга может затронуть абсолютно любой сайт, где есть ценный контент. От этого страдают и медиа, и различные базы данных, и энциклопедии. Как поступать с ворами — решение владельца контента. Кому-то некритично, что у него забирают данные, а для кого-то это может грозить потерей бизнеса. Мы для себя решили пойти сразу в нескольких направлениях защиты и пока это работает. Но технологии тоже не стоят на месте и вероятно, скоро нас ждёт новый цикл противостояния в этой войне.
Что касается DDoS, то система неплохо выдержала новогоднюю нагрузку, но к сожалению, полностью защититься от такого нельзя. Если у атакующего будет достаточно средств для запуска масштабного потока в несколько терабайт за секунду, то не выдержат даже крупные дата-центры. Пока лишь остается надеяться, что у нас нет настолько богатых и мстительных врагов.