1

Suhosin (кор. 수호신 — «ангел-хранитель») — патч для PHP с открытым исходным кодом, выпущенный под лицензией PHP, предназначенный для повышения защиты сервера от действий злоумышленника. Включён по умолчанию в состав PHP в некоторых дистрибутивах Linux, а также в Mac OS X Server. Используется на серверах проекта One Laptop Per Child, домашней странице Ubuntu и Википедии. Также в репозитории Ubuntu имеется пакет php5-suhosin, позволяющий включить дополнительные возможности, помимо базовых, которые у Ubuntu уже имеются в php5 и php5-fpm.

Вебсерверы подвержены атакам злоумышленников. Как решить эту проблему и обезапасить сайт. Можно просканировать сайт специальными програмами на предмет грубых ошибок в настройке безопасности сайта. А так же правильно настроить сервера, PHP и базы данных.
По возможности каждому виртуальному хосту должна быть включена опция open_basedir ограничивающая скриптам каждого конкретного сайта доступ только к папке администратора этого сайта. Скрипты не должны ходить дальше вашего каталога на сервере!

Патч PHP — Suhosin поможет избавиться от целого ряда проблем в приложениях и ядре PHP.
Разработчики Suhosin open sourse приложения ставят своей задачей защитить сервер от таких атак как: PHP Include, SQL Injection, Cross site scripting (XSS) и других атак направленных на веб-сервисы. Полный список возможностей приведен на сайте разработчика Suhosin: http://www.hardened-php.net/suhosin/a_feature_list.html.
Вот не полный список возможностей плагина Suhosin:

  • добавлены функции sha256 ( ) , sha256_file () и поддержка blowfish для всех платформ;
  • кодирование Cookies и данных сессии;
  • запрещение вставки URL, закачки файлов и доступа к произвольным файлам, верификация загруженных файлов через внешний скрипт, запрет загрузки — исполняемых файлов, удаление двоичных данных из загружаемого файла;
  • отключение функции eval (), запуск приложений с использованием eval () с применением белого и черного списков;
  • принудительная установка максимальной глубины рекурсии;
  • поддержка виртуальных узлов и каталогов, настраиваемых через черный и белый списки;
  • защита от прерывания HTTP-заголовка (HTTP Response Splitting);
  • защита глобальных переменных от ex t rac t и import_request_vars, а также от скриптов, манипулирующих memory_limit;
  • защита от длинных и неправильных идентификаторов сессии;
  • фильтрование ASCII-символов;
  • игнорирование переменных GET, POST, COOKIE с целым рядом параметров;
  • установка лимитов ряду переменных REQUEST.

Установка Suhosin на Ubuntu:

apt-get install php5-suhosin

После установки файл конфигурации suhosin.ini должен располагаться в /etc/php5/conf.d.

Настройка Suhosin

Все настройки Suhosin производятся в файле php.ini или в /etc/php5/conf.d/suhosin.ini в зависимости от дистрибутива ОС.

Отключить логи:

suhosin.log.syslog = off

Отключить suhosin через .htaccess:

php_flag suhosin.simulation 1

