
Основной объём трафика в вебе возникает из-за ботов. По большей части, эти боты используются для обнаружения нового контента. Это читалки RSS-фидов, поисковые движки, выполняющие краулинг вашего контента, а сегодня и боты ИИ, собирающие контент, чтобы скармливать его LLM. Но есть и зловредные боты. Их создают спамеры, скрейперы контента и хакеры. На моём прежнем месте работы бот обнаружил уязвимость Wordpress и встроил в наш сервер зловредный скрипт, а затем превратил машину в ботнет, используемый для DDOS. Один из моих первых веб-сайтов был полностью выдавлен из поиска Google из-за ботов, генерирующих спам. Мне нужно было найти способ защиты от этих ботов, поэтому я начал пользоваться zip-бомбами.
Zip-бомба — это относительно маленький сжатый файл, который может развернуться в очень большой и перегрузить машину.
Одной из первых особенностей веба стало применение сжатия gzip. Интернет был медленным, а информации в нём мало, поэтому до передачи данных по проводам их сжимали. Таким образом, состоящий из текста файл HTML на 50 КБ можно было сжать до 10 КБ, сэкономив таким образом на передаче 40 КБ. При коммутируемом Интернет-соединении это позволяло скачать страницу не за 12 секунд, а за 3 секунды.
Точно такое же сжатие можно использовать для передачи CSS, Javascript и даже изображений. Gzip быстр, прост и существенно повышает удобство просмотра страниц. Когда браузер выполняет веб-запрос, он добавляет заголовки, сообщающие целевому серверу, что у него есть поддержка сжатия. А если сервер тоже поддерживает сжатие, то он вернёт данные в сжатом виде.
Accept-Encoding: gzip, deflate
Боты, занимающиеся краулингом веба, тоже поддерживают эту функцию. Именно потому, что их работа заключается в потреблении контента всего веба, они стремятся максимизировать объём, применяя сжатие. И мы в полной мере воспользуемся этой особенностью.
Платформу, на которой я веду блог, боты часто сканируют на уязвимости безопасности, но по большей части я это игнорирую. Но когда я обнаруживаю, что они или пытаются инъецировать атаки, или пытаются нащупать ответ, то возвращаю 200 OK, а затем передаю им gzip. Размер файла варьируется от 1 МБ до 10 МБ, в зависимости от того, что они могут потребить. Чаще всего, когда они получают этот файл, то больше я никогда о них не слышу. Почему? Потому, что они ломаются, ещё не завершив потребление файла.
Content-Encoding: deflate, gzip
Происходит следующее: они получают файл и считывают заголовок, сообщающий им, что файл сжат. Они пытаются распаковать файл размером 1 МБ, чтобы найти в нём тот контент, который ищут. Но файл продолжает распаковываться снова, и снова, и снова, пока у них не заканчивается память и на их сервере не происходит сбой. Файл на 1 МБ распаковывается в 1 ГБ. Этого более, чем достаточно для того, чтобы поломать большинство ботов. Однако для тех надоедливых скриптов, которые не останавливаются, у меня есть файл на 10 МБ. Он распаковывается в 10 ГБ и мгновенно убивает скрипт.
Прежде чем приступать к описанию создания zip-бомбы, должен сказать, что потенциально вы можете устроить сбой и повреждение собственного устройства, так что учитывайте риски. Вот, как создаётся zip-бомба:
dd if=/dev/zero bs=1G count=10 | gzip -c > 10GB.gz
Вот, что делает эта команда:
dd
: команда dd используется для копирования или преобразования данных.if
: входной файл, здесь указан/dev/zero
— особый файл, создающий бесконечный поток нулевых байтов.bs
: размер блока, устанавливает размер блока на 1 гигабайт (1G), то есть dd будет считывать и записывать данные блоками по 1 ГБ за раз.count=10
: эта опция приказывает dd обработать 10 блоков, каждый из которых имеет размер 1 ГБ. То есть так мы создадим 10 ГБ данных из одних нулей.
Затем мы передаём результат выполнения команды программе gzip, сжимающей его в файл 10GB.gz. Получившийся файл будет иметь размер 10 МБ.
На свой сервер я добавил промежуточное ПО, проверяющее текущий запрос на зловредность. У меня есть чёрный список IP-адресов, пытающихся многократно сканировать весь веб-сайт. Также есть и другие эвристики для выявления спамеров. Многие спамеры пытаются спамить на странице, а затем возвращаются, чтобы проверить, попал ли спам на страницу. Я использую этот паттерн для их выявления. Это выглядит примерно так:
if (ipIsBlackListed() || isMalicious()) {
header("Content-Encoding: deflate, gzip");
header("Content-Length: "+ filesize(ZIP_BOMB_FILE_10G)); // 10 MB
readfile(ZIP_BOMB_FILE_10G);
exit;
}
Вот и всё, что нужно. Единственные мои затраты связаны с передачей время от времени файла на 10 МБ. Если этот пост завирусится, я уменьшу размер файла до 1 МБ, что почти столь же эффективно.
Стоит ещё сказать, что zip-бомба не гарантирует полную безопасность. Её можно легко обнаружить и обойти. Да и контент можно считывать только частично. Но для простых ботов, слепо выполняющих краулинг в вебе и мешающих работе серверов, это достаточно хороший инструмент защиты сервера.
Вы можете посмотреть на работу zip-бомб в воспроизведении логов моего сервера.