Всем привет!

Меня зовут Илья. Я скорее программист и вечный-в-попытках-предприниматель чем системный администратор. Но, как известно, в стартапах ты и косец, и жнец, и на дуде игрец. Поэтому сегодня пришлось поиграть во все роли. Статья сможет помочь таким же как я начинающим администраторам, которые по воле судьбы/службы приходится заниматься сервером.

Пишу с пылу, с жару, часть команд писал по памяти. Буду рад любым корректировкам.

Итак, сегодня утром в 11:35 по минскому времени один из менеджеров написал, что сайты перестали работать. А конкретнее, сыпать ошибками MySQL

Т.к. первоначальной настройкой сервера занимались специалисты хостинговой компании, я сразу же написал запрос им. Но получил от ворот поворот:



Что же, возможно это и не клиентоориентированно, но правильно. Не каждому же клиенту помогать с MySQL. Платной услугой пользоваться не хотелось. Будем сами.

Действительно, при заходе на сайт появлялось неприятное:

SQLSTATE[HY000]: General error: 1 Can't create/write to file '/tmp/#sql_b80_0.MYI' (Errcode: 28 - No space left on device),


На первый взгляд все казалось очень простым — не хватает места на диске, где находится MySQL. Но с другой стороны и удивительным — только вчера на том диске было 40 Гб свободного места.

Подключаемся по SSH, смотрим:

bakharevich@server:/# df -h
Filesystem      Size  Used Avail Use% Mounted on
rootfs           60G   17G   40G  30% /
/dev/xvda1       60G   17G   40G  30% /
/dev/xvda3       79G   57G   19G  76% /home/site2.by
/dev/xvda5       69G   36G   30G  55% /home/site3.by

Странно. На диске с БД действительно свободно 40Гб, но MySQL уверенно не хочет запускаться — нет места.

Быстрый поиск в Интернете дал результат — кроме места на диске есть ещё и айноды, которых у нас как раз-таки 0.
bakharevich@server:/# df -i
Filesystem       Inodes   IUsed    IFree IUse% Mounted on
rootfs          3932160 3932160        0  100% /
/dev/xvda1      3932160 3932160        0  100% /
/dev/xvda3      5242880 1122900  4119980   22% /home/site2.by
/dev/xvda5      4587520  801087  3786433   18% /home/site3.by


Т.е. каждый файл, директория и даже симлинк занимают айноду. Где-то в подсознании я безусловно понимал, что такое имеет место быть. Но отсутствие опыта в делах админских/железячных не дало мне сразу же подумать об этом. Хорошо, будем знать! :-) А пока нужно освободить часть айнод, чтобы как можно скорее запустить сайты.

Первое, что я решил удалить, это сессии от PHP. Да, у людей повылетают авторизации, но это не так страшно, т.к. сайты не работают. У нас сессии хранятся на диске. Поэтому:

