Здравствуйте. Недавно я задавал вопрос по поводу создания цикла статей. Вот первая статья.
В этом цикле статей вы узнаете как грамотно настроить LAMP сервер, аля «хостинг только мощней».
Мы будем использовать следующий стек: nginx — apache-mpm-itk — mod_php — mysql — linux/debian.
Буду освещать следующие темы:
- Настройка frontend — backend
- Расчет возможностей сервера, настройка mysql и backend
- Рассказ об опыте на базе intel s3420gp
Совершенно уверенно могу сказать, что настройка LAMP сервера не ограничивается 6-10 командами установки и раскомментирования определенных строчек в файлах настройки.
Пример: по умолчанию nginx не дает возможности закачать на сервер тело запроса больше чем 1M. Если не настроить данный параметр, будет возникать ошибка 414 (Request-URI Too Large), при попытке добавления небольшой серии фотографий.
У apache совершенно противоположное: у него тело запроса по умолчанию не ограничено. Это делает возможным совершать пакости.
В этой статье мы познакомимся со всей настройкой досконально. В статье вы сможете найти конфигурационные файлы, подготовленные мной. Будучи педантом, мои конфигурационные файлы всегда сгруппированы по типу, например: «производительность», «генерация контента», «страницы ошибок», «сжатие», «другие настройки», «общие настройки». Мне кажется, что читаемость данных файлов становится намного лучше, если они сгруппированы.
Мы узнаем о том какие бывают простые атаки и как от них защищаться. Сразу скажу, что при базовой конфигурации frontend в лице nginx — backend apache все равно остается уязвим.
Я практически уверен, что я не смогу уместить все в одну статью. Добро пожаловать под кат.
— Предисловие:
Так получилось, что недавно у нас начал падать сервер. Почему-то падал он c вечера на ночь, а днем вполне себе работал. Не скажу что на нем была огромная нагрузка. Во время падений обнаружил непонятно огромные скачки выделения оперативной памяти на apache, более 700 мегов на процесс, хотя у PHP максимально стояло 256M. Сервер уходил в своппирование, после чего падал. У сервака вначале было 8G RAM, после чего поставили 16G.
До этих падений сервер работал целый год и никаких проблем не знали. У него была жуткая конфигурация сделанная на коленках, ибо c
Apache2.2.16_mpm_itk + php5.3.0 висел в интернете за frontend и backend одновременно, без защит от возможных атак вообще. Мне удалось провести все атаки, упоминавшиеся на хабре =).
Mysql5.1 был настроен в базовой конфигурации с не оптимальным использованием RAM и все такое.
С этого момента пришлось все очень хорошо изучить. Кстати, после того как все нормально настроил, количества ненужного словоблудия в конфигах виртуальных хостов резко уменьшилось!
Начнем настройку
— Репозитории бывают разные:
Первая проблема которая встала, это обновление софта. Как известно, репозитории debian имеют достаточно устаревший софт. Говорят, что они хорошо тестированы, но они реально старые! К слову я сам удивился, когда нашел эту подборку софта.
Теперь репозитории LAMP я беру от сюда www.dotdeb.org/
Вот инструкция по настройке www.dotdeb.org/instructions/
Для тех кто в первый раз очень сухо (а ведь сам был таким однажды и некому было помочь, кроме гугла):
— Устанавливаем debian сразу ставим галку ставить SSH сервер (больше ничего!!!), далее узнаем IP сервера за VGA монитор больше не садимся, можете сдать сервер в датацентр.
— Коннектимся по SSH, советую putty под win.
— nano /etc/apt/sources.list вставляем туда по инструкции с dotdeb. (на заметку: вставка текста в консоль из буфера windows делается правой кнопкой мыши)
— выполняем другие вещи по инструкции
— выполняем большой блок команд которые я написал ниже
— работаем через MC как белые люди
— дальше все зависит от Вас! =)
На заметку, вот моя конфигурация железа: Intel s3420gp, xeon x3450, 16GB ECC RDIMM, 3*1Tb 3.5" SATA «WD BE» (2x-raid1(25G /, 20G swap, 100G /var, ~800G /home) + 1single(1Tb /mnt/unsafe)). На заметку новичкам: я жутко в свое время ступил, что поставил диски Black Edition — надо было ставить Raid Edition (в наши времена Red Edition, спасибо argnist).
И так. Сейчас мы только что поделили диски, поставили операционную систему из минидиска debian (190Mb) и сделали настройки репозиториев. Теперь продолжим. Во время выполнения операций у вас будут вопросы от dpkg, надо на них ответить.
apt-get update
apt-get upgrade
apt-get install nginx apache2 apache2-mpm-itk php5 php5-apc php-pear php5-dev php5-gd mysql-server mysql-client php5-mysql postfix mc -y
pecl install gd
apt-get install libapache2-mod-rpaf -y
echo all done!
nginx — фронтенд, apache2-mpm-itk — бэкенд, mod_php5.3 — язык, mysql5.5 — база данных, postfix — рассылка почты из PHP.
— Составляем архитектуру системы:
Всегда известно, что без наглядной картинки настраивать систему труднее чем, если бы она была. Вначале я сам не мог себе её представить и нарисовал её только после прочтения более половины основной документации по двум серверам и немного про апачи с mysql. Сейчас я её нарисовал для читателей сразу, что бы им было нагляднее и удобнее изучать конфигурацию. Думаю, что по данной картинке будет достаточно просто анализировать узкие части системы в будущем, что позитивно скажется на поддержке системы и, возможно, ее масштабирования. (Картинко кликабельно)
Все части картинки я буду пояснять в следующей статье. В этой статье мы раскроем настройки frontend — backend. Защита apache.
Frontend: настройка nginx
Настраивать nginx мы будем в режиме прокси. Этому есть несколько причин:
- Защита сервера apache от атак
- Сжатие и отдача статического контента на легковесном сервере
- Сохранение мозгов сервера
- Простота реализации
- Apache mod_php работает (не намного || хуже) чем PHP FastCGI, при том, что настройка mod_php более понятна и стандартна
— Конфиги в студию!
Вот мои конфигурационные файлы которые я использую для прокси сервера
yadi.sk/d/w0SNSFIM0nyk1
То что поставилось вам от репозиториев надо безжалостно заменить на эти файлы, а так же добавить в mime расширения .docx, .pptx, .xlsx напротив соответствующих mime типов. Давайте немного посмотрим на устройство конфигов:
/nginx.conf - главный конфигурационный файл - собственно с него и начинается загрузка. В нем я оставил общие настройки сервера и импорт директорий.
/proxy_params - конфигурационный файл, для настройки nginx сервера в режима proxy. Там собраны все настройки касательно проксирования сгруппированные по группам: Базовые настройки, Защита от killapache.pl, Размер буферов, Кеширование, Другое.
/conf.d - директория в которой я сгруппировал конфигурации по каждому модулю. В частности я сгруппировал error-docs - страницы ошибок, ngx_http_core_module - базовые настройки сервера, ngx_http_gzip_module - настройки сжатия.
Я намеренно не объясняю значения параметров настроек, так как на то есть русская документация. Однако я хочу указать на некоторые из них и то, почему я выбрал именно такие параметры. Читателям же желаю подумать, какие настройки нужны для их целей, тем более искать их больше не нужно я их все сгруппировал.
- client_max_body_size я увеличил до 64M, что бы можно было загружать на сервер разную мультимедиа — банально фотографии.
- client_body_buffer_size — стандартный буфер я увеличил до 32k потому что по умолчанию явно не будет хватать. Часто приходится обрабатывать «большие данные (10-20к)» на входе. Вообще этот параметр должен определяться из того какой код будет выполняться на сервере. Если вы например твиттер — то вам больше 1к не нужно тратить (однако все равно надо ставить 8k что бы выронить по странице памяти 64х системы). Если вы хабрахабр, я бы поставил 8k (меньше чем значение по умолчанию), потому что там пишут комментарии часто выходящие за 1k, но в среднем меньше чем 8к (на вскидку, могу ошибаться). Что происходит, если этот параметр переполняется читать в документации.
- large_client_header_buffers — я уменьшил тем самым сровняв с тем, что может принять остальная часть системы — apache+php.
- worker_processes — рабочих процессов поставил по количеству ядер / 2.
- worker_priority — поставил выше всех, что бы весь остальной бэкенд не тормозил отдачу сформированного контента.
- server_tokens off; — не надо светить тем, что у тебя стоит =), можно попасть в беду.
- proxy_read_timeout — я увеличил, до 300 + 20 секунд. Это чуть чуть больше чем timeout apache, который происходит через 300+10 секунд. Так сделано, что бы timeout происходил «из глубин» бэкенда, а не обрывался по непонятным причинам фронтендом. По умолчанию этот параметр 60 секунд, что порой бывает мало для тяжелых вычислений. Замечу, что php в такой конфигурации может выполняться до 300 секунд, до начала чреды таймаутов.
- Прошу обратить внимание на директивы proxy_set_header — в файле proxy_params: они используются для того что бы установить заголовки для проксированного сервера. В частности проксированный сервер не видит какой IP адрес к нему обратился, потому что считает что к нему обращается локальный 127:0:0:1
- Проксирую я на локальный порт 127.0.0.1:88, честно пытался найти сокеты либо костыли на основе них, но не получилось =(
Backend: настройка apache
Теперь приступим к настройке apache. Вот очередная пачка сгруппированных конфигурационных файлов: yadi.sk/d/ZqsisoDl0nzrl
В файлах апача я подписал каждый параметр, скопировав его из документации, что бы было удобнее настраивать. Опять же я отправляю вас к документации для настройки для ваших потребностей и расскажу про ключевые вещи:
- файл ports.conf: прослушиваем порты 88 и 443.
- дополнительно устанавливаем libapache2-mod-rpaf (уже сделали выше). Он служит для того, что бы расшифровывать заголовки, которые передает нам проксирующий сервер. Да те самые заголовки, которые мы устанавливали директивой proxy_set_header.
- DeflateCompressionLevel 1 (файл /mods-enabled/deflate.conf) в defline я установил степень сжатия = 1, я решил сильно не жать. В любом случае, если у вас есть лишние рабочие руки на сервере, то почему бы не 9-ть?.
- Я активировал модуль mod_headers и в файле conf.d/security зарезал некоторые заголовки для безопасности, для хостов висящих на 443-м порте. Подробности в конфигах. Не знаю зачем я этот порт оставил не проксированным, но это факт. Просто руки что-то не дошли, либо я побоялся, а потом уже руки не долшли. В любом случае обычным смертным запрещено к нему обращаться. Кстати с апачи версии >= 2.2.21 эту проблему решили специальной настройкой на уровне ядра.
- ServerTokens Prod, ServerSignature Off — опять же не светим вкусными местами.
- В файле secutiry в секции directory я описал максимально много разных настроек, что бы было меньше словоблудия в файлах виртульных хостов.
- TimeOut 310 — уже писал почему 310 секунд.
- RLimitMEM — интересная штука, советую почитать. Позволяет ограничивать память которую потребляет апач в целом. Так же интересны другие R* параметры
- DefaultType application/octet-stream — если мы не знаем что отдаем, то пускай это будут бинарники.
- AddDefaultCharset Off — лучше не включать, если вы не уверены в том, что у вас все в одной кодировке
С тем на что нужно обратить внимание я закончил. Теперь давайте перейдем к рассмотрению mpm-itk модуля выбранного для выполнения задач на
Дело в том, что данный модуль удобен тем, что при каждом новом обращении к серверу создается новый процесс и он переключается на определенного пользователя, допустим на www-ru-example. То есть этот пользователь «запирается» в своем каталоге и никакие скрипты никуда попасть не смогут, при учете того что вы правильно настроили операционную систему. Замечу, что многие файлы настроек по умолчанию в debian открыты для чтения для всех!!!..
Интересна история этого MPM. Дело в том, что он был сделан на основе mpm prefork, это означает, что все настройки для prefork действуют и на itk. Соответственно в моем конфигурационном файле вы это можете прослеживать.
Прошу обратить внимание на MaxClients 150, эти те самые максимальные 150 пользователей, которые могут быть при обращении к бэкенду. Так же прошу обратить внимание MaxRequestsPerChild. По умолчанию он равен нулю. Советуется устанавливать его хотя бы ограниченным — это уменьшает возможность утечки памяти.
Еще одна важная вещь в mpm-itk это nice value. Это значение я установил равным -2. Я сделал именно так, потому что как только БД отдала результат, PHP должен моментально его до конца сформировать и отдать. Прошу заметить иерархию nice-value.
nginx = -5, apache = -2, mysql = 0. Это сделано для того, что бы максимально быстро формировать контент и отдавать пользователю. Операционная система должна вытеснить не приоритетные процессы на потом.
Хотелось бы сказать пару слов о базовой защите апачи.
Есть несколько типов атак, которые должен знать любой сисадмин: killapache.pl, slow post, slow lori. Все эти атаки очень просто производятся на открытый апач. От killapache.pl спасает mod_headers или nginx, где можно закрыть проблему запретив определенные заголовки. Говорят что killapache.pl это проблема самого протокола. slow post, slow lori это идентичные атаки, одна делается при передаче большого POST, с очень медленным каналом, другая делается передачей сгенерированного контента к клиенту очень медленным каналом. Эти атаки не страшны для сильного мускулистого и жилистого сервера nginx, которым мы прикрылись. Для апача это смертно подобно, например песочница PHP чистится после того как сервер отдал все данные, теперь представьте сколько можно сожрать памяти.
В конце хочу сказать, что в конфигурационных файлах я прислал просто файлы. Не забывайте создавать симулинки в частности для каталогов mods-enabled из mods-available, sites-* и др.
Спасибо за прочтение, надеюсь понравилась моя подборка конфигов. Многие другие вещи я попробую осветить в других топиках. Например настройка бэкенда (php — mysql) и расчет возможностей сервера. Если первая и вторая статья будет интересна, то я могу выкатить еще 2 статьи: «система учета пользователей», «опыт касательно выбора железа начального уровня», «разное про работу на сервере». В финале я могу разработать набор утилит для быстрой настройки сервера по указанным мною статьям.
Автор: wartur