Меня зовут Илья. Я скорее программист и вечный-в-попытках-предприниматель чем системный администратор. Но, как известно, в стартапах ты и косец, и жнец, и на дуде игрец. Поэтому сегодня пришлось поиграть во все роли. Статья сможет помочь таким же как я начинающим администраторам, которые по воле судьбы/службы приходится заниматься сервером.
Пишу с пылу, с жару, часть команд писал по памяти. Буду рад любым корректировкам.
Итак, сегодня утром в 11:35 по минскому времени один из менеджеров написал, что сайты перестали работать. А конкретнее, сыпать ошибками MySQL
Т.к. первоначальной настройкой сервера занимались специалисты хостинговой компании, я сразу же написал запрос им. Но получил от ворот поворот:
![](https://habrastorage.org/files/032/2e2/29d/0322e229d39a4ad1b2bfe062e7223111.png)
Что же, возможно это и не клиентоориентированно, но правильно. Не каждому же клиенту помогать с 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 млн айнод?
![](https://habrastorage.org/files/839/267/0de/8392670dee844c4082eefb7b590dc2a8.png)
При дальнейшем поиске увидел папку /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 — не наш. Мы просто его временно размещаем на нашем сервере. Чем он занимается никому не известно.
Смотрю структуру сайта:
![](https://habrastorage.org/files/39a/363/f4e/39a363f4eb7a4f6e8d42a1fd0e9cde0d.png)
Что-то знакомое. Посмотрим index.php:
![](https://habrastorage.org/files/783/3ab/976/7833ab976060467989c0da6bf1ce4216.png)
Ага, 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 запрос, поэтому параметров запроса не видно в адресе. Название очень подозрительное. Когда-то в детстве у меня тоже была такая директория на домашнем компьютере :-)
Смотрим сам файл:
![](https://habrastorage.org/files/d7e/6b4/a5b/d7e6b4a5b15842c69889a8adfaf18d91.png)
Понятно! Враг найден. Изменяем название файла и в логах exim наступает снова тишина. Наконец можно притронуться к еде, которую будущая жена поставила около меня минут 10 назад :-)
Далее будет допрос заключенного:
— каким образом попал на сервер?
— есть ли сообщники на других сайтах/директориях?
А также нужно разобраться на нашей территории:
— проверить права к папкам
— кроме автоматической проверки свободного места настроить проверку свободных айнод
— настроить exim (например, заблокировать SMTP).
Наверное, необходимо что-то еще. Буду рад комментариям/исправлениям/историям из вашей практики.
Надеюсь, кому-то статья покажется полезной.
Спасибо за внимание!
Комментарии (29)
WaveCut
31.07.2015 17:55Привет, Илья :)
— каким образом попал на сервер?
— есть ли сообщники на других сайтах/директориях?
Есть два распространенных пути подложить веб-шелл: компрометация SSH/FTP/WebDAV или что там у вас, или эксплуатирование уязвимости файлозагрузчика CMS — такое случается регулярно, это далеко не фантастика.
Искать зловред регулярками либо сканнерами безопасности, тут на хабре недавно проскакивала парочка обзоров, не буду рекламировать.
Ну и старайся избегать мэйнстримных и несвежих CMS.roskov Автор
31.07.2015 18:11Привет, Валера :-)
Как я написал выше, CMS не моя. Не думаю, что шелл был закинут через SSH/FTP/WebDav (хотя через последнее недавно украли FL.ru насколько я помню). Но безусловно, стоит проверить.
Спасибо за советы!volanddd
01.08.2015 07:2990% что эксплуатировалась уязвимость в редакторе JCE, 9% что другая уязвимость, вероятность компрометации доступа менее 1%.
digger
31.07.2015 18:09А что такое «рутовский диск»?
roskov Автор
31.07.2015 18:12Извиняюсь за терминологию. Под этим «невероятным» термином я понимал диск, на котором находится ОС и БД.
Подправил в посте. Спасибо.mobilesfinks
31.07.2015 18:14у вас ещё с термином inode недопонятки ))) вы его нодами кличите. Иноды (айноды) тогда уж ))
отсюда понятен флаг "-i" для df и других утилит
feedborg
31.07.2015 21:16-1Честно говоря, я удивлен, что таким вот банальностям в наше время целый топик посвящают. Если не понимаете что делать, то почему услугу не заказать по администрированию, тут же совершенно типовые проблемы описаны. Или просто похвалиться где-то хотелось?
roskov Автор
01.08.2015 12:23+2Честно говоря, сначала я написал мануал просто для себя (если вдруг такое повторится снова). Потом пришла мысль поделиться с сообществом — мне бы очень помогла такая статья в тот момент. Это сейчас я уже понимаю, что возможно этого и не стоило делать. Поэтому наверное да, первый
блинпост комом.
raid
01.08.2015 15:14+8Я вот не понимаю таких людей. По вашему на Хабре вообще ничего писать не нужно.
Если вы с чем-то знакомы и вам не хочется в n-й раз об этом читать — не читайте. А для других информация может оказаться полезной или просто интереснойivn86
02.08.2015 00:11-1информация может оказаться полезной или просто интересной
Полезной я бы счёл информацию поиска зловреда find'ом по дате создания или модификации. Почему-то ни разу такое не встречал. Интересной — демон, отслеживающий inotify'ом модификацию или появление новых сценариев с уведомлением на почту.alekciy
02.08.2015 14:21Зловред дату меняет так, что поиск помогает мало. По второму facron например.
feedborg
02.08.2015 14:24А зачем? У нормальных людей код в системе контроля версий. Обычный diff все наглядно покажет.
feedborg
02.08.2015 14:23Я вот не понимаю таких людей. По вашему на Хабре вообще ничего писать не нужно. Если вам не понравился комментарий — просто проходите мимо и все.
FreeLSD
01.08.2015 08:12Очень распространенная проблема. Правда, как правило, файлы сессий иноды забивают, а не дырявая жумла.
Саппорт мог бы и помочь. Мы всегда помогаем в типовых случаях.
isden
01.08.2015 10:31+1> Более того, site.by — не наш. Мы просто его временно размещаем на нашем сервере. Чем он занимается никому не известно.
Имхо, вот в эту сторону надо копать после восстановления работы своих. Т.е. просто закрыть его и связаться с владельцем (если, конечно, у вас там не какой-то жесткий договор на его обслуживание).
Хостить какую-то левую фигню, которая непонятно что делает, как-то не очень гут, имхо.
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 — не наш. Мы просто его временно размещаем на нашем сервере. Чем он занимается никому не известно
Вы считаете нормальным держать на своем продакшен-сервере такие проекты?
amarao
02.08.2015 20:17Сказать честно, на нескольких миллиардах файлов в одном каталоге, проще новую FS сделать. rm такого чуда, только если продакшен позволяет, в screen/nohup, с ожиданием «за недельку разгребёт».
isden
03.08.2015 10:43У меня есть сильные подозрения, что если перемонтировать раздел без журналирования, то процесс очень сильно ускорится.
amarao
03.08.2015 18:45Не настолько, чтобы это сильно помогло. Там основная проблема — удаление всё ещё остаётся более дорогой операцией, чем добавление, да ещё и со сложностью районе o(что-то-от-числа-файлов-в-каталоге). Удалить миллиард файлов из тысячи каталогов в кажом из которых по тысяче каталогов в каждом из которых по тысяче файлов? Может быть. Удалить каталог с миллиардом файлов? Не в этой жизни.
isden
03.08.2015 19:02Хочется мне посмотреть на каталог с миллиардом файлов… Поискал тут в интернетах — пишут, что синтетическими тестами не удавалось набить больше 10-20 миллионов, потом начинались проблемы с журналом, приходилось жестко тюнить (ext4).
Из личного опыта — работа с каталогом при паре миллионов уже начинает очень заметно подтормаживать. Видел такое у одного клиента.
FFunk
Я вот такой командой смотрю занятое место по директориям:
mobilesfinks
ещё есть утилита ncdu — даёт более наглядное представление какая папка занимает больше всего места на разделе
mobilesfinks
что бы не вспоминать как пишется --max-depth для du, можно использовать ключ -s
получим вывод размера всех директорий корневого раздела. Ну и по аналогии с другими папками.MasMaX
Можно еще