В этом мануале мы попробуем настроить связку nginx и php-fpm, так чтобы она могла работать на бесплатном тарифе. В уме мы держим, что в результате на этом сервере будет бежать drupal (весьма требовательный к ресурсам движок), но настройки подойдут и для массы других cms.
Надо сказать, что львиная доля этого how-to — это перепечатка (естественно с согласия авторов) статьи на [url=http://nixclub.pro/node/31]nixclub.pro[/url] Евгения Верещагина и Александра Кубашина, поскольку они написали, ну буквально про нас и написали хорошо.
Перед началом рекомендуем минимально настроить сервер с помощью [url=http://forum.serverscamp.com/viewtopic.php?f=14&t=202]этого[/url] руководства.
Далее текст перепечатки:
0.0 Введение (или зачем эта статья)
В Сети очень много руководств по настройке отдельных частей и компонентов web-серверов, а вот вменяемого описания по настройке web-сервера от А до Я найти достаточно сложно. Данная статья является описанием нашего опыта по установке и настройке веб-сервера при ограниченном числе ресурсов.
0.1 Что имеем:
Сервер в минимальной VPS-конфигурации: 5Gb HDD, 256Mb RAM.
Debian Squeeze, в качестве системы.
Желание поднять на этом «железе» сервер, на котором будет крутиться сайт под управлением Drupal 7.
В перспективе иметь возможность поднять ещё несколько виртуальных доменов.
0.2 Почему не Apache...
Apache является самым популярным сервером в современной Сети. Он имеет огромное число возможностей, много дополнительных модулей и кучу документации по настройке. Но невероятная гибкость Apache приводит к тому, что его грамотная настройка требует большого опыта (а поддержка web-серверов не является нашей профессиональной деятельностью), к тому же он весьма требователен к ресурсам, а мы в них очень ограничены.
0.3 Наш выбор
В качестве решения для нашего сайта мы выбрали связку из Nginx и PHP-FPM. Если очень коротко и не совсем точно, то первый является «лёгким» http-сервером, а второй тем, кто будет обрабатывать php-скрипты.
1.0 Поехали!
Найти пакет php5-fpm в официальных репозиториях Debian Squeeze не выйдет, нет его и в Backports. Зато есть очень достойный репозиторий на dotdeb.org, им мы и воспользуемся.
Прим. artleg: если вы воспользовались руководством про первоначальную настройку, то у вас уже добавлен этот репозиторий и ключ к нему.
1.1 Подключение репозитория
Добавляем информацию о репозитории в систему
echo «deb http://packages.dotdeb.org squeeze all» > /etc/apt/sources.list.d/dotdeb.list
Импортируем ключ
wget http://www.dotdeb.org/dotdeb.gpg
cat dotdeb.gpg | apt-key add —
Обновляем список пакетов
apt-get update
1.2 Установка основных пакетов
Прим. artleg: перед установкой рекомендуется убить процесс apache2, который запускается при каждом рестарте сервера (дефолтный конфиг openvz, который пока не переделан).
killall apache2
apt-get install nginx php5-cli php5-common php5-suhosin php5-cgi php5-fpm mysql-server php5-mysql php5-gd
Последние 3 нужны именно для Drupal (впрочем, и для большинства других сайтов).
Прим. artleg: поскольку на serverscamp.com к каждому тарифу предоставляется доступ и к mysql-серверу, то рекомендую исключить mysql-server в целях облегчения оптимизации и экономии ресурсов.
1.3 Создание каталога для сайтов и установка прав
Все наши сайты физически будут находится в каталоге /var/www, который в случае отсутсвия нужно создать командой:
mkdir /var/www
Кроме того необходимо дать права на изменение этих файлов веб-серверу, точнее пользователю от которого он запущен (в Debian Nginx запускается от пользователя www-data). Команды по изменению владельца и установки соответствующих прав можно объединить в одну строку:
chmod -R a-rwx,u+rwX,g+rX /var/www && chown www-data:www-data -R /var/www
После загрузки и распаковки движка, дополнений или обновлений необходимо выполнить эти команды повторно.
На этом разминка закончилась, переходим непосредственно к настройке.
2.0 Настройка Nginx
Несмотря на то, что конфигурация Nginx состоит из нескольких файлов, сам nginx начинает читать единственный файл: /etc/nginx/nginx.conf, все остальные подключаются директивой include. С него и начнём:
2.1 /etc/nginx.conf
Прим. artleg: у вас путь до конфига будет /etc/nginx/nginx.conf
Большинство настроек (не все) повторяют конфиг, поставляемый с nginx, а наиболее интересные моменты снабжены комментариями.
user www-data;
# Рекомендуется устанавливать по числу ядер
worker_processes 1;
pid /var/run/nginx.pid;
# Директива уменьшает разрешение времени в рабочих процессах, за счёт чего уменьшается число системных вызовов gettimeofday ().
timer_resolution 100ms;
worker_rlimit_nofile 8192;
error_log /var/log/nginx/error.log;
events {
# Максимальное число подключений к серверу на один worker-процесс
worker_connections 1024;
# Эффективный метод обработки соединений, используемый в Linux 2.6+
use epoll;
}
http {
##
# Базовые настройки
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65; #Прим.  часто имеет смысл уменьшить это значение, я выставляю 5
types_hash_max_size 2048;
# При ошибках не говорим врагу версию nginx
server_tokens off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# Настройка логов
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Настройки сжатия
##
gzip on;
gzip_disable «msie6»;
##
# Настройка виртуальных доменов
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
2.1 Настройка виртуального домена
Прим. artleg: Рекомендуется просто ознакомиться с пунктом 2.1 данного руководства, а сделать по пункту 2.2 (см. ниже).
В стиле Debian все файлы настройки виртуальных доменов создаются в каталоге /etc/nginx/sites-available, а для того, чтобы этот домен активизировать нужно просто создать символическую ссылку на этот файл в каталоге /etc/nginx/sites-enable. Мы советуем не отходить от этой практики.
В качестве примера будем использовать домен test.nixclub.ru:
# Настрока редиректов c url вида http://foo.test.nixclub.ru/bar на url http://test.nixclub.ru/bar
server {
listen 80;
server_name *.test.nixclub.pro;
rewrite ^(.*)$ http://test.nixclub.pro$1 permanent;
}
# Настройка виртуального домена:
server {
##
# Уникальные настройки для домена
##
server_name test.nixclub.pro;
# Папка с контентом сайта (удобно, когда совпадает с именем домена)
root /var/www/test.nixclub.pro;
# Настройка логов, каждому виртуальному домену — свой лог
access_log /var/log/nginx/test.nixclub.pro-access.log;
error_log /var/log/nginx/test.nixclub.pro-error.log;
##
# Типовые настройки общие для всех доменов (если не захочется экзотики)
##
listen 80;
index index.php;
# Реализуем «красивые» ссылки для Drupal (и для ряда других CMS)
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
# Передаём обработку PHP-скриптов PHP-FPM
location ~ .php$ {
# Соединение по TCP.
fastcgi_pass 127.0.0.1:9000;
# На виртуальных хостингах VPS (OpenVZ, etc) полезно соединяться через сокет
# так как число TCP соединений может быть ограничено.
# (пример натройки php-fpm через сокет есть в разделе 3.5)
#Прим. artleg: на serverscamp.com сокет следует располагать внутри папки /var/www что также будет полезно при настройке chroot php-fpm (см. ниже)
# fastcgi_pass unix:/tmp/newpool.sock;
fastcgi_index index.php;
fastcgi_intercept_errors on; # только на период тестирования
# Включаем параметры из /etc/nginx/fastcgi_param
include fastcgi_params;
# Путь к скрипту, который будет передан в php-fpm
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_ignore_client_abort off;
}
# Закрываем доступ к файлами .htaccess и .htpassword
location ~ /.ht {
deny all;
}
}
2.2 Шаблоны сайтов в nginx
Когда доменов становится много и почти все их параметры копируют друг друга, то начинаешь задумываться: а нельзя ли вынести повторяющиеся моменты в отдельный файл. Особенно остро необходимость в этом встаёт, когда нужно внести однотипные изменения сразу в десяток конфигурационных файлов.
Чтобы решить эту проблему мы изначально поделили настойки на две части: уникальную для домена и типовую, общую для «большинства». Типовую часть можно вынести в файл /etc/nginx/templates/drupal (или любой другой, на Ваш вкус) и подключать её директивой include.
При таком подходе конфигурация домена будет выглядеть так:
server {
listen 80;
server_name *.test.nixclub.pro;
rewrite ^(.*)$ http://test.nixclub.pro$1 permanent;
}
server {
listen 80;
server_name test.nixclub.pro;
# Папка с контентом сайта (удобно, когда совпадает с именем домена)
root /var/www/test.nixclub.pro;
# Настройка логов, каждому виртуальному домену — свой лог
access_log /var/log/nginx/test.nixclub.pro-access.log;
error_log /var/log/nginx/test.nixclub.pro-error.log;
# Подключаем шаблон
include /etc/nginx/templates/drupal;
}
А сам файл шаблона (/etc/nginx/templates/drupal) будет содержать следующие строки:
index index.php;
# Реализуем «красивые» ссылки для Drupal (и для ряда других CMS)
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
# Передаём обработку PHP-скриптов PHP-FPM
location ~ .php$ {
# Соединение по TCP.
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_intercept_errors on; # только на период тестирования
# Включаем параметры из /etc/nginx/fastcgi_param
include fastcgi_params;
# Путь к скрипту, который будет передан в php-fpm
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_ignore_client_abort off;
}
# Закрываем доступ к файлами .htaccess и .htpassword
location ~ /.ht {
deny all;
}
2.3 Применение новых параметров
После изменения настроек nginx необходимо выполнить команду:
service nginx reload
При этом работа сайта ни на мгновение не останавливается, а если допущена синтаксическая ошибка, то nginx сообщит об этом и продолжит работать с предыдущей (корректной) конфигурацией.
2.4 Проверка работоспособности
Хотя подробная настройка PHP-FPM описана в следующем разделе, настроек по умолчанию вполне достаточно для проверки работы его связки с Nginx. Для этого мы создадим файл checkalive.php в корневом каталоге сайта (в нашем случае это /var/www/test.nixclub.pro/) следующего содержания:
<?php phpinfo (); ?>
И если конфигурация корректна, то при обращении к данному скрипту из веб-браузера (в нашем случае: http://test.nixclub.pro/checkalive.php) должна отобразится информация о текущих настройках PHP. Наличие этого скрипта на сервере является небезопасным, поэтому сразу после тестирования его лучше удалить!
Прим. artleg: Если при переходе на http://test.nixclub.pro/checkalive.php вас встречает весёлая надпись «Welcome to nginx», то добавьте в каталог /var/www/test.nixclub.pro пустой файл index.php, перейдите по адресу http://test.nixclub.pro/, а потом уже на http://test.nixclub.pro/checkalive.php
2.5 .htaccess !
В Nginx нет никакого аналога апачевского .htaccess, поэтому если работа сайта требует его наличия, то придётся переписывать его содержание в соответствии с синтаксисом nginx в основную конфигурацию домена. В нашем конфиге .htaccess был заменён следующим блоком:
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
3.0 Настройка PHP-FPM
Конфигурация PHP-FPM в Debian разбита на две части: глобальную (/etc/php5/fpm/php-fpm.conf) и настройки для так называемых пулов (/etc/php5/fpm/pool.d/*.conf). Глобальные настройки мы трогать не будем, а вот настройки для пулов обсудим достаточно подробно.
3.1 Пулы
Для начала разберёмся зачем нужны пулы. В случае разных требований сайтов к PHP-окружению (различные параметры php.ini, разное число обработчиков и т.д.) может потребоваться создание дополнительных пулов. Данная операция в PHP-FPM весьма тривиально:
Настройка каждого пула в Debian представлена своим файлом в каталоге /etc/php5/fpm/pool.d/. По умолчанию системе есть единственный пул «www» (файл: /etc/php5/fpm/pool.d/www.conf) именно его настройкой мы и займёмся.
3.2 Workers (обработчики)
Самая спорная часть в настройке пула, это количество обработчиков php-скриптов. На первый взгляд, кажется, что чем больше обработчиков, тем эффективней обрабатываются php-скрипты. Но это не так! Во-первых: большое число обработчиков расходует больше памяти (а для нашего сервера память весьма критичный ресурс), во-вторых: если обработчиков очень много и, так случилось, что все они реально заняты работой, то у сервера может просто не хватить ресурсов на другие задачи (даже есть вероятность, что подключение по SSH станет практически не возможным).
Из личного опыта: на сайте с ~200 посетителями в сутки, среднее число обработчиков за единицу времени существенно меньше 1. В идеале число обработчиков должно быть таким, что даже при стрессовой нагрузке LoadAvarage системы оставался в разумных пределах. Т.е. пусть лучше при высокой нагрузке пользователи периодически получают сообщения о недоступности сервиса (ошибка 502: Gateway timeout), чем полная недоступность сервера даже для администратора.
В результате тестирования (о тестировании будет написано дальше) были выбраны следующие параметры:
# Выбираем динамический режим создания процессов, т.е.
# число запущенных процессов PHP-FPM будет зависеть от текущей нагрузки
pm = dynamic
# Максимальное количество дочерних процессов.
pm.max_children = 7
# Количество дочерних процессов, стартующих сразу при загрузке сервера. Т.к. время запуска каждого
# нового процесса отлично от нулевого, то выбираем значение больше 1, не смотря на экономию ресурсов
pm.start_servers = 3
# Минимальное чисто простаивающих процессов. Должен согласовываться по логике с предыдущими
# при экономии ресурсов будет удобно pm.start_servers = pm.min_spare_servers.
pm.min_spare_servers = 3
# Максимальное чисто простаивающих процессов. Естественно, что не более чем pm.max_children
# и не менее pm.min_spare_servers. Остальные будут выгружены.
pm.max_spare_servers = 4
Считать эти параметры «серебрянной пулей» ни в коем случае нельзя! Оптимальное число обработчиков зависит от ресурсов сервера, сложности php-скриптов, нагрузки, создаваемой на mysql-сервер и т.д. В любом случае оптимальное число обработчиков нужно подбирать на основе тестирования работы сайта.
Для запуска первого сайта на nginx данных настроек достаточно, далее идёт описание «продвинутых» возможностей PHP-FPM, некорректное использование которых может привести к «поломке» web-сервера.
3.3 Slowlog
Очень полезно знать какие скрипты выполняются слишком долго и почему так происходит. Для помощи в решении этой проблемы в php-fpm есть следующие два параметра:
# Если скрипт будет выполняться больше указанного времени, то отладочная информация по нему будет записана в файл «медленных» запросов
request_slowlog_timeout = 3s
# Определяет путь к файлу «медленных» запросов (обязательный параметр, в случае определения request_slowlog_timeout)
slowlog = /var/log/php-slow.log
3.4 Chroot
PHP-FPM имеет очень полезную, с точки зрения безопасности, возможность: выполнение скриптов в chroot окружении. Активация данной функции производится одноимённым параметром, для примера:
# Устанавливаем chroot окружение в каталоге /var/www
chroot = /var/www
Эта единственная и достаточная настройка php-fpm для chroot. Но работа в chroot вносит свои коррективы во всё, что связано с обработкой скриптов:
Во-первых, все пути php (error_log, sessions.save_path и т.д.) теперь будут относительными от директории /var/www.
Во-вторых, php-скрипты не смогут обращаться к unix-сокетам находящимися за пределами этого каталога, т.е. обращение к mysql теперь нужно делать через tcp соединение (в качестве адреса сервера нужно указывать 127.0.0.1, но не localhost!).
В третьих, не будет доступа к программам находящимися за пределами chroot. Если для отправки почты использовался /usr/sbin/sendmail, то придётся переводить работу скриптов на протокол smtp.
Теперь вернёмся к Nginx и обратим внимание на следующие строки внутри location ~ .php$:
# Путь к скрипту, который будет передан в php-fpm
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
Пока php-скрипты выполнялись вне chroot окружения значение переменной $document_root (равна значению директивы root для текущего запроса) для php и статического контента совпадало (было равно /var/www/test.nixclub.pro), но после изменения настроек требуется корректировка данного параметра:
# Путь к скрипту в случае использования chroot
fastcgi_param SCRIPT_FILENAME /test.nixclub.pro$fastcgi_script_name;
Т.е. нам просто нужно «укоротить» путь на значение chroot, другими словами, убрать из начала пути /var/www.
3.5 Добавление пула
При увеличении числа обслуживаемых сайтов может понадобиться создание дополнительных пулов, для настройки различных параметров каждому сайту — своё. Данная операция в php-fpm, на наш взгляд, весьма тривиальна:
Нужно скопировать файл /etc/php5/fpm/pool.d/www.conf под новым именем (для примера назовём его newpool.conf)
Дать новому пулу имя: находим вверху нового файла строку [www] (имя первого пула) и меняем на [newpool]
Меняем адрес подключения к php-fpm (директива «listen»). Т.к. каждый адрес должен быть уникален, то нужно изменить:
listen = 127.0.0.1:9000
на
listen = 127.0.0.1:9001
Или, в случае использования unix-сокетов,
listen = /tmp/newpool.sock
Номера портов и путей к unix-сокетам во всех пулах должны быть разными!
3.6 Применение параметров
Для применения параметров после изменения php.ini (для PHP-FPM полный путь к файлу выглядит так: /etc/php5/fpm/php.ini) или собственных настроек PHP-FPM требуется перезапуск сервиса, при этом выполнение php-скриптов приостанавливается (на небольшой период времени).
Перезапуск производится следующей командой:
service php5-fpm restart
4.0 Немного об оптимизации
Грамотная оптимизация сервера требует наличия десятка сертификатов, нескольких тонн прочитанной литературы, огромного практического опыта и, конечно, правильной фазы луны. И это почти правда 🙂
Далее мы будем заниматься «простой» оптимизацией, польза от которой, тем не менее, тоже весьма заметна.
4.1 MySQL
Первое, что рекомендуют при оптимизации любой БД в Unix системах, это включение опции noatime для раздела с данными БД. При этом отключается запись информации о последнем обращении к файлам. Эту опцию нужно прописать в файл /etc/fstab в качестве параметра монтирования ФС. Для применения данного параметра без перезагрузки системы достаточно выполнить команду:
mount -o remount <точка монтирования раздела>
Далее выполним оптимизацию таблиц mysql, это делается следующей командой:
mysqloptimize --analyze --all-databases -u root -p
Информацию по приведённым параметрам можно (точнее нужно) посмотреть в справке по программе (man mysqloptimize).
Следующим шагом будет использование утилиты MySQLTuner. Она входит в основной репозиторий Debian, поэтому её установка весьма тривиальна:
apt-get install mysqltuner
Официальная документация рекомендует работу сервера хотя бы сутки, под типичной для него нагрузкой, перед использованием утилиты. А т.к. для достижения максимального эффекта нам придётся многократно запускать эту утилиту, то вместо суточного ожидания мы будем использовать короткое стресс-тестирование (подробное описание нагрузочного тестирования дано ниже).
При запуске утилиты будут запрошены логин и пароль администратора mysql, после чего будет выдан краткий анализ работы MySQL и набор параметров, которые рекомендуют добавить в конфигурацию сервера (/etc/mysql/my.cnf). После изменения параметров необходим перезапуск mysql:
service mysql restart
Наш алгоритм использования этой утилиты выглядит следующим образом:
Запускаем нагрузочное тестирования web-сервера (запоминаем результаты)
Запускаем mysqltuner.
Изменяем параметры mysql в соответствии с рекомендациями утилиты.
Перезапускаем mysql.
Возвращаемся к 1-му пункту. Цикл нужно повторять до тех пор пока не закончатся рекомендации mysqltuner (чуть подробее описано ниже).
Очень часто mysqltuner при каждой итерации рекомендует увеличение одного и того же параметра (каждый раз на большее значение), причём даже после нескольких изменений подряд улучшения работы сервера нет (смотрите результаты стресс-тестирования). При этом нам известны два варианта: первый — параметр ещё не достиг значения при котором почувствуется эффект от его изменения (тут нужно просто набраться терпения и пройти ещё несколько итераций) и второй — эффект от данного параметра может и будет, но у нас просто не хватит на это ресурсов (т.е. если при очередной итерации Вам советуют выделить под какой-то параметр память сравнимую с общим объёмом в системе, а результата после этого всё равно нет, то нужно просто откатится на разумное значение этого параметра).
По нашему опыту: подбор верных параметров может увеличить общую производительность web-сервера в несколько раз!
Хотя данный набор советов весьма эффективен (как минимум для нас), но он не отменяет изучения официальной (и околоофициальной) документации по работе и оптимизации mysql сервера.
4.2 PHP-APC
Один из самых простых способов ускорения выполнения php-скриптов, это установка php-акселератора. Есть несколько весьма известных программ этого типа, но мы остановили наш выбор на php-apc (во-первых: у нас есть опыт работы с ним, во-вторых: он есть в репозитории).
Установка:
apt-get install php-apc
service php5-fpm restart
Уже после этих двух команд скорость выполнения php-скриптов должна возрасти, но при этом PHP-APC имеет более 30 параметров для настройки, грамотный подбор которых сможет ещё больше повысить производительность Вашей системы.
4.3 Swap
Прим. artleg: на ovz серверах, которым является наш «atom» этот номер не пройдёт.
Хостер пожертвовал нам 128Mb виртуальной памяти, но нам этого явно не достаточно (сервер просто переставал отвечать при тестировании под нагрузкой), поэтому добавим ещё 512Mb:
dd if=/dev/zero of=/swapfile bs=1M count=512
mkswap /swapfile
swapon /swapfile
echo '/swapfile swap swap defaults 0 0' >> /etc/fstab
Если предыдущие советы рекомендуются к использованию на всех системах, то данный раздел больше применим при жёстком дефиците ресурсов.
5.0 Нагрузочное тестирование
Само по себе стресс-тестирование нам просто скажет какую максимальную нагрузку сможет выдержать сервер при текущих настройках, но нам этого не достаточно. Наша задача включает поиск «узких» мест в работе системы: какая именно программа наиболее активно использует процессор, достаточно ли памяти, не взлетел ли LoadAvarage (если Вы до сих пор не знаете, что это такое, то самое время обратится в Google).
5.1 Необходимое ПО
Во-первых, нам нужна сама утилита для нагрузочного тестирования веб-серверов. Мы остановили наш выбор на siege — это простой и при этом очень мощный инструмент. Во-вторых, нам нужна программа, отображающая текущую загрузку системы, для этих целей мы будем использовать htop (это более продвинутый вариант классической утилиты top).
Обе программы есть в стандартном репозитории, следовательно установка выглядит так:
apt-get install siege htop
5.2 htop
Интерфейс htop очень прост: Верхняя часть поделена на две зоны: слева отображается загрузка ядер CPU, использование памяти и swap, справа: информация по числу процессов, LoadAvarage (за 1, 5 и 15 минут) и общий uptime системы. В нижней части список процессов с наиболее полезной информацией по ним (использование CPU, памяти и т.д.).
При работе с программой удобнее всего включить сортировку процессов по утилизации CPU (наиболее «жадные» сверху) и всё время обращать внимание, на соотношение использования CPU и текущего LoadAvarage.
Для примера: если загрузка процессора далека от максимальной, память ещё не заканчивается, но при этом LoadAvarage через чур высок, то, скорее всего, узким местом является обращение к жёсткому диску (а в связке nginx+php+mysql именно последний наиболее активно его использует). Следовательно в этом случае нужно обратить больше внимания настройке mysql.
5.3 Siege
Для начала краткое описание опций программы, которые мы будем использовать:
-с <число> — число одновременно запускаемых запросов;
-f <файл> — файл содержащий набор ссылок, по которым будет обращаться программа во время тестирования;
-i — режим «internet», в этом режиме программ случайно выбирает адреса для запросов, список адресов задаётся параметром -f;
-b — режим «benchmark», все тесты при этом запускаются без пауз;
-t — время тестирования.
Перевод документации на русский можно найти здесь: http://habrahabr.ru/blogs/webdev/65128/ .
В простейшем случае тестирование можно запустить так:
siege <url>
При этом в несколько потоков будет обращение к одному единственному <url>. Такой режим хоть и имеет определённый смысл, но сильно уступает варианту, когда программа в произвольном порядке обращается к различным адресам сайта. И здесь возникает вопрос: как получить карту сайта в формате, понимаемом, siege?
Почти все CMS (drupal не исключение) имеют встроенную функцию генерации файла sitemap.xml, для того чтобы его получить достаточно воспользоваться командой:
wget http://<домен сайта>/sitemap.xml
Для преобразования этого файла в формат siege мы воспользуемся одним из рецептов доступных по этой ссылке. А именно создадим файл sitemap2list.sh следующего содержания:
#! /bin/sh
sed -r 's/<loc/n<loc/g; s!</loc>!</loc>n!g' $1 | sed -r -n '/<loc>.*?</loc>/! D; /<loc>.*?</loc>/ s!</?loc>!!g; s!s+!!g; P'
Не забываем установить права на исполнение:
chmod 755 sitemap2list.sh
После этого преобразование выполняется следующей командой:
./sitemap2list.sh sitemap.xml > usrl.txt
Файл urls.txt получен, теперь можно запускать само тестирование:
siege -i -b -f urls.txt
5.4 Подбор числа обработчиков php-fpm
При подборе параметров мы воспользовались следующим методом (возможно это даже наше know-how):
Устанавливаем для php-fpm в качестве максимального числа обработчиков (параметр pm.max_children) заведомо большое значение, мы использовали 20.
Производим набор тестов следующего вида:
siege -i -b -t 1m -с <num> -f urls.txt
При каждом новом тесте мы будем увеличивать <num> на 1 (т.е. при первом тесте <num> = 1, при втором 2 и т.д.). По достижении определённого значения <num> (у нас это было 8) число обработанных запросов в секунду начнёт уменьшаться, значит нам нужно выбрать значении предыдущего тестирования (для нас это 7) в качестве максимального числа обработчиков.
5.5 Пример для MySQLTuner
Для стресс-тестирования во время настройки MySQLTuner мы пользовались следующей командой:
siege -i -b -t 2m -f urls.txt
Документация по nginx камрада Сысоева
Статья на хабре, учтите мы нашли несколько ошибок в предлагаемом конфиге
Перевод документации по siege на русский
Скрипт преобразования sitemap.xml в формат siege, так же данный блог содержит много другой полезной информации
Великий Google

Скрипт очень прост в установке и настройке. Вы можете использовать следующий набор шагов для получения симпатичных графиков со статистикой работы вашего nginx-сервера:

  • Добавьте в конфигурационный файл nginx следующий раздел location:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    http {
    ...
    server {
    listen SOME.IP.ADD.RESS;
    ...
    location /nginx_status {
    stub_status on;
    access_log   off;
    allow SOME.IP.ADD.RESS;
    deny all;
    }
    ...
    }
    ...
    }
  • Проверьте свою конфигурацию следующей командой:
    1
    2
    3
    4
    # /your/installation/sbin/nginx -t
    2006/04/29 04:24:36 [info] 31676#0: the configuration file /opt/nginx/conf/nginx.conf syntax is ok
    2006/04/29 04:24:36 [info] 31676#0: the configuration file /opt/nginx/conf/nginx.conf was tested successfully
    #
    Если вы получите сообщение о том, что директива stub_status неизвестна, то проверьте включена ли опция ----with-http_stub_status_module при компиляции nginx.
  • Если проверка конфигурации прошла успешно, перезапустите nginx и проверьте статистику:
    1
    2
    3
    4
    5
    6
    croesus:~# GET http://your-domain.com/nginx_status
    Active connections: 1492
    server accepts handled requests
    2124355 2124355 8278635
    Reading: 6 Writing: 405 Waiting: 1081
    croesus:~#
  • Скачайте скрипт генерации графиков: rrd_nginx.pl и сделайте его исполнимым:
    1
    # chmod +x rrd_nginx.pl
  • Измените настройки в файле rrd_nginx.pl, чтобы дать скрипту знать, куда складывать rrd-базу и картинки со статистикой:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/usr/bin/perl
    use RRDs;
    use LWP::UserAgent;# определите путь к базам для rrdtool
    my $rrd = '/opt/rrd';
    # определите путь к картинкам
    my $img = '/opt/rrd/html';
    # определите URL для статистики nginx
    my $URL = «http://your-domain.com/nginx_status»;
    ...
  • Последний шаг в настройке – добавление следующей команды в файл /etc/crontab и перезапуск демона cron:
    * *     * * *   root    /some/path/rrd_nginx.pl
    

Когда все приготовления будут завершены, Вы получите в каталоге $img следующие графики:

https://gist.github.com/mattrude/4362399

Выделенный Web-сервер на основе nginx – отличный способ повышения производительности Web-сайтов. В скорости обработки статического контента ему просто нет равных: он легко выдерживает несколько тысяч одновременных соединений и может быть легко оптимизирован и подогнан под любую конфигурацию. Однако? выступая в качестве фронт-энда для Apache, nginx оказывается наиболее уязвимым местом всей Web-инфраструктуры, поэтому безопасности nginx необходимо уделить особое внимание.

Эта статья – своего рода ликбез, или, если хочешь, резюме всех техник повышения безопасности nginx. В ней не будет теории, описания основ настройки Web-сервера и прочей воды. Вместо этого ты получишь исчерпывающий практический материал, описывающий все основные шаги, которые необходимо проделать для того, чтобы получить по-настоящему защищенный Web-сервер.

Установка

Пакет nginx доступен в прекомпилированном виде для любого дистрибутива. Однако собрав сервер самостоятельно, ты сможешь сделать его более компактным и надежным, а также получишь возможность изменить строку приветствия Web-сервера, чтобы отбить несмышленых скрипт-кидди.

Измени строку приветствия Web-сервера

Скачай исходники nginx, открой файл src/http/ngx_http_header_filter_module.c и найди следующие две строки:

static char ngx_http_server_string[] = "Server: nginx" CRLF;
static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;

Замени их на что-то вроде этого:

static char ngx_http_server_string[] = "Server: ][ Web Server" CRLF;
static char ngx_http_server_full_string[] = "Server: ][ Web Server" CRLF;

Удали все неиспользуемые тобой nginx-модули

Некоторая часть модулей nginx подключается к Web-серверу прямо во время компиляции, и любой из них таит в себе потенциальную опасность. Возможно, в будущем в одном из них будет найдена уязвимость, и твой сервер окажется под угрозой. Отключив ненужные модули, ты сможешь значительно снизить риск возникновения такой ситуации.

Выполни сборку с помощью следующих команд:

# ./configure --without-http_autoindex_module --without-http_ssi_module
# make

# make install

Так ты получишь nginx с заранее отключенными (и в большинстве случаев бесполезными) модулями SSI (Server Side Includes) и Autoindex. Чтобы узнать, какие модули можно безболезненно выбросить из Web-сервера, запусти скрипт configure с флагом ‘–help’.

Препарируем nginx.conf

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

Отключи показ версии сервера на всех ошибочных страницах

Добавь в файл nginx.conf строку «server_tokens off». Это заставит nginx скрывать информацию о типе и версии Web-сервера на страницах, генерируемых в ответ на ошибочный запрос клиента.

Настрой защиту от срыва стека

Добавь в секцию server следующие строки:

# vi /etc/nginx/nginx.conf

# Максимальный размер буфера для хранения тела запроса клиента
client_body_buffer_size 1K;
# Максимальный размер буфера для хранения заголовков запроса клиента
client_header_buffer_size 1k;
# Максимальный размер тела запроса клиента, прописанный в поле Content-Length заголовка. Если сервер должен поддерживать загрузку файлов, это значение необходимо увеличить
client_max_body_size 1k;
# Количество и размер буферов для чтения большого заголовка запроса клиента
large_client_header_buffers 2 1k;

Обрати внимание на директиву large_client_header_buffers. По умолчанию, для хранения строки URI nginx выделяет четыре буфера, размер каждого из которых равен размеру страницы памяти (для x86 это 4 Кб). Буферы освобождаются каждый раз, когда по окончанию обработки запроса соединение переходит в состояние keep-alive. Два буфера по 1 Кб могут хранить URI длиной только 2 Кб, что позволяет бороться с ботами и DoS-атаками.

Для повышения производительности добавь следующие строки:

# vi /etc/nginx/nginx.conf

# Таймаут при чтении тела запроса клиента
client_body_timeout 10;
# Таймаут при чтении заголовка запроса клиента
client_header_timeout 10;
# Таймаут, по истечению которого keep-alive соединение с клиентом не будет закрыто со стороны сервера
keepalive_timeout 5 5;
# Таймаут при передаче ответа клиенту
send_timeout 10;

Контролируй количество одновременных соединений

Для защиты Web-сервера от перегрузки и попыток осуществить DoS-атаку добавь в конфиг следующие строки:

# vi /etc/nginx/nginx.conf

# Описываем зону (slimits), в которой будут храниться состояния сессий. Зона размером 1 Мб может хранить около 32000 состояний, мы устанавливаем ее размер равным 5 Мб
limit_zone slimits $binary_remote_addr 5m;
# Задаем максимальное количество одновременных соединений для одной сессии. По сути, это число задает максимальное количество соединений с одного IP
limit_conn slimits 5;

Первая директива должна находиться в секции HTTP, вторая – в секции location. Когда количество соединений выйдет за пределы лимитов, клиент получит сообщение «Service unavailable» с кодом 503.

Разреши коннекты только к своему домену

Взломщики могут использовать ботов для сканирования подсетей и поиска уязвимых Web-серверов. Обычно боты просто перебирают диапазоны IP-адресов в поисках открытых 80 портов и посылают запрос HEAD для получения информации о веб-сервере (или главной странице). Ты можешь легко предотвратить такой скан, запретив обращение к серверу по IP-адресу (добавить в подсекцию location):

# vi /etc/nginx/nginx.conf

if ($host !~ ^(host.com|www.host.com)$ ) {
return 444;
}

Ограничь количество доступных методов обращения к Web-серверу

Некоторые боты используют различные методы обращения к серверу для попытки определения его типа и/или проникновения, однако в документе RFC 2616 четко сказано, что Web-сервер не обязан реализовывать их все, и неподдерживаемые методы могут просто не обрабатываться. Сегодня используемыми остаются только методы GET (запрос документа), HEAD (запрос заголовков сервера) и POST (запрос на публикацию документа), поэтому все остальные можно безболезненно отключить с помощью помещения следующих строк в секцию server конфигурационного файла:

# vi /etc/nginx/nginx.conf

if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 444;
}

Отшивай ботов

Другой способ блокирования ботов, сканеров и прочей нечисти основан на определении типа клиента (user-agent). Он не слишком эффективен, потому как большинство ботов косят под вполне легитимные браузеры, но в ряде случаев остается полезным:

# vi /etc/nginx/nginx.conf

# Блокируем менеджеры загрузки
if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
return 403;
}
# Блокируем некоторые типы ботов
if ($http_user_agent ~* msnbot|scrapbot) {
return 403;
}

Блокируй Referrer-спам

Если твой сайт публикует Web-логи в общедоступном виде, ты легко можешь стать жертвой Referrer-спама (когда спам-боты обращаются к твоему серверу, указывая в заголовке referrer – адрес рекламируемого сайта). Такой вид спама может легко испортить SEO-рейтинги интернет-страницы, поэтому его необходимо блокировать в обязательном порядке. Один из способов сделать это – занести наиболее частые слова, встречающиеся в адресах рекламируемых сайтов, в черный список.

# vi /etc/nginx/nginx.conf

# Секция server
if ( $http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen) )
{
return 403;
}

Блокируй хотлинк

Хотлинк – это включение в страницу изображения (или иного контента) с другого сайта. По сути, это воровство, потому как изображение, на которое ты потратил не один час своего свободного времени, не только свободно используется другими, но и создает нагрузку на твой Web-сервер, не приводя на него посетителей. Для борьбы с хотлинками достаточно сделать так, чтобы изображения отдавались клиенту только в том случае, если он запросил их, уже находясь на сайте (другими словами, заголовок referrer-запроса должен содержать имя твоего сайта). Добавь в секцию server конфигурационного файла nginx.conf следующие строки (host.com – это адрес твоего сайта):

# vi /etc/nginx/nginx.conf

location /images/ {
valid_referers none blocked www.host.com host.com;
if ($invalid_referer) {
return 403;
}
}

В качестве альтернативы ты можешь настроить сервер на отдачу специального баннера с сообщением о воровстве вместо запрашиваемого изображения. Для этого замени строку «return 403» на строку:

rewrite ^/images/uploads.*.(gif|jpg|jpeg|png)$ http://www.host.com/banned.jpg last

Защищай важные каталоги от посторонних

Как и любой другой Web-сервер, nginx позволяет регулировать доступ к каталогам на основе IP-адресов и паролей. Эту возможность можно использовать для закрытия некоторых частей сайта от посторонних глаз. Например, для отрезания URI от внешнего мира:

# vi /etc/nginx/nginx.conf

location /uploads/ {
# Разрешаем доступ только машинам локальной сети
allow 192.168.1.0/24;
# Отшиваем всех остальных
deny all;
}

Теперь к документам каталога uploads будут иметь доступ только пользователи локальной сети. Для установки пароля придется проделать более сложные действия. Сначала необходимо создать приватный для nginx-файл паролей и добавить в него необходимых пользователей (в качестве примера добавим пользователя admin):

# mkdir /etc/nginx/.htpasswd
 # htpasswd -c /etc/nginx/.htpasswd/passwd admin

Далее открой файл nginx.conf и впиши в него следующие строки:

# vi /etc/nginx/nginx.conf
location /admin/ {
 auth_basic "Restricted";
 auth_basic_user_file /etc/nginx/.htpasswd/passwd;
 }

Новых пользователей можно добавить с помощью следующей команды:

# htpasswd -s /etc/nginx/.htpasswd/passwd пользователь

Используй SSL

Если твой сайт работает с приватными данными пользователей, такими как номера кредитных карт, пароли от других сервисов, или же предоставляет доступ к другой важной информации, которая может стать лакомым кусочком для третьих лиц, позаботься о шифровании. Nginx хорошо работает с SSL, и этой возможностью нельзя пренебрегать.

Для настройки SSL-шифрования средствами nginx достаточно выполнить несколько простых шагов. Сначала ты должен создать сертификат с помощью следующей последовательности команд:

# cd /etc/nginx
 # openssl genrsa -des3 -out server.key 1024
 # openssl req -new -key server.key -out server.csr
 # cp server.key server.key.org
 # openssl rsa -in server.key.org -out server.key
 # openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Затем описать сертификат в конфигурационном файле nginx:

# vi /etc/nginx/nginx.conf
server {
 server_name host.com;
 listen 443;
 ssl on;
 ssl_certificate /etc/nginx/server.crt;
 ssl_certificate_key /etc/nginx/server.key;
 access_log /etc/nginx/logs/ssl.access.log;
 error_log /etc/nginx/logs/ssl.error.log;
 }

После этого можно перезагрузить Web-сервер:

# /etc/init.d/nginx reload

Естественно, без поддержки со стороны самого Web-сайта это делать бессмысленно.

Другие способы

Установи правильные значения системных переменных

Открой файл /etc/sysctl.conf и помести в него следующие строки:

# vi /etc/sysctl.conf
# Защита от smurf-атак
 net.ipv4.icmp_echo_ignore_broadcasts = 1
 # Защита от неправильных ICMP-сообщений
 net.ipv4.icmp_ignore_bogus_error_responses = 1
 # Защита от SYN-флуда
 net.ipv4.tcp_syncookies = 1
 # Запрещаем маршрутизацию от источника
 net.ipv4.conf.all.accept_source_route = 0
 net.ipv4.conf.default.accept_source_route = 0
 # Защита от спуфинга
 net.ipv4.conf.all.rp_filter = 1
 net.ipv4.conf.default.rp_filter = 1
 # Мы не маршрутизатор
 net.ipv4.ip_forward = 0
 net.ipv4.conf.all.send_redirects = 0
 net.ipv4.conf.default.send_redirects = 0
 # Включаем ExecShield
 kernel.exec-shield = 1
 kernel.randomize_va_space = 1
 # Расширяем диапазон доступных портов
 net.ipv4.ip_local_port_range = 2000 65000
 # Увеличиваем максимальный размер TCP-буферов
 net.ipv4.tcp_rmem = 4096 87380 8388608
 net.ipv4.tcp_wmem = 4096 87380 8388608
 net.core.rmem_max = 8388608
 net.core.wmem_max = 8388608
 net.core.netdev_max_backlog = 5000
 net.ipv4.tcp_window_scaling = 1

Размести корневой каталог Web-сервера на выделенном разделе

Поместив корневой каталог Web-сервера в выделенный раздел и запретив на нем размещение любых исполняемых файлов и файлов-устройств, ты обезопасишь остальную часть системы от тех, кто сможет получить доступ к корню Web-сервера. При этом запись в файле /etc/fstab должна иметь примерно такой вид:

/dev/sda5 /nginx ext4 defaults,nosuid,noexec,nodev 1 2

Помести nginx в chroot/jail-окружение

Любая современная *nix-система позволяет запереть приложение в изолированной среде исполнения. В Linux для этого можно использовать технологии KVM, Xen, OpenVZ и VServer, во FreeBSD – Jail, в Solaris – Zones. Если ни одна из этих технологий не доступна, ты можешь поместить nginx в классический chroot, который хоть и намного более хрупок, но большинство взломщиков остановить сможет.

Установи правила SELinux для защиты nginx

Хорошей альтернативой изолированным средам исполнения являются локальные системы обнаружения и предотвращения вторжений, такие как SELinux или AppArmor. Будучи правильно настроенными, они смогут предотвратить попытки взлома Web-сервера. По дефолту ни одна из них не настроена для работы в связке с nginx, однако в рамках проекта SELinuxNginx(http://sf.net/projects/selinuxnginx/) были созданы правила для SELinux, которые может использовать любой желающий. Остается только скачать и установить:

# tar -zxvf se-ngix_1_0_10.tar.gz
# cd se-ngix_1_0_10/nginx
# make
# /usr/sbin/semodule -i nginx.pp

Настрой брандмауэр

Обычно nginx устанавливают на выделенных машинах, готовых к высокой нагрузке, поэтому зачастую он остается единственным сетевым сервисом, работающим на сервере. Чтобы обезопасить сервер, достаточно создать совсем небольшой набор правил, которые будут открывать 80, 110 и 143-й порты (если, конечно, nginx должен работать еще и как IMAP/POP3-прокси) и закрывать от внешнего мира все остальное.

Ограничь количество соединений с помощью брандмауэра

Для не слишком нагруженного Web-сайта хорошей идеей будет ограничить количество попыток соединений с одного IP-адреса в минуту. Это сможет уберечь тебя от некоторых типов DoS-атак и брутфорса. В Linux это можно сделать с помощью стандартного iptables/netfilter-модуля state:

# iptables -A INPUT -p tcp --dport 80 -i eth0
 -m state --state NEW -m recent --set
 # iptables -A INPUT -p tcp --dport 80 -i eth0
 -m state --state NEW -m recent --update
 --seconds 60 --hitcount 15 -j DROP

Правила урезают лимит на количество подключений с одного IP в минуту до 15. То же можно сделать и с помощью pf:

# vi /etc/pf.conf
webserver_ip="1.1.1.1"
 table <abuse> persist
 block in quick from <abuse>
 pass in on $ext_if proto tcp to $webserver_ip
 port www flags S/SA keep state
 (max-src-conn 100, max-src-conn-rate 15/60,
 overload <abusive_ips> flush)

Кроме лимита на количество последовательных подключений (15 в минуту), данное правило устанавливает дополнительный лимит на количество одновременных подключений равный 100.

Настрой PHP

Если ты используешь nginx в связке с PHP, не забудь настроить и его. Вот как должен выглядеть конфигурационный файл /etc/php/php.ini защищенного сервера:

# vi /etc/php/php.ini

# Отключаем опасные функции
disable_functions = phpinfo, system, mail, exec
# Максимальное время исполнения скрипта
max_execution_time = 30
# Максимальное время, которое может потратить скрипт на обработку данных запроса
max_input_time = 60
# Максимальное количество памяти, выделяемое каждому скрипту
memory_limit = 8M
# Максимальный размер данных, отсылаемых скрипту с помощью метода POST
post_max_size = 8M
# Максимальный размер загружаемых файлов
upload_max_filesize = 2M
# Не показывать ошибки PHP-скриптов пользователям
display_errors = Off
# Включаем Safe Mode
safe_mode = On
# Включаем SQL Safe Mode
sql.safe_mode = On
# Позволяем выполнять внешние команды только в этом каталоге
safe_mode_exec_dir = /путь/к/защищенному/каталогу
# Защищаемся от утечки информации о PHP
expose_php = Off
# Ведем логи
log_errors = On
# Запрещаем открытие удаленных файлов
allow_url_fopen = Off

Выводы

Применив описанные в статье рекомендации, ты получишь гораздо более защищенный Web-сервер. Но имей в виду, что не все техники подойдут к твоей конфигурации. Например, защита от брутфорса, основанная на урезании размеров буферов, выделяемых nginx под обработку запросов клиентов, может привести к падению производительности, а в некоторых случаях и к сбоям в обработке запросов. Ограничение на количество подключений нанесет сильный удар по производительности даже средненагруженного Web-сайта, но принесет пользу, если страница имеет низкий поток посетителей. Всегда проверяй, как внесенные тобой изменения повлияли на производительность и общую работоспособность Web-страницы.

https://xakep.ru/2010/12/15/54168/

Небольшая заметка о том, как средствами Nginx-а закрыть доступ к файлам/папке по паролю. В nginx-е это решение не менее элегантно, чем в apache, а может и еще лучше, кому как нравится.

В конфигурационном файле, в папке, которую хотим закрыть надо только указать файл, где хранятся пароли.
Вот два примера для закрытия папки с файлами:

        location ^~ /files/ {
            root   /path/to/server;
            autoindex    on;
            autoindex_exact_size  off;
            auth_basic "Hello, please login";
            auth_basic_user_file /usr/nginx/passwords;
            access_log   /usr/nginx/logs/files.log   download;
        }

и админовской части c дополнительным ограничением по IP:

        location ^~ /admin/ {
            fastcgi_pass unix:/home/project/server.sock;
            include  conf/fastcgi.conf;
            allow 11.11.0.0/16;
            allow 22.22.22.22;
            deny all;
            auth_basic "Hello, Admin, please login";
            auth_basic_user_file /usr/nginx/adminpassword;
            access_log   /usr/nginx/logs/admin.log  main;
        }

Добавить пользователя можно с помощью стандартной утилиты от apache:

htpasswd -b passwords NewUser NewPassword

В файле запись с зашифрованным паролем имеет вид:

NewUser:P47ghZ4kloG78: Your Can Comment Here

Защиту от перебора паролей можно организовать одновременно двумя методами, основанными на использовании iptables:

  • Блокирование IP на время, если количество запросов в секунду превышает какое-либо разумное количество
  • Вести лог неудачных попыток подбора пароля и скриптом раз в минуту проверять лог и заносить IP адреса в iptables

Для первого варианта достаточно создать правила:

iptables -A INPUT -p tcp --syn --dport 80 -i eth0 -m state --state NEW
            -m recent --name bhttp --set
iptables -A INPUT -p tcp --syn --dport 80 -i eth0 -m state --state NEW
            -m recent --name bhttp --update --seconds 120
            --hitcount 360 -j DROP
iptables -A INPUT -p tcp --syn --dport 80 -i eth0 -j ACCEPT

Можно вместо DROP использовать TARPIT, чтобы усложнить жизнь ломателям 🙂

Для второго варианта надо добавить в конфиг:

        location /401.html {
            root   /usr/nginx;
            access_log   /usr/nginx/logs/denied.log  error401;
        }

Формат error401, у меня например такой:

log_format error401  '$remote_addr - $remote_user [$time_local] '
                     '$status "$request"';

Теперь все неправильные попытки будут записываться в отдельный лог, который мы можем обрабатывать по cron-у:

*/1 * * * * root /usr/nginx/parser401.pl >/dev/null 2>&1

например, таким скриптом: parser401.pl Скрипт проверяет лог, и если обнаруживает больше 4-х попыток неправильного набора пароля, блокирует этот IP.