2 min read
Как боты съели 70 ГБ на моём сервере за 20 часов

Вчера у меня на сервере внезапно кончилось вообще всё свободное место (ровно в 0 байт), а боты начали падать с disk I/O error из-за невозможности записать даже байт в SQLite.

Полез разбираться с ncdu и быстро нашёл виновника: папка /root/forgejo/data/gitea/repo-archive/ в контейнере Forgejo разрослась на 70+ ГБ. Внутри лежали сотни сгенерированных ZIP-архивов по 300–500 МБ каждый.

Что произошло?

Когда в веб-интерфейсе запрашивают архив релиза или ветки (/archive/tag.zip), Forgejo на лету пакует его и сохраняет копию в кэш.

Какой-то распределённый AI-краулер на резидентных прокси (IP со всего мира от Бразилии до Вьетнама) решил методично пройтись по всем тегам и коммитам в моём публичном зеркале крупного опенсорс-репозитория. На каждый чих бота Forgejo честно генерировал и складывал на диск полугигабайтный архив (стабильно держа около 15% CPU).

Встроенный крон очистки в Forgejo по умолчанию срабатывает раз в сутки в полночь (@midnight), удаляя архивы старше 24 часов. За 20 часов нагенерировалось 70 ГБ, и до полуночи сервер не дожил буквально час.

Как лечить

  1. Экстренная очистка (безопасно, на сам Git не влияет):

    rm -rf /root/forgejo/data/gitea/repo-archive/*
  2. Закрыть публичный доступ к зеркалам: Бороться с распределённым ботнетом через fail2ban или robots.txt бесполезно. Самое надёжное — перевести аккаунт mirrors в режим Limited (только для авторизованных пользователей). Бот упирается в форму логина за 1 мс без какой-либо нагрузки на диск.

  3. Зарезать генерацию архивов в app.ini: Если архивы для репозиториев вообще не нужны:

    [repository]
    DISABLE_DOWNLOAD_SOURCE_ARCHIVES = true

    Либо чистить их кэш каждый час:

    [cron.archive_cleanup]
    SCHEDULE = @every 1h
    OLDER_THAN = 2h

Теория мёртвого интернета на практике

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

Кстати, именно поэтому я закрыл доступ к зеркалам на git.gluek.info от анонимов. Если держите у себя публичные зеркала — имейте в виду эти грабли.