rm -rf /var/lib/php5/*


А также перенастроить их сохранение на другой диск в php.ini:

session.save_path = "/path/to/new/dir/"


Смотрим, сколько освободили айнод:

bakharevich@server:/home# df -i
Filesystem       Inodes   IUsed    IFree IUse% Mounted on
rootfs          3932160 32928660    3500  100% /
/dev/xvda1      3932160 3932160        0  100% /
/dev/xvda3      5242880 1122900  4119980   22% /home/site2.by
/dev/xvda5      4587520  801087  3786433   18% /home/site3.by


Всего 3500 :-( Но этого может хватить, чтобы запустить MySQL, а значит и временно восстановить работу сайтов.

Пробуем перезапустить MySQL:

bakharevich@server:~$ sudo service mysql start
[ ok ] Starting MySQL (Percona Server) database server: mysqld . . ..


Отлично, сайты заработали! Но количество айнод продолжает уменьшаться. Примерно через 10 минут их снова станет 0.

Продолжаем удалять файлы. Инстиктивно я начал с /var/log/ і /var/cache/:

du --max-depth=1 /var/log/ | sort -n -r
du --max-depth=1 /var/cache/ | sort -n -r


Удалил лишнее. Стало примерно еще 3.000 айнод, но этого естественно все равно очень мало. И вообще, кто мог создать такое количество файлов, чтобы использовать около 1.5 млн айнод?



При дальнейшем поиске увидел папку /var/spool/exim4/input. Exim4 — почтовый сервер, который, как я понимаю, идет вместе с Debian. Попробовал подсчитать кол-во файлов в директории, но результат долго не показывался. Значит файлов там действительно очень и очень много:

ls -l /var/spool/exim4/input | wc -l


Быстрый поиск в Интернете показал, что эта директория для писем в очереди. Гм… Это интересно, потому что ни один из наших сайтов не пользуется локальным почтовым сервером. Все переведено на «Яндекс.Почта для домена» и Google. Ладно, к этому вернемся позже. Пока нужно освободить айноды!

Просто удалять файлы в директории не хочется. Ищем правильное удаление и находим нечто подобное:

exim -bp | exiqgrep -i -f $user | xargs exim -Mrm


Запускаю. Жду некоторое время и понимаю, что айноды не освобождаются. Быстро размышляю, что это скорее всего из-за первой команды exim -bp, которая сначала выводит список писем в очереди. Раз там более 1 млн писем, то и выводить будет долго.

Более того, к этому времени свободные айноды уже закончились. Сайты вновь остановились. Начинают писать менеджеры, приходят одна за одной SMS о неработоспособности сайтов, звонит телефон… Обстановка накаляется. Ладно! Придется действовать жестко. Удаляем напрямую:

rm -rf /var/spook/exim4/input/*


Но не тут-то было. Айноды не высвобождаются. Удаляются ли файлы тоже не могу посмотреть — объем более миллиона не позволяет их быстро подсчитать. Скорее всего, rm * тоже сначала читает всю директорию, а потом уже начинает удаление.

Ладно, пробуем более жесткий вариант:

rm -r /var/spool/exim4/input/


… и наконец-то айноды освобождаются тысячами. Чувствую, что победил в небольшой битве, но враг ушел в лес для перегруппировки и еще одной атаки примерно через месяц :-) Надо наступать дальше.

Уже более спокойный и рассудительный, начал смотреть логи exim. Сначала ничего интересного… как вдруг нечто подобное:

2015-07-31 13:58:41 1ZIwuU-0007a9-Rm ** joan_galloway@site.by R=dnslookup T=remote_smtp: retry time not reached for any host after a long failure period
2015-07-31 13:58:41 1ZIwuU-0007a9-Rm joan_galloway@site.by: error ignored
2015-07-31 13:58:41 1ZIwuU-0007a9-Rm Completed


Интересно! Как я уже писал, мы не пользуемся локальным почтовым сервером. Более того, site.by — не наш. Мы просто его временно размещаем на нашем сервере. Чем он занимается никому не известно.

Смотрю структуру сайта:



Что-то знакомое. Посмотрим index.php:



Ага, Joomla! Причем от 2013 года. Наверное воспользовались уязвимостью старых версий.

С большой надеждой, что сайт не очень популярный, открываю логи-вебсервера, чтобы найти что-то подозрительное. Сразу делаю поиск по email «joan_galloway», который был найден в логах exim. Но ничего нет… Ищем дальше. Запросы картинок, файлов стилей… И вдруг:

50.62.177.108 - - [31/Jul/2015:14:37:41 +0300] "POST /components/com_weblinks/views/categories/system.php HTTP/1.1" 404 2056 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.7.6)"


Очень интересно! Некий файл system.php. Был POST запрос, поэтому параметров запроса не видно в адресе. Название очень подозрительное. Когда-то в детстве у меня тоже была такая директория на домашнем компьютере :-)

Смотрим сам файл:



Понятно! Враг найден. Изменяем название файла и в логах exim наступает снова тишина. Наконец можно притронуться к еде, которую будущая жена поставила около меня минут 10 назад :-)

Далее будет допрос заключенного:

— каким образом попал на сервер?
— есть ли сообщники на других сайтах/директориях?

А также нужно разобраться на нашей территории:

— проверить права к папкам
— кроме автоматической проверки свободного места настроить проверку свободных айнод
— настроить exim (например, заблокировать SMTP).

Наверное, необходимо что-то еще. Буду рад комментариям/исправлениям/историям из вашей практики.

Надеюсь, кому-то статья покажется полезной.

Спасибо за внимание!

Комментарии (29)


  1. FFunk
    31.07.2015 17:38

    Я вот такой командой смотрю занятое место по директориям:

    du --si --max-depth=1



    1. mobilesfinks
      31.07.2015 18:12
      +3

      ещё есть утилита ncdu — даёт более наглядное представление какая папка занимает больше всего места на разделе


    1. mobilesfinks
      31.07.2015 18:18

      что бы не вспоминать как пишется --max-depth для du, можно использовать ключ -s

      du -xhs /*
      
      получим вывод размера всех директорий корневого раздела. Ну и по аналогии с другими папками.


      1. MasMaX
        05.08.2015 16:26
        +1

        Можно еще

        du -d 1 -h /
        


  1. WaveCut
    31.07.2015 17:55

    Привет, Илья :)

    — каким образом попал на сервер?
    — есть ли сообщники на других сайтах/директориях?

    Есть два распространенных пути подложить веб-шелл: компрометация SSH/FTP/WebDAV или что там у вас, или эксплуатирование уязвимости файлозагрузчика CMS — такое случается регулярно, это далеко не фантастика.
    Искать зловред регулярками либо сканнерами безопасности, тут на хабре недавно проскакивала парочка обзоров, не буду рекламировать.
    Ну и старайся избегать мэйнстримных и несвежих CMS.


    1. roskov Автор
      31.07.2015 18:11

      Привет, Валера :-)

      Как я написал выше, CMS не моя. Не думаю, что шелл был закинут через SSH/FTP/WebDav (хотя через последнее недавно украли FL.ru насколько я помню). Но безусловно, стоит проверить.

      Спасибо за советы!


      1. TheRaven
        31.07.2015 18:17

        Joomla, особенно старая — швейцарский сыр, а боты ходят по ним часто. Посмотрите список плагинов которые установлены и прогуглите на тему известных уязвимостей, иначе история будет повторяться.


        1. roskov Автор
          31.07.2015 18:19

          Да, пометил в планах, спасибо!


      1. volanddd
        01.08.2015 07:29

        90% что эксплуатировалась уязвимость в редакторе JCE, 9% что другая уязвимость, вероятность компрометации доступа менее 1%.


  1. inkvizitor68sl
    31.07.2015 17:55
    +1

    1. roskov Автор
      31.07.2015 18:12

      Спасибо большое. То, что нужно.


  1. digger
    31.07.2015 18:09

    А что такое «рутовский диск»?


    1. roskov Автор
      31.07.2015 18:12

      Извиняюсь за терминологию. Под этим «невероятным» термином я понимал диск, на котором находится ОС и БД.

      Подправил в посте. Спасибо.


      1. mobilesfinks
        31.07.2015 18:14

        у вас ещё с термином inode недопонятки ))) вы его нодами кличите. Иноды (айноды) тогда уж ))
        отсюда понятен флаг "-i" для df и других утилит


        1. roskov Автор
          31.07.2015 18:16

          Верно, спасибо, исправил :-)


  1. feedborg
    31.07.2015 21:16
    -1

    Честно говоря, я удивлен, что таким вот банальностям в наше время целый топик посвящают. Если не понимаете что делать, то почему услугу не заказать по администрированию, тут же совершенно типовые проблемы описаны. Или просто похвалиться где-то хотелось?


    1. roskov Автор
      01.08.2015 12:23
      +2

      Честно говоря, сначала я написал мануал просто для себя (если вдруг такое повторится снова). Потом пришла мысль поделиться с сообществом — мне бы очень помогла такая статья в тот момент. Это сейчас я уже понимаю, что возможно этого и не стоило делать. Поэтому наверное да, первый блин пост комом.


    1. raid
      01.08.2015 15:14
      +8

      Я вот не понимаю таких людей. По вашему на Хабре вообще ничего писать не нужно.
      Если вы с чем-то знакомы и вам не хочется в n-й раз об этом читать — не читайте. А для других информация может оказаться полезной или просто интересной


      1. ivn86
        02.08.2015 00:11
        -1

        информация может оказаться полезной или просто интересной

        Полезной я бы счёл информацию поиска зловреда find'ом по дате создания или модификации. Почему-то ни разу такое не встречал. Интересной — демон, отслеживающий inotify'ом модификацию или появление новых сценариев с уведомлением на почту.


        1. alekciy
          02.08.2015 14:21

          Зловред дату меняет так, что поиск помогает мало. По второму facron например.


        1. feedborg
          02.08.2015 14:24

          А зачем? У нормальных людей код в системе контроля версий. Обычный diff все наглядно покажет.


      1. feedborg
        02.08.2015 14:23

        Я вот не понимаю таких людей. По вашему на Хабре вообще ничего писать не нужно. Если вам не понравился комментарий — просто проходите мимо и все.


  1. FreeLSD
    01.08.2015 08:12

    Очень распространенная проблема. Правда, как правило, файлы сессий иноды забивают, а не дырявая жумла.
    Саппорт мог бы и помочь. Мы всегда помогаем в типовых случаях.


  1. isden
    01.08.2015 10:31
    +1

    > Более того, site.by — не наш. Мы просто его временно размещаем на нашем сервере. Чем он занимается никому не известно.

    Имхо, вот в эту сторону надо копать после восстановления работы своих. Т.е. просто закрыть его и связаться с владельцем (если, конечно, у вас там не какой-то жесткий договор на его обслуживание).
    Хостить какую-то левую фигню, которая непонятно что делает, как-то не очень гут, имхо.


  1. Iforgot
    01.08.2015 11:39
    +1

    Ну правильно, вы бы в саппорт написали: у меня мускул не взлетает — закончилось место! А проблема то не в месте, проблема что спамят с вашего железа. Админ бы почистил диск, получил бы место, мускул бы взлетел, но на недолго. Вы бы опять обратились в саппорт: как же так, я платил, а мускул и недели не проработал!

    В общем, правильно заданный вопрос — половина ответа. Ваш сервер — обычный спам релей, ломанули старую уязвимость на сайте и залили php код.

    Вот навскидку еще пара подсобных инструментов:
    Показывает количество в очереди писем (просто цифру)
    exim -bpc

    вот эти команды чистят очередь:
    exipick -zi | xargs exim -Mrm
    exipick -i | xargs exim -Mrm
    exiqgrep -o 0 -i | xargs exim4

    затем надо в php.ini включить:
    mail.add_x_header = On
    mail.log = /var/www/phpmail.log

    Эта штука будет в лог писать путь до php файла, который рассылает спам. Пока вы не обновили дырявый опенсорсный движок, php файлы будут к вам заливаться до бесконечности. Но хотя бы на пару часов можно прибить виновника, чтобы снять нагрузку с проца и нормально решить проблему )

    >Более того, site.by — не наш. Мы просто его временно размещаем на нашем сервере. Чем он занимается никому не известно

    Вы считаете нормальным держать на своем продакшен-сервере такие проекты?


  1. amarao
    02.08.2015 20:17

    Сказать честно, на нескольких миллиардах файлов в одном каталоге, проще новую FS сделать. rm такого чуда, только если продакшен позволяет, в screen/nohup, с ожиданием «за недельку разгребёт».


    1. isden
      03.08.2015 10:43

      У меня есть сильные подозрения, что если перемонтировать раздел без журналирования, то процесс очень сильно ускорится.


      1. amarao
        03.08.2015 18:45

        Не настолько, чтобы это сильно помогло. Там основная проблема — удаление всё ещё остаётся более дорогой операцией, чем добавление, да ещё и со сложностью районе o(что-то-от-числа-файлов-в-каталоге). Удалить миллиард файлов из тысячи каталогов в кажом из которых по тысяче каталогов в каждом из которых по тысяче файлов? Может быть. Удалить каталог с миллиардом файлов? Не в этой жизни.


        1. isden
          03.08.2015 19:02

          Хочется мне посмотреть на каталог с миллиардом файлов… Поискал тут в интернетах — пишут, что синтетическими тестами не удавалось набить больше 10-20 миллионов, потом начинались проблемы с журналом, приходилось жестко тюнить (ext4).
          Из личного опыта — работа с каталогом при паре миллионов уже начинает очень заметно подтормаживать. Видел такое у одного клиента.